《计算机接口技术》大作业 下载本文

模式寄存器用于设置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页