单片机读取传感器数据串口通信问题。传感器自动发送TTL数据34字节为一组;波特率9600,8数据 位,1停止位;

查看: 5075|回复: 30
传感器不停地发送多个数据,单片机接受的问题
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
原子哥,我最近自己在做一些要玩意儿,现在遇到一个问题,求指导!
我用串口给传感器发送命令,查询当前的一些信息,传感器接收到这个信息后,会给我发送4个字节的信息(HEX),传感器是连续发送的,我中断函数会不会来不及接受啊?
我做了一下几个试验:
1.我用串口调试助手,来充当传感器,也就是单片机和上位机相连,然后用JTAG在线调试,单片机发出了命令,然后我用串口调试助手模拟发出相应的4个字节,此时我是发送一个字节,然后按F10,单步执行的。执行完第一个接受中断服务函数后,再发下一个字节,一共发了4个,符合我的要求
我一下子在串口调试助手上写了四个字节,然后点击发送,只能进入中断服务函数一次,就跟仅仅发第一个字节的效果一样,单片机只接收到一个字节,这是为什么?
2.我用串口调试助手和传感器相连,给传感器发送命令,传感器给串口调试助手一下子出来了四个字节,为什么会是一下出来四个呢?这说明传感器是连续发送返回数据,如果用串口调试助手一定能跟得上,如果用mini STM32能不能跟得上?
我是这样想的啊,如果波特率是9600的话,差不多一个位0.1ms,0.1ms能对于STM32来讲时间还是比较长的,只要中断服务函数不是特别长,就没事。
我之前用串口调试助手代替传感器,与单片机相连,然后用传感器代替单片机和串口调试助手相连,这两个试验的结果就如上面所说,我用单片机和传感器相连时,居然得不到数据,波特率设置没有问题啊
感谢原子哥莅临指导!
主题帖子精华
在线时间456 小时
STM32串口中断就是一个字节中断一次,在中断函数里把收到的数据可以暂时放到一个Buffer里,可以等4个字节数据全部收完后再去处理啊。
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
回复【2楼】augustedward:
---------------------------------
我的中断服务函数,就只有将DR寄存器中的数值赋给BUFFER
主题帖子精华
在线时间456 小时
回复【3楼】guanandzhang:
---------------------------------
那给了Buffer以后,有没有buffer++;?也就是说定义一个buffer[64]数组,收到的第一个数放到buffer[0],第二个放到buffer[1]...,等4个收完以后,再进行数据处理?
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
a722afaff5c36f112b875a_768.png (0 Bytes, 下载次数: 0)
22:54 上传
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
3fca337cff_661.png (0 Bytes, 下载次数: 0)
22:54 上传
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
我对四个字节的数据处理是放在主函数中的,再说了,传一个字节的数据大概是1ms,时间上执行很多指令了啊
主题帖子精华
在线时间456 小时
回复【5楼】guanandzhang:
---------------------------------
中断没问题啊!
主题帖子精华
金钱116786
在线时间891 小时
中断看你用的是我的代码,接收4个字节是完全没压力的。
怀疑你处理方式有问题。
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
我想的是,是不是传感器发送4个字节时,发送完第一个字节到开始发送第二个字节中间的间隙时间很短,根本来不及走中断,也就是说,&传感器发送完第一个字节,单片机接收到第一个字节,然后到中断服务函数,在执行中断服务函数时,第二字节就已经开始发送,由于在执行中断服务函数,所以第二个字节单片机根本就没有接收到啊?
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
原子哥,请你帮忙看一看啊
20:43 上传
点击文件名下载附件
1.08 MB, 下载次数: 386
主题帖子精华
在线时间456 小时
回复【10楼】guanandzhang:
---------------------------------
不用担心中断来不及,波特率才9600,STM32有充足的时间来进入中断并完成中断。
USART_RX_BUF[],为什么判断4.5.6.7呢,怎么不从0开始?,还有就是数据处理完后,要把USART_RX_STA清0。
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
这一部分我以前想的是,因为每次返还的数据是四个字节,我直接在每一次执行时,buffer中的i都加上4,这样不就行了吗
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
我现在只想如果我在线调试第一次能够成功,下面我再改写buffer里面的变量,我可以用指针
主题帖子精华
在线时间0 小时
回复【13楼】guanandzhang:
---------------------------------
用FIFO吧,4byte一组,一个个byte进Queue,4byte出来
很喜爱电子行业
主题帖子精华
金钱116786
在线时间891 小时
回复【13楼】guanandzhang:
---------------------------------
最好是直接清零USART_RX_STA变量。
另外,我不知道你的的传感器发送数据是不是自动的,如果是,你串口接收里面还必须做接收完成处理,也就是不能让第二次数据覆盖第一次的数据。
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
原子哥,你可以帮我看看我写的代码有问题吗,怎么就是实现不了呢
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
我的传感器发送数据是自动的,因为我用串口调试助手,完全可以实现
主题帖子精华
初级会员, 积分 78, 距离下一级还需 122 积分
在线时间0 小时
那我把&代码中的63&变成3不就可以了吗?
我想,即使覆盖了,我在线调试的第一次串口通信了,我单片机也该接收到传感器发送的数据才是啊
主题帖子精华
初级会员, 积分 51, 距离下一级还需 149 积分
在线时间2 小时
回复【楼主位】guanandzhang:
---------------------------------
你好,我也遇到和你相同的问题,就是单独测试,传感器和上位机的串口调试相连,发送询问指令时传感器可以返回数据。用单片机和上位机串口调试助手通讯,调试助手可以收到正确的指令但是把单片机和传感器连接就收不到数据,请问你是怎么解决的?
主题帖子精华
初级会员, 积分 51, 距离下一级还需 149 积分
在线时间2 小时
回复【16楼】正点原子:
回复【13楼】guanandzhang:
---------------------------------
最好是直接清零USART_RX_STA变量。
另外,我不知道你的的传感器发送数据是不是自动的,如果是,你串口接收里面还必须做接收完成处理,也就是不能让第二次数据覆盖第一次的数据。
---------------------------------
原子哥,我也遇到相同的问题,就是单独测试,传感器和上位机的串口调试相连,发送询问指令时传感器可以返回数据。用单片机和上位机串口调试助手通讯,调试助手可以收到正确的指令但是把单片机和传感器连接就收不到数据,请问怎么解决?
主题帖子精华
金钱116786
在线时间891 小时
回复【21楼】haoyun1243:
---------------------------------
检查你单片机的代码。
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子& &
主题帖子精华
初级会员, 积分 124, 距离下一级还需 76 积分
在线时间19 小时
我的传感器发送数据是自动的,因为我用串口调试助手,完全可以实现
您好!能把传感器自动发送数据,用串口接收的代码给我参考下吗?我现在自动发送速度太快,接收的数一直是原始值。非常感谢
主题帖子精华
初级会员, 积分 124, 距离下一级还需 76 积分
在线时间19 小时
您好!能把传感器自动发送数据,用串口接收的代码给我参考下吗?我现在自动发送速度太快,接收的数一直是 ...
我现在也是这种情况,求教
主题帖子精华
高级会员, 积分 917, 距离下一级还需 83 积分
在线时间47 小时
我现在也是这种情况,求教
最简单粗暴的方式,传感器的时钟是谁给的?如果是MCU控制那还不简单啊,如果不是,那让MCU时钟速度远大于传感器,怎么可能接不到
主题帖子精华
初级会员, 积分 124, 距离下一级还需 76 积分
在线时间19 小时
最简单粗暴的方式,传感器的时钟是谁给的?如果是MCU控制那还不简单啊,如果不是,那让MCU时钟速度远大于传感 ...
传感器用软件IIC&&传感器Data
on the I2C-bus can be transferred at a rate up to 100 kbit/s in
the standard-mode, or up to 400 kbit/s in the fast-mode
我软件IIC设置的GPIO速度是25-100Mhz ,&&传感器是数字输出,一秒能输出2000个,而我一秒需要采集250 个数,用串口的时候,显示接收字节数超级快。
我没太明白您说的意思
主题帖子精华
高级会员, 积分 917, 距离下一级还需 83 积分
在线时间47 小时
传感器用软件IIC&&传感器Data
on the I2C-bus can be transferred at a rate up to 100 kbit/s in
一秒需要采集250 个数,这么慢..
主题帖子精华
初级会员, 积分 124, 距离下一级还需 76 积分
在线时间19 小时
一秒需要采集250 个数,这么慢..
500个也行,可是传感器自己的采样率是2000Kz,太快,我设置了延时,串口接收字节数还是很快,读到的数都是初始值
主题帖子精华
高级会员, 积分 917, 距离下一级还需 83 积分
在线时间47 小时
SDA(串行数据线)和SCL(串行时钟线)都是双向I/O线,接口电路为开漏输出.需通过上拉电阻接电源VCC.当总线空闲时.两根线都是高电平,连接总线的外同器件都是CMOS器件,输出级也是开漏电路
看下这个做了没,而且采样频率跟输出是两码事,我虽然没用,但是我敢肯定没哪个傻逼传感器就自顾自的发数据而不管主机的
主题帖子精华
高级会员, 积分 917, 距离下一级还需 83 积分
在线时间47 小时
500个也行,可是传感器自己的采样率是2000Kz,太快,我设置了延时,串口接收字节数还是很快,读到的数都是 ...
发送到SDA 线上的每个字节必须为8 位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位(MSB),如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL 保持低电平,迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL 后数据传输继续
假设它真的自顾自的发,你看网上不也都有让它屈服的办法吗?
主题帖子精华
初级会员, 积分 124, 距离下一级还需 76 积分
在线时间19 小时
SDA(串行数据线)和SCL(串行时钟线)都是双向I/O线,接口电路为开漏输出.需通过上拉电阻接电源VCC.当总 ...
非常感谢,我试一下
Powered by 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
51单片机串口通信(相关例程)
下载积分:600
内容提示:51单片机串口通信(相关例程)
文档格式:DOC|
浏览次数:273|
上传日期: 13:42:22|
文档星级:
全文阅读已结束,如果下载本文需要使用
 600 积分
