信息工程课程设计报告书课程名称单片微机原理与接口技术课程设计题目串口通信的计算器学生姓名、学号学生专业班级指导教师姓名课程设计起止日期2017年6月19日----6月30日一、课程设计项目名称串口通信的计算器二、项目设计目的及技术要求2.1项目设计目的通过《单片微型计算机与接口技术》课程设计,使学生能够掌握单片机的开发过程、设计方法和单片机应用电路的特点,使学生能够综合应用《单片机原理及应用》、《模拟电子技术基础》、《数字电子技术基础》等课程的知识。要求学生经过课程设计的教学环节进一步理解智能电子系统的结构和组成原理,掌握智能电子系统的基本设计方法,完成系统电路和应用程序的实践,从而使学生的电子线路设计能力、单片机机应用能力有较大提高。1)学会单片机的应用方法,开发环境;2)结合任务要求,完成系统设计和调试,功能扩展和创新;3)熟悉汇编或C51语言,用C51完成系统的软件编程;2.2项目的主要任务1)上位机串口助手发送字符串,单片机接受到后,进行字符的分解,计算出结果,显示在数码管上,并将结果发送到串口助手上显示。2)计算的+,-,X,/都可以。在除法运算中,如果除数为0,则在数码管显示0H,表示不能运算。计算出来的结果不能超过999超过,则在数码管上显示0H。3)矩阵按键的0-4四个按键分别代表+,-,X,/运算。按下按键编号为运算的键,则表示确定开始计算结果,并把结果显示在数码管上面,通过串口发送到上位机显示。同样的在第2步的要求也能实现。三、项目设计方案论证3.1实现串口通信的计算器的整体方案PC可通过串口助手软件将数据发送至单片机,单片机接收数据,通过按键立进行相应的运算,将计算结果在数码管上显示,并且将计算结果发送回PC。图3-1串口通信的计算器的整体思路3.2硬件原理图串口通信计算器主要涉及到按键、数码管、单片机的电路图。单片机STC89C52上位机串口助手按键运算串口助手数码管显示结果3.3程序设计思路主函数,串口函数、拆分函数、按键函数、计算函数、数码管函数等五部分组成。下面就是对具体函数思路的解析:图3-3程序中函数的思路图(1)串口函数:PC通过串口向单片机发送的算式是以字符串的形式发送的,故单片机程序可使用数组存放接收到的字符串。由于每次发送的算式均以“#”结尾,所以在程序中可对每次接收到的字符进行检测,若检测到“#”则接收结束,程序开始执行下一步操作。/*串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度*/voidUartWrite(unsignedchar*buf,unsignedcharlen){while(len--)//循环发送所有字节{flagTxd=0;//清零发送标志串口助手字符串的输入字符串的读取输出结果字符串拆分成num1、num2数码管显示按键扫描按键驱动操作计算结果串口助手显示SBUF=*buf++;//发送一个字节数据while(!flagTxd);//等待该字节发送完成}}/*串口中断服务函数*/voidInterruptUART()interrupt4{if(RI)//接收到新字节{RI=0;//清零接收中断标志位if(SBUF!='#'){if(cntRxdsizeof(bufRxd))//接收缓冲区尚未用完时,{//保存接收字节,并递增计数器bufRxd[cntRxd++]=SBUF;//if(bufRxd[0]=='1'){LED1=0;}//if(bufRxd[2]=='2'){LED2=0;}}}else{cntRxd=0;restopflag=1;}}if(TI)//字节发送完毕{TI=0;//清零发送中断标志位flagTxd=1;//设置字节发送完成标志}}2.拆分函数:单片机将接收到的bufRxd[]数组用strtok()函数拆分成两个字符串,再通过atoi()函数将字符串转化为整型赋值给num1、num2。//分离所接收到字符串,赋值给num1、num2voidApartUart(char*strin,int*num1,int*num2){char*ps[3];char*t=NULL;inti=0;t=strtok(strin,;);while(t!=NULL){ps[i++]=t;t=strtok(NULL,;);}*num1=atoi(ps[0]);*num2=atoi(ps[1]);}3.按键函数:矩阵按键的驱动、1ms扫描一次矩阵按键。循环检测按键的动作。for(i=0;i4;i++)//循环检测4*4的矩阵按键{for(j=0;j4;j++){if(backup[i][j]!=KeySta[i][j])//检测按键动作{if(backup[i][j]!=0)//按键按下时执行动作{//KeyAction(KeyCodeMap[i][j]);//调用按键动作函数GetResult();}backup[i][j]=KeySta[i][j];//刷新前一次的备份值}4.计算函数:按下按键编号为运算的键,计算的+,-,X,/都可以。在除法运算中,如果除数为0;在减法运算中,num1num2等情况无法显示计算结果。将计算结果在数码管上显示,无法显示计算的显示“0H”;并将计算结果发送发到串口助手上显示。voidGetResult(){if(KeySta[0][0]==0){result=num1+num2;SBUF=result;}elseif(KeySta[0][1]==0){if(num1num2){result=num1-num2;SBUF=result;}else{LedBuff[0]=0x76;LedBuff[1]=0x3f;LedBuff[2]=0x00;}}elseif(KeySta[0][2]==0){result=num1*num2;SBUF=result;}elseif(KeySta[0][3]==0){if(num2!=0){result=num1/num2;SBUF=result;}else{LedBuff[0]=0x76;LedBuff[1]=0x3f;LedBuff[2]=0x00;}}elseif(KeySta[1][0]==0){result=0;}elseif(KeySta[1][1]==0){result=num1*num1;}elseif(KeySta[1][2]==0){result=num2*num2;}}5.数码管函数:1ms中刷新一次数码管,将计算结果处理结果按十进制从高到低依次提取并转为数码管显示字符。当计算结果大于999时,无法显示计算结果,数码管显示“0H”。if(flag1s==1){flag1s=0;if(result999){LedBuff[0]=LedChar[result%10];LedBuff[1]=LedChar[result/10%10];LedBuff[2]=LedChar[result/100%10];}else{LedBuff[0]=0x76;LedBuff[1]=0x3f;LedBuff[2]=0x00;}}扩展应用:增加清零,num1的平方运算、num2的平方运算的操作elseif(KeySta[1][0]==0){result=0;}elseif(KeySta[1][1]==0){result=num1*num1;}elseif(KeySta[1][2]==0){result=num2*num2;}3.4软件程序#includereg52.h#includestdio.h#includestring.h#includestdlib.hbitflagTxd=0;//单字节发送完成标志,用来替代TXD中断标志位unsignedcharcntRxd=0;//接收字节计数器unsignedcharpdatabufRxd[20];//接收字节缓冲区sbitKEY_IN_1=P1^7;sbitKEY_IN_2=P1^6;sbitKEY_IN_3=P1^5;sbitKEY_IN_4=P1^4;sbitKEY_OUT_1=P1^3;sbitKEY_OUT_2=P1^2;sbitKEY_OUT_3=P1^1;sbitKEY_OUT_4=P1^0;//sbitLED1=P2^0;//sbitLED2=P2^1;unsignedcharpdataKeySta[4][4]={//全部矩阵按键的当前状态{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};signedintnum1=0;signedintnum2=0;signedintresult=0;sbitADDR0=P2^2;sbitADDR1=P2^3;sbitADDR2=P2^4;unsignedcharLedChar[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsignedcharLedBuff[]={0x00,0x00,0x00,0x00,0x00,0x00};unsignedcharflag1s=0;unsignedlongsec=0;unsignedcharrestopflag=0;voidConfigTimer0();voidConfigUART(unsignedintbaud);voidUartWrite();voidApartUart(char*strin,int*num1,int*num2);voidKeyDriver();voidKeyScan();voidGetResult();voidmain(){TMOD=0x01;TH0=0xFC;TL0=0x67;TR0=1;EA=1;ET0=1;ConfigUART(2400);while(1){if(restopflag==1){ApartUart(bufRxd,&num1,&num2);/*if((num1==1)&(num2==2)){result=num1+num2;LED1=0;LED2=0;}*/}KeyDriver();//调用按键驱动/*GetResult();if(result999){LcdShowStr(0,0,result);}else{LcdShowStr(0,1,0H)}*/if(flag1s==1){flag1s=0;if(result999){LedBuff[0]=LedChar[result%10];LedBuff[1]=LedChar[result/10%10];LedBuff[2]=LedChar[result/100%10];}else{LedBuff[0]=0x76;LedBuff[1]=0x3f;LedBuff[2]=0x00;}}}}//分离所接收到字符串,赋值给num1、num2voidApartUart(char*strin,int*num1,int*num2){char*ps[3];char*t=NULL;inti=0;t=strtok(strin,;);while(t!=NULL){ps[i++]=t;t=strtok(NULL,;);}*num1=atoi(ps[0]);*num2=atoi(ps[1]);}/*串口配置函数,baud-通信波特率*/voidConfigUART(unsignedintbaud){SCON=0x50;//配置串口为模式1TMOD&=0x0F;//清零T1的控制位TMOD|=0x20;//配置T1为模式2TH1=256-(12000000/12/32)/baud;//计算T1重载值TL1=TH1;//初值等于重载值ET1=0;//禁止T1中断ES=1;//使能串口中断TR1=1;//启动T1}/*串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度*/voidUartWrite(unsignedchar*buf,unsignedcharlen){while(len--)//循环发送所有字节{flag