STC89C52单片机学习——第20节: [8-2]串口向电脑发送数据&电脑通过串口控制 ...

打印 上一主题 下一主题

主题 970|帖子 970|积分 2910

写这个文章是用来学习的,记载一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做!

     本文写于:2025.03.15   
  
  
前言

   本次条记是用来记载我的学习过程,同时把我需要的困难和思考记下来,有助于我的学习,同时也作为一种习惯,可以督促我学习,是一个鼓励自己的过程,让我们开始51单片机的学习之路。
   欢迎大家给我提意见,能给我的嵌入式之旅提供方向和门路,现在作为小白,我就先学习51单片机了,就跟着B站上的江协科技开始学习了.
   在这里会记载下江协科技51单片机开辟板的配套视频教程所作的实行和学习条记内容,由于我之前有一个开辟板,我大概率会用我的板子模拟着来做.让我们一起加油!
   另外为了增强我的学习效果:每次条记把我不知道或者问题在后面提出来,再下一篇开头作为解答!
开辟板阐明

   本人接纳的是慧净的开辟板,由于这个板子是我N年前就买的板子,索性就拿来用了。不再另外购买视频中的普中开辟板了。
   原理图如下

视频中的都用这个开辟板来实现,如果有资源就使用起来。
仔细看了看:开辟板的晶振为:11.0592Mhz;12Mhz晶振是用来给CH340G芯片外置晶振;
下图是实物图

引用

51单片机入门教程-2020版 步伐全程纯手打 从零开始入门
还参考了下图中的书籍:
手把手教你学51单片机(C语言版)

STC89C52手册

解答和科普

一、串口通讯

IO 口模拟串口通讯,让大家了解了串口通讯的本质,但是我们的单片机步伐却需要不停的检测扫描单片机IO 口收到的数据,大量占用了单片机的运行时间。在单片机内部做一个硬件模块,让它自动接收数据,接收完了,通知我们一下就可以了。
51 单片机的UART 串口的结构由串行口控制寄存器SCON、发送和接收电路三部分构成。STC89C52系列单片机内部集成有一个功能很强的全双工串行通讯口,与传统8051单片机的串口完全兼容。设有2个相互独立的接收、发送缓冲器,可以同时发送和接收数据。发送缓冲器只能写入而不能读出,接收缓冲器只能读出而不能入,因而两个缓冲器可以共用一个地点码(99H)。两个缓冲器统称串行通讯特别功能寄存器SBUF。






模式1 是最常用的,就是我们前边提到的1 位起始位,8 位数据位和1 位克制位。STC89C52 单片机来讲,这个波特率发生器只能由定时器T1 或定时器T2 产生,而不能由定时器T0 产生,这和我们模拟的通讯是完全差别的概念。如果用定时器2,需要配置额外的寄存器,默认是使用定时器1 的。 就使用定时器T1 作为波特率发生器来讲解,方式1 下的波特率发生器必须使用定时器T1 的模式2,也就是自动重装载模式,
定时器的重载值计算公式为:TH1 = TL1 = 256 - 晶振值/12 /2/16 /波特率
和波特率有关的还有一个寄存器,是一个电源管理寄存器PCON,他的最高位可以把波特率进步一倍,也就是如果写PCON |= 0x80 以后,计算公式就成了:TH1 = TL1 = 256 - 晶振值/12 /16 /波特率
公式中数字的含义这里表明一下,256 是8 位定时器的溢出值,也就是TL1 的溢出值,晶振值在我们的开辟板上就是11059200,12 是说1 个机器周期即是12 个时钟周期,值得关注的是这个16,我们来重点阐明。在IO 口模拟串口通讯接收数据的时间,采集的是这一位数据的中间位置,而实际上串口模块比我们模拟的要复杂和精确一些。他接纳的方式是把一位信号采集16 次,其中第7、8、9 次取出来, 这三次中其中两次如果是高电平,那么就认定这一位数据是1,如果两次是低电平,那么就认定这一位是0,如许一旦受到不测干扰读错一次数据,也依然可以保证最终数据的正确性。








UART 串口步伐
一般情况下,我们编写串口通讯步伐的基本步骤如下所示:
1、配置串口为模式1。
2、配置定时器T1 为模式2,即自动重装模式。
3、根据波特率计算TH1 和TL1 的初值,如果有需要可以使用PCON 进行波特率更加。
4、打开定时器控制寄存器TR1,让定时器跑起来。
这里还要特别留意一下,就是在使用T1 做波特率发生器的时间,万万不要再使能T1 的克制了。




TL1 = 0xF3; //设定定时初值 256-243=13 13us溢出一次 1/13us =0.07692MhzTH1 = 0xF3; //设定定时器重装值 256-243=13 SMOD=1 0.07692/16=0.00480769MHZ 10001000=4807.69HZ 7.69/4800=0.001602的误差。


