找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5552|回复: 13
收起左侧

51单片机串口SBUF一次只能接收八个字节,如何连续接受长数据?

[复制链接]
ID:907024 发表于 2021-11-28 23:43 | 显示全部楼层 |阅读模式
20黑币
本帖最后由 qinkang189 于 2021-11-29 09:27 编辑

我在电脑端通过串口助手发送两个数字,例如两个16进制0102只有当前面两位为01时才执行后面的02操作(比如让数码管亮2),但我记得SBUF一次只能接收八个字节,那我怎么用串口发0102这种四个数字,并且使单片机接受呢?求大神指导,我中断到这里不会写了。

回复

使用道具 举报

ID:624769 发表于 2021-11-29 00:18 | 显示全部楼层
首先,51单片机SBUF 一次只能接受 1个字节。你要接受8个字节就必须建立缓冲池。

我不知道你的 0102是 4个字节,还是2个字节。你倒是发送 HEX还是发送 ASCII 。
具体参考这个吧: http://www.51hei.com/bbs/dpj-214784-1.html
回复

使用道具 举报

ID:907024 发表于 2021-11-29 07:24 | 显示全部楼层
188610329 发表于 2021-11-29 00:18
首先,51单片机SBUF 一次只能接受 1个字节。你要接受8个字节就必须建立缓冲池。

我不知道你的 0102是 4 ...

你好,我的意思是发送hex
回复

使用道具 举报

ID:123289 发表于 2021-11-29 08:14 | 显示全部楼层
任何单片机,一次中断只接收一个字节。
为何你认为是N个字节呢?是因为你调用了别人的函数,而别人的函数误导你了。
最佳方案:一次中断中只接收一个字节,而后就退出中断,再将下载到的字节进行处理(组字、储存、筛查……),决不要在中断服务程序中再等下一个字节。
理由:串行速度慢,串入一个字节的时间,CPU可以执行数以千计的指令,这样做太浪费CPU时间,影响其它程序的运行。
这样做你想串多少个字节是不受限制的!

回复

使用道具 举报

ID:123289 发表于 2021-11-29 08:15 | 显示全部楼层
同理,发送也一样。
回复

使用道具 举报

ID:907024 发表于 2021-11-29 08:16 来自手机 | 显示全部楼层
一次发送四个数字,hex的
回复

使用道具 举报

ID:907024 发表于 2021-11-29 08:29 来自手机 | 显示全部楼层
yzwzfyz 发表于 2021-11-29 08:14
任何单片机,一次中断只接收一个字节。
为何你认为是N个字节呢?是因为你调用了别人的函数,而别人的函数 ...

你好,意思是在主函数中处理,中断正常写吗?
回复

使用道具 举报

ID:752974 发表于 2021-11-29 08:32 | 显示全部楼层
首先概念要清楚,51单片机的UART每次只能接受8个BIT,而不是8个字节,当单片机配有串口FIFO时可以接收多个字节,但也是逐个字节接收的。具体接收方法地板说的很清楚。
回复

使用道具 举报

ID:907024 发表于 2021-11-29 09:21 来自手机 | 显示全部楼层
本帖最后由 qinkang189 于 2021-11-29 09:29 编辑

各位大佬有没有中断代码,参考一下
回复

使用道具 举报

ID:907024 发表于 2021-11-29 09:21 来自手机 | 显示全部楼层
本帖最后由 qinkang189 于 2021-11-29 09:25 编辑

这样写可以发送0102这种两个16进制的数吗  void main(void)  {  while(1)  
{  InitUART();
P0 = Receive[0];
P2 = Receive[1];
}  
}
  //中断  void UARTInterrupt(void) interrupt 4  
{
  if(RI)
{  RI = 0;
Receive[Count] = SBUF;         //用数组接收串口数据,一个BYTE。  
Count++;
if(Count == 2){Count = 0;}      //只接收两个,下次再接收覆盖。  }
回复

使用道具 举报

ID:401564 发表于 2021-11-29 13:21 | 显示全部楼层
8051单片机串口一次只能接收一个字节(8个位),不是8个字节
8051每次接收到一个字节的数据,都会进入中断,但不一定要处理数据,你只有用数组保存就可以
接收完你要接收的数据之后,再进行比对处理
你的代码是可以的,你试着用电脑的串口助手发送一下就知道了
但是,一般要考虑数据的完整性和正确性,大多采用起始帧和结束帧
回复

使用道具 举报

ID:298123 发表于 2021-11-29 13:22 | 显示全部楼层
简单点用状态机,复杂点用FIFO
回复

使用道具 举报

ID:752974 发表于 2021-11-29 16:55 | 显示全部楼层
qinkang189 发表于 2021-11-29 09:21
这样写可以发送0102这种两个16进制的数吗  void main(void)  {  while(1)  
{  InitUART();
P0 = Recei ...

这个中断服务函数写的很好,很精简。
回复

使用道具 举报

ID:624769 发表于 2021-11-29 17:31 | 显示全部楼层
qinkang189 发表于 2021-11-29 09:21
这样写可以发送0102这种两个16进制的数吗  void main(void)  {  while(1)  
{  InitUART();
P0 = Recei ...

只收两个的情况下:

Count++;
if(Count == 2){Count = 0;}      //只接收两个,下次再接收覆盖。  }

合并成:
Count ^= 0x01;  效率会高很多。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表