51单片机串口如何接收多位字节数据
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
void rs232_init();
uchar flag,i,g,d;
uchar code table[]="I get ";
//sbit led=P1^0;
main()
{
rs232_init();
while(1)
{
if(flag==1)
{
ES=0;
for(i=0;i<6;i++)
{
SBUF=table[i];
while(!TI);
TI=0;
}
SBUF=g;
while(!TI);
TI=0;
SBUF=d;
while(!TI);
TI=0;
ES=1;
flag=0;
}
}
}
void rs232_init()
{
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
REN=1;
SM0=0;
SM1=1;
EA=1;
ES=1;
}
void ser()interrupt 4
{
RI=0;
g=SBUF;
d=SBUF;
flag=1;
}
我用串口调试助手调试时,上位机给单片机发送两个字节的数据,例如发送ck两个字母时,只接收到cc两个字母呢?
很久没用c语言了,研究研究先
首先数据发送是一位一位发送的,串口接收也是一位一位接收的,当接收8位数据后,申请中断。
你的程序中,程序进入中断后,你用了g=SBUF,d=SBUF,程序之所以进入中断是因为串口接收到了八位数据,是八位数据,不是十六位数据,也就是你发送的字母ck中的c,k还没有发送完呢,所以g和d都被赋值了c,打印结果当然是cc了。
你要了解串口是接收八位数据后申请中断,你必须在下一个八位数据接收完(下一次中断到来前)以前取走这个数据,不然这个数据将会丢失。
我给你改 的程序如下,我定义一个宏N,N就是你每次发送的数据个数,然后一个数组,数组有N个元素,用于存储串口接受的数据。
当串口有中断时,我立即把这个数据存储到数组中,同时将数组指针指向下一位,然后当下一个中断来时重复上面步骤,直到接收数据个数到达N。
这里中断中程序不能太长,如果程序很长,我本次数据还没存储好,下一个数据已经到了,会丢失数据。
- #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define N 2 //可一次接收数据量
- void rs232_init();
- uchar flag,i; //删除无用变量
- uchar code table[]="I get ";
- uchar table1[N]; //接收缓存数组
- uchar j=0; //接收计数器
- //sbit led=P1^0;
- main()
- {
- rs232_init();
- while(1)
- {
- if(flag==1)
- {
- ES=0;
- for(i=0;i<6;i++)
- {
- SBUF=table[i];
- while(!TI);
- TI=0;
- }
- for(j=0;j<N;j++) //发送接收数组
- {
- SBUF=table1[j];
- while(!TI);
- TI=0;
- }
- j=0; //清零接收计数器
- ES=1;
- flag=0;
- }
- }
- }
- void rs232_init()
- {
- TMOD=0x20;
- TH1=0xfd;
- TL1=0xfd;
- TR1=1;
- SM0=0;
- SM1=1;
- REN=1; //先设定号工作方式,在打开允许接收
- EA=1;
- ES=1;
- }
- void ser()interrupt 4
- {
- RI=0;
- table1[j++]=SBUF; //存数据到接收缓存
- if(j==N) //数组满时,允许发送
- flag=1;
- }
非常非常感谢你!我想了一天了也没想通
谢谢,我也受益。
谢谢,我也受益。
嗯,高手如云,一起学习,谢谢了
一起学习啊,O(∩_∩)O谢谢
楼上的高手,请问一下,用串口怎样显示从DS18B20读出的温度值呢?谢谢。
一个字节一个字节地接收,不能同时,爱收多少都可以。
用上crc16校验会更好。
谢谢小编分享11111111111111111111
好难懂啊...不过收益匪浅...
收益匪浅..收益匪浅..
你好,我按照您的程序修改了一下,把“i get”的数组重新赋值,把多位数输入进去,为什么输出的数字会不同呢(已转换ascii码)我把num的位数调到3却可以正常输出,6位就不能了
- #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define N 6 //可一次接收数据量
- void rs232_init();
- uchar flag,i,d,num;
- uint n; //删除无用变量
- uchar table[6];
- uchar table1[N]; //接收缓存数组
- uchar j=0; //接收计数器
- //sbit led=P1^0;
- main()
- {
- rs232_init();
- while(1)
- {
- // num++;
- n=100000;num=348965;
- for(i=0;i<6;i++)
- {
- d=(int)(num/n);
- num=(int)(num-n*d);
- d=(char)(d+0x30);
-
- n=n/10;
- table[i]=d;
- }
- if(flag==1)
- {
- ES=0;
- for(i=0;i<6;i++)
- {
- SBUF=table[i];
- while(!TI);
- TI=0;
- }
- for(j=0;j<N;j++) //发送接收数组
- {
- SBUF=table1[j];
- while(!TI);
- TI=0;
- }
- j=0; //清零接收计数器
- ES=1;
- flag=0;
- }
- }
- }
- void rs232_init()
- {
- TMOD=0x20;
- TH1=0xfd;
- TL1=0xfd;
- TR1=1;
- SM0=0;
- SM1=1;
- REN=1; //先设定号工作方式,在打开允许接收
- EA=1;
- ES=1;
- }
- void ser()interrupt 4
- {
- RI=0;
- table1[j++]=SBUF; //存数据到接收缓存
- if(j==N) //数组满时,允许发送
- flag=1;
- }
嗯,高手如云,一起学习,谢谢了
高人啊,你写的这个程序能接收5个字节的数据么
谢谢
想学习都应该建个微信群哈哈
一看小编就知道是个初学者,数据的定义大小不分,建议去看下char,int等的范围