二、串口向电脑发送数据

配置UART串口:
1、配置串口为模式1。

  1. SCON=0x40;                                                //工作模式选择1
复制代码

只改变PCON寄存器的最高位,使SMOD为1.给1的时间是不处于2的。以是我们要给1.也就是12个周期的。
  1. PCON &= 0x7F;                //波特率不倍速                               
复制代码
2、配置定时器T1 为模式2,即自动重装模式。


只操纵T1,左边的M1和M0配置。定时器1应该配置为0010.
  1. TMOD &= 0x0F;                //设置定时器模式清零
  2. TMOD |= 0x20;                //设置定时器模式置1
复制代码
3、根据波特率计算TH1 和TL1 的初值,如果有需要可以使用PCON 进行波特率更加。
  1. TL1 = 0xFD;                //设定定时初值
  2. TH1 = 0xFD;                //设定定时器重装值
复制代码
4、打开定时器控制寄存器TR1,让定时器跑起来。
这里还要特别留意一下,就是在使用T1 做波特率发生器的时间,万万不要再使能T1 的克制了。
  1. ET1 = 0;                //禁止定时器1中断
  2. TR1 = 1;                //启动定时器1
复制代码


只发给电脑不担当的代码
  1. #include <REGX52.H>
  2. /**
  3.   * @brief    串口初始化 9600bps@11.0592MHz
  4.   * @param          无
  5.   * @retval         无
  6.   */
  7. void UART_Init(void)                //9600bps@11.0592MHz
  8. {
  9.         PCON &= 0x7F;                //波特率不倍速
  10.         SCON = 0x40;                //8位数据,可变波特率
  11.        
  12.         TMOD &= 0x0F;                //清除定时器1模式位
  13.         TMOD |= 0x20;                //设定定时器1为8位自动重装方式
  14.         TL1 = 0xFD;                //设定定时初值
  15.         TH1 = 0xFD;                //设定定时器重装值
  16.         ET1 = 0;                //禁止定时器1中断
  17.         TR1 = 1;                //启动定时器1
  18. }
  19. void UART_SendByte(unsigned char Byte)
  20. {
  21.         SBUF=Byte;
  22.         while(TI==0);
  23.         TI=0;
复制代码
main.c
  1. #include <REGX52.H>
  2. #include <INTRINS.H>
  3. #include "Delay.h"
  4. #include "UART.h"
  5. unsigned char sec;
  6. void main()
  7. {
  8.         UART_Init();
  9.        
  10.         while(1)
  11.         {
  12.                 UART_SendByte(sec);
  13.                 sec++;
  14.                 Delay(1000);
  15.                
  16.         }
  17. }
复制代码
实行征象:

三、电脑通过串口控制LED(*接收和发送)

单片机接收的时间是不知道什么时间电脑会发送,以是用克制来触发。

  1. SCON = 0x50;                //8位数据,可变波特率允许接收REN
复制代码

使能克制
  1. EA=1;
  2. ES=1;                        //接收和发送都会触发中断
复制代码

前面的名称可以自己写


验证是否进入克制:
  1. void UART_Routine()   interrupt 4
  2. {
  3.         P1=0x00;
  4. }       
复制代码
  1. void UART_Routine()   interrupt 4                //发送和接受进入这同一个中断
  2. {
  3.         if(RI==1)                                //区分开是发送还是接收
  4.         {
  5.                 P1=SBUF;        //读取SBUF的值放在P1直接处理了
  6.                 RI=0;                        //必须软件清零,硬件置1
  7.         }
  8. }       
复制代码
实行征象:

     电脑通过串口发送数据控制P1口接收SBUF
  
  1. #include <REGX52.H>
  2. #include <INTRINS.H>
  3. #include "Delay.h"
  4. #include "UART.h"
  5. unsigned char sec;
  6. void main()
  7. {
  8.         UART_Init();
  9.        
  10.         while(1)
  11.         {
  12.                
  13.                
  14.         }
  15. }
  16. void UART_Routine()   interrupt 4                //发送和接受进入这同一个中断
  17. {
  18.         if(RI==1)                                //区分开是发送还是接收
  19.         {
  20.                 P1=SBUF;        //读取SBUF的值放在P1直接处理了
  21.                 UART_SendByte(SBUF);
  22.                 RI=0;                        //必须软件清零,硬件置1
  23.         }
  24. }       
复制代码
实行征象:


     发送控制单片机LED并给电脑显示
  

  1. UART_SendByte(0x30);
复制代码



问题

1、就是波特率加不加快
2、就是控制位有点多,脑筋有点乱了
3、留意配置是否正确
4、另外涉及到通讯之后和我的拓展坞会卡顿我的鼠标
总结

本节课重要学了了LED闪烁,通过延迟函数的延迟,实现了LED闪烁。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

飞不高

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表