下载此文档
该用户还上传了这些文档
51单片机串口通信(相关例程)
关注微信公众号单片机C语言之串口通信协议 - CSDN博客
单片机C语言之串口通信协议
现实生活中, 我们总是要与人打交道,互通有无。单片机也一样,需要跟各种设备交互。例如汽车的显示仪表需要知道汽车的转速及电动机的运行参数,那么显示仪表就需要从汽车的底层控制器取得数据。而这个数据的获得过程就是一个通信过程。类似的例子还有控制器通常是单片机或者PLC与变频器的通信。通信的双方需要遵守一套既定的规则也称为协议,这就好比我们人之间的对话,需要在双方都遵守一套语言语法规则才有可能达成对话。
通信协议又分为硬件层协议和软件层协议。硬件层协议主要规范了物理上的连线,传输电平信号及传输的秩序等硬件性质的内容。常用的硬件协议有串口,IIC, SPI, RS485, CAN和 USB。软件层协议则更侧重上层应用的规范,比如modbus协议。
好了,那这里我们就着重介绍51单片机的串口通信协议,以下简称串口。串口的6个特征如下。
& & & & (1)、物理上的连线至少3根,分别是Tx数据发送线,Rx数据接收线,GND共用地线。
(2)、0与1的约定。RS232电平,约定﹣5V至﹣25V之间的电压信号为1,﹢5V至﹢25V之间的电压信号为0 。TTL电平,约定5V的电压信号为1,0V电压信号为0 。CMOS电平,约定3.3V的电压信号为1,0V电压信号为0 。其中,CMOS电平一般用于ARM芯片中。
(3)、发送秩序。低位先发。
(4)、波特率。收发双方共同约定的一个数据位(0或1)在数据传输线上维持的时间。也可理解为每秒可以传输的位数。常用的波特率有300bit/s, 600bit/s, 2400bit/s, 4800bit/s, 9600bit/s。
(5)、通信的起始信号。发送方在没有发送数据时,应该将Tx置1 。 当需发送时,先将Tx置0,并且保持1位的时间。接受方不断地侦测Rx,如果发现Rx常时间变高后,突然被拉低(置为0),则视为发送方将要发送数据,迅速启动自己的定时器,从而保证了收发双方定时器同步定时。
(6)、停止信号。发送方发送完最后一个有效位时,必须再将Tx保持1位的时间,即为停止位。
好了,理论暂时到这里,现在我们要做一个实验,将一个字节从51单片机发送到电脑串口调试助手上。这个实验的目的是为了掌握串口通信协议的收发过程。
实验一、虚拟串口实验
一般单片机都有专门的串口引脚,51里面分别是P3.0和P3.1,这些引脚拥有串口的硬件电路,因此使用它们并不需要设置信号的发送停止。为了掌握协议,我们使用其他的引脚来模拟串口,所以也叫虚拟串口。这里我们选用P1.0,然而注意到我们51单片机要发送数据给电脑,必须经过一个串口转USB设备(即TTL电平转换为RS232电平),而限于我们的开发板只有P3.0与P3.1连接到了串口转USB设备,所以我们可以将P1.0短接到P3.1 。 下图是这个串口转USB的原理图。
好了直接上代码吧。
#include &reg51.h&
将P1.0虚拟成串口发送脚TX
以9600bit/s的比特率向外发送数据
因为波特率是 9600bit/s
所以me发送一位的时间是 t=1000000us/us
sbit TX=P3^1; //P1^0 output TTL signal, need to transferred to rs232 signal, can be connected to P3^1
#define u16 unsigned int //宏定义
#define u8 unsigned char
void delay(u16 x)
while(x--);
void Timer0_Init()
TMOD |= 0x01;
void Isr_Init()
void Send_Byte(u8 dat)
sbuf=//通过引入全局变量sbuf,可以保存形参dat
TX=0; //A 起始位
while(ti==0);
//等待发送完成
ti=0; //清除发送完成标志
void TF0_isr() interrupt 1
//每104us进入一次中断
static u8 //记录进入中断的次数
if(i&=1 && i&=8)
if((sbuf&(1&&(i-1)))==0)
// (sbuf&(1&&(i-1)))表示取出i-1位
ti=1; //发送完成
void main()
TX=1; //使TX处于空闲状态
Timer0_Init();
Isr_Init();
Send_Byte(65); //0x41
delay(60000);
}实验引入了定时器0来控制发送线上的各个位的保持时间。首先main函数进入,TX置1则使发送线处于空闲,这时候发送方和接受方都处于空闲。接下来初始化定时器0,TR0置0表示还不要启动定时器0。接着中断系统初始化,此时中断系统已经开启。进入while循环,先进Send_Byte()函数,将65传给形参dat,dat再将65赋值给sbuf,到这里准备工作就做好了。接着TX置0,这个是起始位,要保持这个起始位104us。于是就启动定时器TR0置1,计时器开始计数。当第一次溢出的时候,也就是过了104us,进入中断,同时接收方也侦测到了这个突然被拉低的信号,于是迅速启动自己的定时器。进入中断子函数后,先是重装定时器初值,然后i加1,也就是当i=1时,就应该发送数据的最低位了,总共有8位数据,所以使用条件语句if(i&=1
&& i&=8)来判断是否发送完数据位。然后再通过if(i==9) 来发送停止位,最后当i=10时,也就是发送完了,这时候要关闭定时器(那么程序也就),同时i置0,ti置1(才能跳出while(ti==0)循环),最后将ti置0,保证下次要发送字节时让程序停留在while(ti==0)。
以上说的是虚拟串口,上文中谈到与串口相关的引脚P3.0与P3.1,事实上51单片机自带片上串口,那这个串口又该怎么使用呢?
片上串口支持同步模式与异步模式。简单来说同步模式就是指有时钟线,而异步模式无时钟线。这里的时钟线是指在同步通信时,用一根线专门传输时钟信号,这个信号用来与要发送的每一位保持同步,这样就避免了例如异步通信中因为采用定时器而引入的时间误差。
片上串口还支持8位模式和9位模式。如下图所示
其中D0-D7是一个字节的8个位。9位模式只是多了一个位TB8,这个TB8的作用是奇偶校验或多机通信。奇偶校验原理这不加分析。多机通信时比如主机只发送数据给网络中的一台地址为0x02的设备,这时候先让TB8为1,前面的D0-D7则为地址即0x02,之后再让TB8为0,前面的D0-D7则为数据了。
上面设置了片上串口的模式,另外还要设置串口的波特率。
片上串口的波特率等于定时器1工作在方式2时溢出率的32分频。如果要定时器1工作在方式2,那么TMOD=0x20。另外要保证为32分频,我们还必须设置计数器初值。设晶振为11.0592Mhz,则定时器的计数脉冲为F=f/12,则定时器每计一个脉冲的时间为T=12/f。又令计数器的起点为x,则溢出一次要计的脉冲数为(256-x)。所以在计数起点为x时,溢出一次的时间为t=12/f*(256-x)。则对应的溢出率为1/t=f/(12*(256-x))。对应的波特率就为b=f/(384*(256-x))。
x=256-f/(384*b)
其中f为晶振频率,b为希望的波特率,x为定时器的计数起点TH1的值。
例如当晶振为11.0592M,希望波特率为9600bit/s,则TH1=253。题外话,我们同样可以演算出在其他常用波特率情况下,TH1始终为一个整数。这里也就解释了为什么51里面选用了11.0592M的晶振而不是12M,这样就保证了串口的时序更加准确,虽然牺牲了定时器的准确度。
实验二,片外串口发送一个字节。
好了现在开始我们的实验之旅。直接看代码吧。
#include &reg51.h&
#define u16 unsigned int
#define u8 unsigned char
void delay(u16 x)
while(x--);
void Uart_Init() //串口初始化
SCON=0x50; //8位异步模式
TMOD|=0x20; //定时器1工作方式2
TH1=253;//9600bit/s
void Send_Byte(u8 dat)
SBUF= //启动发送,只需要把发送内容给SBUF这个寄存器
while(TI==0); //等待发送完成,因为TI为1时表示在发送停止位
void main()
Uart_Init();
Send_Byte('m');
delay(60000);
实验二较之实验一,代码减少了很多,而且不用考虑繁琐的位发送时序。只需要明白各个寄存器SCON,TMOD,TCON,SBUF的用法。TI是SCON中的第一位,为发送中断请求标志位。在本方式中,在停止位开始发送时由内部硬件置位,响应中断后TI必须又软件清零。
实验三、片上串口发送一个字符串
上面介绍了如何发送一个字节,那如何发送一个字符串甚至文本呢?这里我们首先介绍下字符串的概念。
字符串:从存储器的某个地址开始,连续存放多个字符的ASCII码,并且在最后一个字符的后面存放一个0,这段连续的内存空间就叫字符串,最后的0叫字符串的结束符。注意这里的0和加单引号的0不是一个概念,加单引号的0是指0的ASCII码。
数组与字符串的关系:字符串是数组的一种特殊情况,数组在特定条件下可当做字符串用。C语言用双引号描述一个字符串,如“abcd”。
下面我们通过一个实验来展示如何发送字符串。我们实验的目标是打印字符串“Hello World ! 第一!”到打印机。直接上代码。
#include &reg51.h&
#define u16 unsigned int
#define u8 unsigned char
void delay(u16 x)
while(x--);
void Uart_Init() //串口初始化
SCON=0x50; //8位异步模式
TMOD|=0x20; //定时器1工作方式2
TH1=253;//9600bit/s
void Send_Byte(u8 dat)
//串口发送一个字节
SBUF= //启动发送,只需要把发送内容给SBUF这个寄存器
while(TI==0); //等待发送完成,因为TI为1时表示在发送停止位
void Send_String(u8 *str)
//发送一个字符串 *str为字符串第一个字符的地址
if(*str != 0)
Send_Byte(*str);
void main()
Uart_Init();
Send_String(&Hello World! 第一!&);
Send_Byte(10);
delay(60000);
delay(60000);
这里就不再讲述代码了,如有问题,请及时联系。谢谢观看本文!转载此文请联系本人!
本文已收录于以下专栏:
相关文章推荐
本笔记是结合正点原子PPT,正点原子不完全手册,正点原子视频结合着来写的。有自己的心得,和不足的整理!...
在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体的定义形式为:
struct 结构体名{
结构体所包含的变量或数组
结构体是一种集合,它里面包含了多个变...
串口通信协议示例与分析
变频器与个人电脑使用RS-232/RS-485 串行总线连接,如下所示:
串口通信指串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。
串口通信协议(Serial communi...
1.串口通信协议拟定;
2.通信校验--CRC;
3.Linux多线程编程;
1.串口通信协议;
1.1协议拟定:
linux串口通信协议编程详解:
他的最新文章
讲师:王禹华
讲师:宋宝华
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 单片机串口通信 的文章

 

随机推荐