模式寄存器用于设置8251A工作于同步/异步方式,数据格式
控制寄存器
使8251A实现某种操作或进入规定的工作状态
第10页
状态寄存器
CPU可通过I/O读操作把8251的状态字读入CPU,用以控制CPU与8251之间的数据交换
4. 软件设计 4.1 设计思想
程序主要由按键判断、显示、定时计数以及串行口子程序构成,他们完成的功能为在显示程序处显示按键的值,并根据具体的运算得出结果值,在串行口输出屏处可以记录已经输入的值以及运算结果,而定时计数单元用于产生系统的时
第11页
间基准时间。 4.2 源程序
/****************************************************************************** ************ LABCENTER ELECTRONICS ************
************ Proteus VSM Sample Design Code ************
************ Integer Calculator ( 2K Code Limit) ************ ******************************************************************************/ #include \//Variables
static LONG lvalue; static LONG rvalue; static CHAR currtoken; static CHAR lasttoken; static CHAR lastpress;
static CHAR outputbuffer[MAX_DISPLAY_CHAR]; VOID main (VOID)
//Initialise our variables and call the
//Assembly routine to initialise the LCD display. { lvalue = 0; rvalue = 0; currtoken = '='; lasttoken = '0';
initialise(); // Initialize the LCD calc_output(OK); calc_evaluate(); }
VOID calc_evaluate() { CHAR key; INT i;
CHAR number[MAX_DISPLAY_CHAR]; CHAR *bufferptr;
// Clear the buffer before we start. for (i = 0; i <= MAX_DISPLAY_CHAR; i++) { number[i] = ' '; }
bufferptr = number; for (;;)
{ key = calc_getkey(); if (calc_testkey(key))
// Key test positive for digit so we read it into the // buffer and then write the buffer to the screen/LCD. // Size limit the number of digits - allow for termination // and possible negative results.
{ if (bufferptr != &number[MAX_DISPLAY_CHAR - 2]) { *bufferptr = key; calc_display(number);
第12页
bufferptr++; } } else
// Key is an operator so pass it to the function handlers.
// If we are just after startup or cancel then assign to lvalue // otherwise assign to rvalue. {
//Assign the value. if (lasttoken == '0')
{ lvalue = calc_asciidec (number);} else
{ rvalue = calc_asciidec (number);} //Clear the number buffer. bufferptr = number;
for (i = 0;i <= MAX_DISPLAY_CHAR; i++) { number[i] = ' '; } //Process the Operator. currtoken = key;
if (currtoken == 'C')
{ calc_opfunctions(currtoken); } else
{ calc_opfunctions(lasttoken); }
// Clear the outputbuffer for reuse on next operation. for (i = 0;i <= MAX_DISPLAY_CHAR;i++) { outputbuffer[i] = ' ';} bufferptr = number;
// Handle the equals operation here for brevity.
// All we need do is preserve the previous operator in // lasttoken.
if (currtoken != 0x3D) lasttoken = currtoken; }
lastpress = key; } }
VOID calc_opfunctions (CHAR token)
// Handle the operations. Lvalue holds the result and we test for // consecutive operator presses. { CHAR result; switch(token) // Add.
{ case '+' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{ lvalue += rvalue;
result = calc_chkerror(lvalue); } else
{ result = SLEEP; } break; // Subtract.
case '-' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
第13页
{ lvalue -= rvalue;
result = calc_chkerror(lvalue); } else
{ result = SLEEP;} break; // Multiply.
case '*' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{ lvalue *= rvalue;
result = calc_chkerror(lvalue); } else
{ result = SLEEP;} break; // Divide.
case '/' : if ((currtoken == '=' ) || ((lastpress >= 0x30) && (lastpress <=0x39)))
{ if (rvalue)
{ lvalue /= rvalue;
result = calc_chkerror(lvalue); } else
{ result = ERROR;} } else
{ result = SLEEP;} break; // Cancel.
case 'C' : lvalue = 0; rvalue = 0;
currtoken = '0'; lasttoken = '0';
result = OK; break; default : result = SLEEP; }
calc_output(result); }
/************************************************************************ ***** Utility Routines ***** ***************************/
INT calc_chkerror (LONG num)
// Check upper and lower bounds for the display. // i.e. 99999999 and -99999999.
{ if ((num >= -9999999) && (num <= 9999999)) return OK; else
return ERROR; }
VOID calc_output (INT status)
// Output according to the status of the operation.
// *Sleep* is used for the first op press after a full cancel // or on startup.
第14页