0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

掌握串口通信协议的收发过程

GReq_mcu168 2017-12-22 10:02 次阅读

(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的原理图。

掌握串口通信协议的收发过程

好了直接上代码吧。

[cpp]view plaincopy

  1. #include"reg51.h"

  2. /*

  3. 将P1.0虚拟成串口发送脚TX

  4. 以9600bit/s的比特率向外发送数据

  5. 因为波特率是9600bit/s

  6. 所以me发送一位的时间是t=1000000us/9600=104us

  7. */

  8. sbitTX=P3^1;//P1^0outputTTLsignal,needtotransferredtors232signal,canbeconnectedtoP3^1

  9. #defineu16unsignedint//宏定义

  10. #defineu8unsignedchar

  11. u8sbuf;

  12. bitti=0;

  13. voiddelay(u16x)

  14. {

  15. while(x--);

  16. }

  17. voidTimer0_Init()

  18. {

  19. TMOD|=0x01;

  20. TH0=65440/256;

  21. TH0=65440%256;

  22. TR0=0;

  23. }

  24. voidIsr_Init()

  25. {

  26. EA=1;

  27. ET0=1;

  28. }

  29. voidSend_Byte(u8dat)

  30. {

  31. sbuf=dat;//通过引入全局变量sbuf,可以保存形参dat

  32. TX=0;//A起始位

  33. TR0=1;

  34. while(ti==0);//等待发送完成

  35. ti=0;//清除发送完成标志

  36. }

  37. voidTF0_isr()interrupt1//每104us进入一次中断

  38. {

  39. staticu8i;//记录进入中断的次数

  40. TH0=65440/256;

  41. TL0=65440%256;

  42. i++;

  43. if(i>=1&&i<=8)  

  44. {

  45. if((sbuf&(1<<(i-1)))==0)  // (sbuf&(1<<(i-1)))表示取出i-1位  

  46. {

  47. TX=0;

  48. }

  49. else

  50. {

  51. TX=1;

  52. }

  53. }

  54. if(i==9)//停止位

  55. {

  56. TX=1;

  57. }

  58. if(i==10)

  59. {

  60. TR0=0;

  61. i=0;

  62. ti=1;//发送完成

  63. }

  64. }

  65. voidmain()

  66. {

  67. TX=1;//使TX处于空闲状态

  68. Timer0_Init();

  69. Isr_Init();

  70. while(1)

  71. {

  72. Send_Byte(65);//0x41

  73. delay(60000);

  74. }

  75. }

实验引入了定时器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,这样就保证了串口的时序更加准确,虽然牺牲了定时器的准确度。

实验二,片外串口发送一个字节。

好了现在开始我们的实验之旅。直接看代码吧。

[cpp]view plaincopy

  1. #include"reg51.h"

  2. #defineu16unsignedint

  3. #defineu8unsignedchar

  4. voiddelay(u16x)

  5. {

  6. while(x--);

  7. }

  8. voidUart_Init()//串口初始化

  9. {

  10. SCON=0x50;//8位异步模式

  11. TMOD|=0x20;//定时器1工作方式2

  12. TH1=253;//9600bit/s

  13. TR1=1;

  14. }

  15. voidSend_Byte(u8dat)

  16. {

  17. SBUF=dat;//启动发送,只需要把发送内容给SBUF这个寄存器

  18. while(TI==0);//等待发送完成,因为TI为1时表示在发送停止位

  19. TI=0;

  20. }

  21. voidmain()

  22. {

  23. Uart_Init();

  24. while(1)

  25. {

  26. Send_Byte('m');

  27. delay(60000);

  28. }

  29. }

实验二较之实验一,代码减少了很多,而且不用考虑繁琐的位发送时序。只需要明白各个寄存器SCON,TMOD,TCON,SBUF的用法。TI是SCON中的第一位,为发送中断请求标志位。在本方式中,在停止位开始发送时由内部硬件置位,响应中断后TI必须又软件清零。

实验三、片上串口发送一个字符串

上面介绍了如何发送一个字节,那如何发送一个字符串甚至文本呢?这里我们首先介绍下字符串的概念。

字符串:从存储器的某个地址开始,连续存放多个字符的ASCII码,并且在最后一个字符的后面存放一个0,这段连续的内存空间就叫字符串,最后的0叫字符串的结束符。注意这里的0和加单引号的0不是一个概念,加单引号的0是指0的ASCII码。

数组与字符串的关系:字符串是数组的一种特殊情况,数组在特定条件下可当做字符串用。C语言用双引号描述一个字符串,如“abcd”。

下面我们通过一个实验来展示如何发送字符串。我们实验的目标是打印字符串“Hello World ! 第一!”到打印机。直接上代码。

[cpp]view plaincopy

  1. #include"reg51.h"

  2. #defineu16unsignedint

  3. #defineu8unsignedchar

  4. voiddelay(u16x)

  5. {

  6. while(x--);

  7. }

  8. voidUart_Init()//串口初始化

  9. {

  10. SCON=0x50;//8位异步模式

  11. TMOD|=0x20;//定时器1工作方式2

  12. TH1=253;//9600bit/s

  13. TR1=1;

  14. }

  15. voidSend_Byte(u8dat)//串口发送一个字节

  16. {

  17. SBUF=dat;//启动发送,只需要把发送内容给SBUF这个寄存器

  18. while(TI==0);//等待发送完成,因为TI为1时表示在发送停止位

  19. TI=0;

  20. }

  21. voidSend_String(u8*str)//发送一个字符串*str为字符串第一个字符的地址

  22. {

  23. abc://标号

  24. if(*str!=0)

  25. {

  26. Send_Byte(*str);

  27. str++;

  28. gotoabc;

  29. }

  30. }

  31. voidmain()

  32. {

  33. Uart_Init();

  34. while(1)

  35. {

  36. Send_String("HelloWorld!第一!");

  37. Send_Byte(10);

  38. delay(60000);

  39. delay(60000);

  40. }

  41. }


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6030

    文章

    44505

    浏览量

    632364
  • 串口通信
    +关注

    关注

    34

    文章

    1607

    浏览量

    55390

原文标题:单片机C语言之串口通信协议

文章出处:【微信号:mcu168,微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    通用异步收发传输器UART串口通信协议有哪些特性呢

    什么是通用异步收发传输器UART呢?通用异步收发传输器UART串口通信协议有哪些特性呢?
    发表于 11-01 07:03

    单线串口通信协议

    单线串口通信协议如下:需要发送的数据帧:
    发表于 12-07 08:16

    掌握通信协议的研究方法

    从根本出发,从简单开始,逐步加码,从而让你彻底掌握通信协议的研究方法。就是串口uart,因为uart只有物理层,尤其是TTL电平的uart,就是个很简单很直观的物理层协议。你可以通过学
    发表于 01-13 06:09

    Modbus通信协议的相关资料下载

    Modbus通信协议是在RS-485串口实验的基础上实现的,简单说就是首先要实现RS-485的串口通信,对所收发的数据串按照Modbus的规
    发表于 02-09 07:47

    什么是串口通信串口通信协议了解

    行传输低。2、串口通信协议在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设;STM32标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和
    发表于 02-15 06:54

    串口通信协议的相关资料分享

    一、串口通信协议简介物理层:规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。其实就是硬件部分。协议层:协议层主要规定通讯逻辑,统一
    发表于 02-17 07:36

    SPI通信协议通信过程是怎样的?

    SPI通信协议通信过程是怎样的?
    发表于 02-17 06:52

    串口通信协议的相关资料分享

    的建立三、建立STM32与PC之间的通信基础1、串口助手的使用2、效果呈现一、串口通信协议1、UART简介嵌入式开发中,UART串口
    发表于 02-22 07:16

    串口通信协议详解

    串口是计算机上一种非常通用设备通信协议。大多数计算机包含两个基于RS232的串口串口同时也是仪器仪表设备通用的
    发表于 11-09 14:51 8685次阅读

    基于状态机的串口通信协议的设计与实现

    设计并实现了一种基于状态机的串口通信协议,并将此协议应用到称重仪表的上位机通信中。本文介绍了串口通信协议
    发表于 05-08 15:22 169次下载
    基于状态机的<b class='flag-5'>串口</b><b class='flag-5'>通信协议</b>的设计与实现

    PC与单片机串口通信协议

    PC与单片机串口通信协议
    发表于 12-26 22:12 0次下载

    科尔摩根伺服驱动器串口通信协议

    科尔摩根伺服驱动器串口通信协议
    发表于 09-03 09:30 24次下载
    科尔摩根伺服驱动器<b class='flag-5'>串口</b><b class='flag-5'>通信协议</b>

    单片机C语言之串口通信协议

    本文首先介绍了串口的基本结构,其次介绍了串口通信方式,最后详细介绍了单片机C语言之串口通信协议
    发表于 05-22 12:37 4863次阅读
    单片机C语言之<b class='flag-5'>串口</b><b class='flag-5'>通信协议</b>

    西门子PLC串口协议与以太网通信协议对比

    西门子plc品牌众多,通信协议的类型就更多了,具体可分为串口协议和以太网通信协议两大类。 串口协议
    发表于 12-30 09:13 1542次阅读
    西门子PLC<b class='flag-5'>串口</b><b class='flag-5'>协议</b>与以太网<b class='flag-5'>通信协议</b>对比

    UART串口通信协议是什么?

    UART (Universal Asynchronous Receiver/Transmitter) 是一种通信接口协议,用于实现串口通信。它是一种简单的、可靠的、广泛应用的
    的头像 发表于 03-19 17:26 1222次阅读