登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] UART串口通信

[复制链接]
发表于 2021-2-2 23:53:04 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 单片机
学习安排: UART串口通信
开始时间: 2021-02-01
结束时间: 2021-02-02
    串口通信是单片机最常用的一种通信技术,通常用于单片机与计算机之间以及单片机和单片机之间的通信。通信按照基本类型可以分为并行通信和串行通信。

1.png

其中单片机中就存在一个UART模块用于通信,要正确地使用它,当然还得把对应的特殊功能寄存器配置好。

51单片机地UART串口的结构由串行口控制寄存器SCON、发送和接收电路三部分构成。首先是串口控制寄存器SCON
2.png
SCON寄存器的配置与之前配置定时器有些类似,
在硬件串口模块中,有一个专门的波特率发生器用来控制发送和接收数据的速度。对于STC89单片机来说,这个波特率发生器只能由定时器T1或定时器T2产生,而不能由定时器T0产生,使用定时器T1的模式2,也就是自动重装载模式,定时器的重载值计算公式为:
  TH1 = TL1 = 256 -晶振值/12/2/16/波特率
其中12是说一个机械周期等于12个时钟周期,256是8位定时器的溢出值,串口通信接收数据的时候的采取方式是把信号采集16次,其中第7、8、9次取出来,而不是取中间值,保证最终数据的正确性。
然后串口通信的发送和接收电路在物理上有两个名字相同的SBUF寄存器,它们的地址都是0x99,但一个用来作为发送缓冲,一个用来作为接收缓冲。
   编写串口通信的基本步骤如下:
3.png
需要注意的是在使用T1做波特率发生器的时候,不要再使能T1中断了。

还有关于ASCII码的相关知识,在学习C语言的时候已经学过了。
下面是通过单片机串口调试助手发送的数据,开发板上的数码管上显示出来的代码。


  1. #include <reg52.h>

  2. sbit ADDR3 = P1^3;
  3. sbit ENLED = P1^4;

  4. unsigned char code LedChar[] = {  //数码管显示字符转换表
  5.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  6.     0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  7. };
  8. unsigned char LedBuff[7] = {  //数码管+独立LED显示缓冲区
  9.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  10. };
  11. unsigned char T0RH = 0;  //T0重载值的高字节
  12. unsigned char T0RL = 0;  //T0重载值的低字节
  13. unsigned char RxdByte = 0;  //串口接收到的字节

  14. void ConfigTimer0(unsigned int ms);
  15. void ConfigUART(unsigned int baud);

  16. void main()
  17. {
  18.     EA = 1;       //使能总中断
  19.     ENLED = 0;    //选择数码管和独立LED
  20.     ADDR3 = 1;
  21.     ConfigTimer0(1);   //配置T0定时1ms
  22.     ConfigUART(9600);  //配置波特率为9600
  23.    
  24.     while (1)
  25.     {   //将接收字节在数码管上以十六进制形式显示出来
  26.         LedBuff[0] = LedChar[RxdByte & 0x0F];
  27.         LedBuff[1] = LedChar[RxdByte >> 4];
  28.     }
  29. }
  30. /* 配置并启动T0,ms-T0定时时间 */
  31. void ConfigTimer0(unsigned int ms)
  32. {
  33.     unsigned long tmp;  //临时变量
  34.    
  35.     tmp = 11059200 / 12;      //定时器计数频率
  36.     tmp = (tmp * ms) / 1000;  //计算所需的计数值
  37.     tmp = 65536 - tmp;        //计算定时器重载值
  38.     tmp = tmp + 18;           //补偿中断响应延时造成的误差
  39.     T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节
  40.     T0RL = (unsigned char)tmp;
  41.     TMOD &= 0xF0;   //清零T0的控制位
  42.     TMOD |= 0x01;   //配置T0为模式1
  43.     TH0 = T0RH;     //加载T0重载值
  44.     TL0 = T0RL;
  45.     ET0 = 1;        //使能T0中断
  46.     TR0 = 1;        //启动T0
  47. }
  48. /* 串口配置函数,baud-通信波特率 */
  49. void ConfigUART(unsigned int baud)
  50. {
  51.     SCON  = 0x50;  //配置串口为模式1
  52.     TMOD &= 0x0F;  //清零T1的控制位
  53.     TMOD |= 0x20;  //配置T1为模式2
  54.     TH1 = 256 - (11059200/12/32)/baud;  //计算T1重载值
  55.     TL1 = TH1;     //初值等于重载值
  56.     ET1 = 0;       //禁止T1中断
  57.     ES  = 1;       //使能串口中断
  58.     TR1 = 1;       //启动T1
  59. }
  60. /* 按键扫描函数,需在定时中断中调用 */
  61. void LedScan()
  62. {
  63.     static unsigned char i = 0;  //动态扫描索引
  64.    
  65.     P0 = 0xFF;             //关闭所有段选位,显示消隐
  66.     P1 = (P1 & 0xF8) | i;  //位选索引值赋值到P1口低3位
  67.     P0 = LedBuff[i];       //缓冲区中索引位置的数据送到P0口
  68.     if (i < 6)             //索引递增循环,遍历整个缓冲区
  69.         i++;
  70.     else
  71.         i = 0;
  72. }
  73. /* T0中断服务函数,完成LED扫描 */
  74. void InterruptTimer0() interrupt 1
  75. {
  76.     TH0 = T0RH;  //重新加载重载值
  77.     TL0 = T0RL;
  78.     LedScan();   //LED扫描显示
  79. }
  80. /* UART中断服务函数 */
  81. void InterruptUART() interrupt 4
  82. {
  83.     if (RI)  //接收到字节
  84.     {
  85.         RI = 0;  //手动清零接收中断标志位
  86.         RxdByte = SBUF;  //接收到的数据保存到接收字节变量中
  87.         SBUF = RxdByte;  //接收到的数据又直接发回,叫作-"echo",
  88.                          //用以提示用户输入的信息是否已正确接收
  89.     }
  90.     if (TI)  //字节发送完毕
  91.     {
  92.         TI = 0;  //手动清零发送中断标志位
  93.     }
  94. }
复制代码



好懒~~不想说~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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