完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
最近做一个单片机的通讯程序,问题很怪!求解!
1.晶振采用12MHZ,初始化为4800的波特率,有大概0.16%误差! 2.接收采用中断接收,发送采用查询方式,放在主程序里面。 3.如果没有中断,则发送A代码,接受数据正确返回B代码,接受错误返回C代码,分别置有标志位。 4.另外还有一个定时器中断作为显示输出。 5.主程序中增加了I2C的读写程序。 目前的现象为: 在程序测试的时候,有接近一半的几率返回的数据不对,如果没有通讯中断的时候,所有返回的数据是正确的。一旦通讯中断,会返回错误的数据(错误的数据一般由A数据的一部分和B(或者C)数据的一部分组成。)如果将数据发送频率加快以后,所有数据又会恢复正常。如果硬件重新上电,则又会错误? 调试完成后DATA 115. 用的stc90C51. A,B,C发送代码放在一个数组里面。 求解! |
|
相关推荐
4个回答
|
|
错误发生了以后,采用原有的代码单独测试了通讯的接收和发送程序,不会出现错误!
但是一旦加入了其它的读写程序,则会出现问题。 是否程序占用空间太大了的原因,数据存储读取不正常了? |
|
|
|
那肯定是读写操作出错了,可能是读写时序不对 |
|
|
|
“定时器中断作为显示输出”这部分移到主程序
|
|
|
|
//---------------------------------------------------------------------------------- void main() //主程序 { value humi_val,temp_val; unsigned char num=105,num1=300; unsigned char error,checksum,n; init_uart(); //定义时钟启动 UsartConfiguration(); //串行口 s_connectionreset(); //连接复位 Delay10ms(10); TR1=1; while(1) { num=At24c02Read(2); Delay10ms(2); num1=At24c02Read(4); Delay10ms(2); if(K1==0) {Delay10ms(1); if(K1==0) num=At24c02Read(2); Delay10ms(2); num++; if(num>=70)num=70; DisplayData[0] = GPIO_DIG_CODE[10*num/1000];//千位 DisplayData[1] = GPIO_DIG_CODE[10*num%1000/100];//百位 DisplayData[2] = GPIO_DIG_CODE[10*num%1000%100/10]|0X80;//十位 加小数点程序 DisplayData[3] = GPIO_DIG_CODE[10*num%1000%100%10];//个位 At24c02Write(2,num); Delay10ms(1); } //------------------------------------------------------------------------ else if(K2==0) {Delay10ms(1); if (K2==0) num=At24c02Read(2); Delay10ms(1); num--; if(num<=20)num=20; DisplayData[0] = GPIO_DIG_CODE[10*num/1000];//千位 DisplayData[1] = GPIO_DIG_CODE[10*num%1000/100];//百位 DisplayData[2] = GPIO_DIG_CODE[10*num%1000%100/10]|0X80;//十位 加小数点程序 DisplayData[3] = GPIO_DIG_CODE[10*num%1000%100%10];//个位 At24c02Write(2,num); Delay10ms(1); } ///-------------------------------------------------------------------------------- else if(K3==0) {Delay10ms(1); if (K3==0) num1=At24c02Read(4); Delay10ms(1); num1++; if(num1>=40)num1=40; DisplayData[4] = GPIO_DIG_CODE[10*num1/1000];//千位 DisplayData[5] = GPIO_DIG_CODE[10*num1%1000/100];//百位 DisplayData[6] = GPIO_DIG_CODE[10*num1%1000%100/10]|0X80;//十位 加小数点程序 DisplayData[7] = GPIO_DIG_CODE[10*num1%1000%100%10];//个位 At24c02Write(4,num1); Delay10ms(1); } //-------------------------------------------------------------------------------------- else if(K4==0) {Delay10ms(1); if (K4==0) num1=At24c02Read(4); Delay10ms(1); num1--; if(num1<=20)num1=20; DisplayData[4] = GPIO_DIG_CODE[10*num1/1000];//千位 DisplayData[5] = GPIO_DIG_CODE[10*num1%1000/100];//百位 DisplayData[6] = GPIO_DIG_CODE[10*num1%1000%100/10]|0X80;//十位 加小数点程序 DisplayData[7] = GPIO_DIG_CODE[10*num1%1000%100%10];//个位 At24c02Write(4,num1); Delay10ms(1); } //---------------------------------------------------------------------------- else //无键盘操作时候的扫描程序 { //------------------------------------- //ES=0; error=0; //初始化error=0,即使当前没有错误 error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI); // 测量湿度 error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP); // 测量温度 if(error!=0) s_connectionreset(); //如果系统发生错误,系统连接复位 else { humi_val.f=(float)humi_val.i; // 整形数变浮点数 temp_val.f=(float)temp_val.i; // 整形数变浮点数 calc_sth11(&humi_val.f, &temp_val.f); // 修正相对湿度及温度 humi_val.f=humi_val.f*10; // 整形数变浮点数 temp_val.f=temp_val.f*10; temp_val.i=(int)temp_val.f; humi_val.i=(int)humi_val.f; DisplayData[0] = GPIO_DIG_CODE[humi_val.i/1000];//千位 DisplayData[1] = GPIO_DIG_CODE[humi_val.i%1000/100];//百位 DisplayData[2] = GPIO_DIG_CODE[humi_val.i%1000%100/10]|0X80;//十位 加小数点程序 DisplayData[3] = GPIO_DIG_CODE[humi_val.i%1000%100%10];//个位 DisplayData[4] = GPIO_DIG_CODE[temp_val.i/1000];//千位 DisplayData[5] = GPIO_DIG_CODE[temp_val.i%1000/100];//百位 DisplayData[6] = GPIO_DIG_CODE[temp_val.i%1000%100/10]|0X80;//十位 DisplayData[7] = GPIO_DIG_CODE[temp_val.i%1000%100%10]; // ES=1; } if(flag==0)//有数据过来 { outdata[34]=outdata[34]+0x01; ES=0; outdata[0]=0x55; //帧头 outdata[1]=0xAA; //帧头 outdata[2]=0x1E; //数据长度 outdata[3]=outdata[34]; //帧序号 outdata[4]=0x10; //版本号 outdata[5]=0x00; //服务器地址 outdata[6]=0x00; //服务器地址 outdata[7]=0x00; //服务器地址 outdata[8]=0x00; //服务器地址 outdata[9]=0x08; //储藏柜地址 outdata[10]=0x00; //储藏柜地址 outdata[11]=0x00; //储藏柜地址 outdata[12]=0x00; //储藏柜地址 outdata[13]=0xC1;//定时上传指令 outdata[14]=0x00; outdata[15]=0x00; outdata[16]=0x00; outdata[17]=0x00;//数据上传时间 outdata[18]=0x02; //参数总数 outdata[19]=0x21;//表示温度 outdata[20]=0x00; outdata[21]=num1; //温度设置值 outdata[22]=temp_val.i/10; //温度实际值 outdata[23]=temp_val.i%10; //温度实际值 outdata[24]=0x20;//表示湿度 outdata[25]=0x00; outdata[26]=num; //湿度设置值 outdata[27]=humi_val.i/10; outdata[28]=humi_val.i%10; //温度实际值 outdata[29]=0x00; //校验 for(n=0;n<29;n++) {outdata[29]=outdata[n]+outdata[29];} //数据发送的时候是否要把中断关闭,以免在数据发送的时候引起不必要的错误; for(n=0;n<30;n++) { SBUF = outdata[n]; while(!TI); TI = 0; } ES=1; Delay10ms(50); } else if(flag==1) {//检测数据写入是否正确 ES=0; outdata[34]=outdata[34]+0x01; flag=0; At24c02Write(2, outdata[28]); Delay10ms(1); num=At24c02Read(2); Delay10ms(1); for(n=0;n<20;n++) { outdata[n]=0X00; } if(num== outdata[28]) { ES=0; outdata[0]=0x66; //帧头 outdata[1]=0xAA; //帧头 outdata[2]=0x0F; //数据长度 outdata[3]=outdata[34]; //帧序号 outdata[4]=0x10; //版本号 outdata[5]=0x00; //服务器地址 outdata[6]=0x00; //服务器地址 outdata[7]=0x00; //服务器地址 outdata[8]=0x00; //服务器地址 outdata[9]=0x08; //储藏柜地址 outdata[10]=0x00; //储藏柜地址 outdata[11]=0x00; //储藏柜地址 outdata[12]=0x00; //储藏柜地址 outdata[13]=0x31;//定时上传指令 outdata[14]=0x00; outdata[15]=0x00; //校验 for(n=0;n<15;n++) {outdata[15]=outdata[n]+outdata[15];} //数据发送的时候是否要把中断关闭,以免在数据发送的时候引起不必要的错误; for(n=0;n<16;n++) { SBUF = outdata[n]; while(!TI); TI = 0; } //需要加入输出继电器的控制,设置控制阈值等。 ES=1; Delay10ms(50); } else { // ES=0; outdata[0]=0x77; //帧头 outdata[1]=0xAA; //帧头 outdata[2]=0x0F; //数据长度 outdata[3]=outdata[34]; //帧序号 outdata[4]=0x10; //版本号 outdata[5]=0x00; //服务器地址 outdata[6]=0x00; //服务器地址 outdata[7]=0x00; //服务器地址 outdata[8]=0x00; //服务器地址 outdata[9]=0x08; //储藏柜地址 outdata[10]=0x00; //储藏柜地址 outdata[11]=0x00; //储藏柜地址 outdata[12]=0x00; //储藏柜地址 outdata[13]=0x31;//定时上传指令 outdata[14]=0x01; outdata[15]=0x00; for(n=0;n<15;n++) {outdata[15]=outdata[n]+outdata[15];} //数据发送的时候是否要把中断关闭,以免在数据发送的时候引起不必要的错误; for(n=0;n<16;n++) { SBUF = outdata[n]; while(!TI); TI = 0; } ES=1; Delay10ms(50); } } else if(flag==2) { ES=0; outdata[34]=outdata[34]+0x01; for(n=0;n<20;n++) { outdata[n]=0X00; } flag=0; outdata[0]=0x88; //帧头 outdata[1]=0xAA; //帧头 outdata[2]=0x0F; //数据长度 outdata[3]=outdata[34]; //帧序号 outdata[4]=0x10; //版本号 outdata[5]=0x00; //服务器地址 outdata[6]=0x00; //服务器地址 outdata[7]=0x00; //服务器地址 outdata[8]=0x00; //服务器地址 outdata[9]=0x08; //储藏柜地址 outdata[10]=0x00; //储藏柜地址 outdata[11]=0x00; //储藏柜地址 outdata[12]=0x00; //储藏柜地址 outdata[13]=0x31;//定时上传指令 outdata[14]=0x01; outdata[15]=0x00; for(n=0;n<15;n++) {outdata[15]=outdata[n]+outdata[15];} //数据发送的时候是否要把中断关闭,以免在数据发送的时候引起不必要的错误; for(n=0;n<16;n++) { SBUF =outdata[n]; while(!TI); TI = 0; } ES=1; Delay10ms(50); } } //执行加湿和除湿的动作 //程序需要增加一个延时动作的功能,等待湿度稳定下来以后进行控制。 if(humi_val.i/10==num) //误差值在0.5以内的时候 ,加湿除湿停止工作 {JS=1; CS=1;} else if (humi_val.i/10>num&& humi_val.i/10-num>4) //实际湿度大于设定湿度 {JS=1; CS=0;} else if(humi_val.i/10 {JS=0; CS=1;} else {} } } // void GPIO_DIGDisplayDatalay() interrupt 1 //定时器0中断,自动重装赋值 { //定时器在工作方式二会自动重装初,所以不用在赋值。 GPIO_DIG=0; //消隐 switch(Num) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 //把这一段程序去掉以后,该数码管不显示。 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位 case(6): LSA=0;LSB=1;LSC=1; break;//显示第6位 case(7): LSA=1;LSB=1;LSC=1; break;//显示第7位 } GPIO_DIG = DisplayData[Num]; //段选,选择显示的数字。 Num++; if(Num>7) { Num=0; } } //------------------------ //--------------------------- void Usart() interrupt 4 //只判断接收标志位,如果是接收标志引起的中断时候则运行程序。 //中断里面引用其他程序,会导致程序重复导入,因此中断采集到数据以后只需要附一个数据输入标志位,放到主程序中去判断即可。 { if(RI) { RI=0; outdata[i]=SBUF; if(i==0&&outdata[i]==0x55)//判断帧头字符0X55AA { outdata[35]=outdata[35]+ outdata[i]; i=1; } else if(i==1&&outdata[i]==0xAA) //判断帧头字符 { outdata[35]=outdata[35]+outdata[i]; i=2; } else if(i>=2&&i<33) { outdata[35]=outdata[35]+ outdata[i]; //中间接收字符 i++; } else if(i==33&&outdata[i]== outdata[35]&&outdata[5]==0x08&&outdata[6]==0x00&&outdata[7]==0x00&&outdata[8]==0x00) //检测校验数据是否正确 而且地址正确 { if(outdata[24]==0x20&&outdata[28]==outdata[32]&&outdata[28]>=0x14&&outdata[28]<=0x46)//参数是否设置正确 {i=0; flag=1; //数据命令正确 ES=0; outdata[35]=0; } else {i=0; flag=2; //数据命令错误 ES=0; outdata[35]=0;} } else {i=0; outdata[35]=0;} } } //---------------------------------------------------------------------------------- void init_uart() //时钟初始化 定时器0 //---------------------------------------------------------------------------------- { TMOD=0X02; //选择为定时器模式,工作方式2,仅用TRX打开启动。 TH0=0X9C; //给定时器赋初值,定时100us TL0=0X9C; ET0=1; //打开定时器0中断允许 EA=1; //打开总中断 TR0=1; //打开定时器 } /******************************************************************************* * 函 数 名 :UsartConfiguration() * 函数功能 :设置串口 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void UsartConfiguration() //定时器1 { SCON=0X50; //设置为工作方式1 TMOD=0X22; //设置计数器工作方式2 TMOD=0X22 将定时器1的值需要重复设定 PCON=0X80; //波特率加倍 TH1=0XF3; //计数器初始值设置,注意波特率是4800的 TL1=0XF3; // ES=1; EA=1; // TR1=1; //打开计数器 } |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
690 浏览 0 评论
735 浏览 1 评论
基于瑞萨FPB-RA4E2智能床头灯项目——1编译环境搭建与点亮驱动ws2812全彩LED
624 浏览 0 评论
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-LCD显示图片编程示例之介绍mmap
1099 浏览 0 评论
《DNESP32S3使用指南-IDF版_V1.6》第二章 常用的C语言知识点
1092 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11794 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-26 07:11 , Processed in 0.649690 second(s), Total 82, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号