完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
给你按默认主动上传方式写的程序,看懂以后,其它应用方式自然就会了。
程序经TX-1C实验板验证无误。 //按默认主动上传方式的程序 //FF 17 04 00 00 25 13 88 25 #include #define uint unsigned int #define uchar unsigned char ***it dula=P2^6; //段选 ***it wela=P2^7; //位选 uchar code table[]={ //共阴数码管0~F数组 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; uchar table0[] ="OK "; //用于串口助手返回验证 uchar table1[]="ERROR ";//用于串口助手返回验证 uchar rec_buf[9]; //缓存 uint V_data; //收到的16位有效数据变量 uint swan,wan,qian,bai,shi,ge;//数码管显示位 bit flag=0; //接收完成标 /*************初始化串口**************/ void InitUART() //9600bps@11.0592MHz { PCON &= 0x7F; //波特率不倍速 SCON = 0x50; //8位数据,可变波特率 TMOD|= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFD; //设定定时初值 TH1 = 0xFD; //设定定时器重装值 TR1 = 1; //启动定时器1 ET1 = 0; //禁止定时器1中断 EA = 1; //开总中断 ES = 1; //开串口中断 } /**********串口发送函数*************/ void SendOneByte(uchar c) { SBUF = c; //发送数据 while(!TI); //等待发送完成 TI = 0; //发送中断请求标志位清0 } /*********校验和计算***********/ uchar FucCheckSum(uchar *i,uchar ln) { uchar j,tempq=0; i+=1; for(j=0;j<(ln-2);j++) { tempq+=*i; i++; } tempq=(~tempq)+1; return(tempq); } /************数据解析程序*************/ void analysis() { uchar i,j; //临时变量 if(flag==1) //如果9位数据串接收完成 { ES=0; //关串口中断 flag=0; //接收完成标志清0 j=FucCheckSum(rec_buf,9);//校验和计算 if(rec_buf[8]==j)//验证数据校验和 { V_data=(rec_buf[4]<<8)|rec_buf[5];//恢复16位有效数据(浓度值) for(i=0;i<3;i++) SendOneByte(table0[i]);//返回OK } else for(i=0;i<6;i++) SendOneByte(table1[i]);//返回ERROR ES=1; //开串口中断 } } /*************数据分解***************/ void Transformation() { swan = V_data/100000; // 十万位 wan = V_data%100000/10000; // 万位 qian = V_data%10000/1000; // 千位 bai = V_data%1000/100; // 百位 shi = V_data%100/10; // 十位 ge = V_data%10; // 个位 } /**********6位数码管显示程序************/ void display() { static uchar xx=0; //分时显示变量 switch(xx) { case 0: dula=0; P0=table[swan]; //显示十万位段码 dula=1; dula=0; wela=0; P0=0x7e; //显示十万位码 wela=1; wela=0; xx=1; break; case 1: dula=0; P0=table[wan]; //显示万位段码 dula=1; dula=0; wela=0; P0=0x7d; //显示万位位码 wela=1; wela=0; xx=2; break; case 2: P0=table[qian]; //显示千位段码 dula=1; dula=0; P0=0x7b; //显示千位位码 wela=1; wela=0; xx=3; break; case 3: P0=table[bai]; //显示百位段码 dula=1; dula=0; P0=0x77; //显示百位位码 wela=1; wela=0; xx=4; break; case 4: P0=table[shi]; //显示十位段码 dula=1; dula=0; P0=0xef; //显示十位位码 wela=1; wela=0; xx=5; break; case 5: P0=table[ge]; //显示个位段码 dula=1; dula=0; P0=0xdf; //显示个位位码 wela=1; wela=0; xx=0; break; } } /**************主程序**************/ void main() { InitUART(); //初始化串口 while(1) { analysis(); //数据解析 Transformation();//数据分解 display(); //数码管显示 } } /*********串口中断服务程序**********/ void UARTInterrupt() interrupt 4 { static uchar num=0; //静态计数变量 RI=0; //接收中断请求标志位清0 rec_buf[num]=SBUF; //接收到的数据串保存在缓存数组 if(rec_buf[0]==0xFF) //验证数据头(起始位) { num++; if(num>=9) { flag=1; //接收完成标志置1 num=0; //计数变量清0 } } }
最佳答案
|
|
|
|
|
|
通讯就是标准的串口通讯,资料里有写的,通讯协议里的16进制数是列举的例子
|
|
|
|
|
|
可能是我对串口通讯的了解还不太够,我有以下几个问题: 1.我发的图片中它说表4命令行格式,是不是指的是表4中第一个字节到第八个字节的16进制数就是我需要发送给传感器的命令?可是他不是说默认主动上传了,我为何还要发命令行给他?而且表5和6不就是切换上传方式的命令吗? 2.表7竟然是气体浓度的格式?一个气体浓度发了8个字节?表8的传感器返回值又如何解读?里面不是有气体浓度了吗? 3.到底传感器和52单片机之间是怎么通讯的?是传感器默认每1秒上传一起数据吗?上传的是什么数据?是表8吗? |
|
|
|
|
|
没人呀,dalao们快来呀
|
|
|
|
|
异世界的投影 发表于 2018-3-30 13:05 1.表4是传感器发给你的;是在主动模式下才用的 2.表7是你发给传感器的,表8是传感器发给你的,是在问答模式下用的 3.你先接上,用默认的主动模式,只要串口接收数据就行了,按照表4解析数据获得气体浓度;后面的再研究吧 |
|
|
|
|
|
楼上正解,通讯协议确定后就是固定的,但是如何应用每一个命令则是活的
|
|
|
|
|
|
感谢dalao还特意写了程序来讲解,不过这里 V_data=(rec_buf[4]<<8)|rec_buf[5];//恢复16位有效数据(浓度值) 我的意见是把它变成 rec_buf[4]*256+rec_buf[5] ?不然怎么可以算出来 |
|
|
|
|
|
我自己也根据大佬的程序仿照了一下,用的1602显示屏,但是怎么显示的还是0.00000?我的传感器坏了? #include #define uchar unsigned char #define uint unsigned int ***it rs = P0^5; //1602的数据/指令选择控制线 ***it rw = P0^6; //1602的读写控制线 ***it en = P0^7; //1602的使能控制线 /*P2口接1602的D0~D7 ***it led_2=P1^3; uchar UART_dat[9]; uint ch2o,flag; void delay( uint n ) { uint x, y; for( x=n; x>0; x-- ) for( y=112; y>0; y-- ); } void lcd_wcom( uchar com ) //1602写命令函数 { rs=0; //选择指令寄存器 rw=0; //选择写 P2=com; //把命令字送入P2 delay( 5 ); //延时一小会儿,让1602准备接收数据 en=1; //使能线电平变化,命令送入1602的8位数据口 en=0; } void lcd_wdat( uchar dat ) //1602写数据函数 { rs=1; //选择数据寄存器 rw=0; //选择写 P2=dat; //把要显示的数据送入P2 delay( 5 ); //延时一小会儿,让1602准备接收数据 en=1; //使能线电平变化,数据送入1602的8位数据口 en=0; } void lcd_wbyte(uchar *byte) //1602写字符串函数 { while(*byte!=' |

淘帖
4141