欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > 【51单片机】7. 串口通信、单片机向电脑发送数据电脑发送数据点亮LED灯Demo

【51单片机】7. 串口通信、单片机向电脑发送数据电脑发送数据点亮LED灯Demo

2025/6/19 1:45:34 来源:https://blog.csdn.net/passer__jw767/article/details/148634311  浏览:    关键词:【51单片机】7. 串口通信、单片机向电脑发送数据电脑发送数据点亮LED灯Demo

1. 串口的定义

  • 串口成本低、易使用、通信线路简单,可实现两个设备互相通信

  • 单片机串口可以使单片机与各式各样的模块相互通信,极大扩展了单片机应用范围,增强单片机系统硬件实力

  • 51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机串口通信

2. 硬件电路

  • 简单双向串口通信有两根通信线(发送端TXD和接收端RXD)

  • TXD与RXD交叉连接

  • 仅需单项数据传输可以只接一根通信线

  • 电平标准不一致时需要加电平转换芯片

在这里插入图片描述

3. 电平标准

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用电平标准包括:

  • TTL电平:+5V表示1,0V表示0(单片机使用

  • RS232电平:-3-15V表示1,+3+15V表示0

  • RS485电平:两线压差+2+6V表示1,-2-6V表示0(差分信号)

TTL&RS232只能传10多米后错误率就很高了,RS485可以达到千米级

4. 常见通信接口

在这里插入图片描述

  • 全双工:通信双方可以在同一时刻相互传输数据

  • 半双工:通信双方可以互相传输数据,但必须分时复用一根数据线(同一时刻只能一个人发)

  • 单工:通信只能有一方发送到另一方,不能反向传输

  • 异步:通信双方各自约定通信速率

  • 同步:通信双方靠一根时钟线约定通信速率

如某一方1s传一个,但对方0.5s接收一个,就不能达成一致,同步就通过一根时钟线约定通信速率

异步就是双方各自计时,到时间了收/发

  • 总线:链接各个设备的数据传输线路(类似一条马路将多个住户连接起来,使得住户可以相互交流)

5. 串口参数及时序图

  • 波特率:串口通信速率(发送和接收各数据位间隔时间)

  • 校验位:用与数据验证

  • 停止位:用于数据帧间隔

在这里插入图片描述

9位相较而言,多出的那一位可以用于校验(奇偶校验)

6. 串口模式图

在这里插入图片描述

SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用的是相同的地址。写操作时写入发送寄存器,读操作时读出的是接收寄存器。

在这里插入图片描述

进入中断逻辑后是一个或门,只要有1个满足就会触发对应的中断

7. 串行口相关寄存器

在这里插入图片描述

  • SBUF是就是6中说的缓冲区

  • SCON是串行控制器(可位寻址),配置SM0和SM1可以控制不同工作方式:

    • 方式0:SM0=0,SM1=0;同步移位串行方式:移位寄存器

    • 方式1:SM0=0,SM1=1;8位UART,波特率可变

    • 方式2:SM0=1,SM1=0;9位UART

    • 方式3:SM0=1,SM1=1;9位UART,波特率可变

    • REN:允许/禁止串行接收控制位。REN=1允许串行接收,REN=0禁止接收

    • TI:发送中断请求标志位,在方式2中,停止位开始发送由内部硬件置位,必须使用软件复位

  • PCON是电源控制寄存器,里面的SMOD是波特率选择位

    • SMOD=1使通信方式1、2、3波特率加倍;SMOD=0各工作方式波特率加倍,复位时SMOD=0

    • SMOD0是帧错误检测有效控制位,SMOD0=1时,SCON中的SM0/FE用于帧错误检测;SMOD0=0时,SCON中的SM0/FE用于和SM1一起制定串口工作方式

8. 八位自动重载和十六位的区别

十六位记的数多,但每次都需要自己写的代码赋初值(参考定时器那一章的代码,每次溢出中断我们都需要重新给TH和TL赋初值),浪费时间。双八位就是将十六位分开,一个计数,另一个存放初值,每次计数完成后AR会自动将值赋给CNT,不用代码处理,比较快,但只有八位所以记的数少了。

串口通信设置八位自动重载,这样就不需要做手动设置了

9. 单片机通过串口向电脑发送数据

在这里插入图片描述

从波特率计算器中生成波特率设置相关的代码

接着写主代码:

#include <REGX52.H>
#include "Delay.h"unsigned char sec = 0;void UART_Init()
{SCON = 0x40;  // 模式 -> 0 1,8位UART,波特率可变PCON = 0x80;  // SMOD置1表示波特率加倍TMOD &= 0x0F;		//清除定时器1模式位TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1
}void UART_SendByte(unsigned char byteData)
{SBUF = byteData; // 填充缓冲区SBUFwhile (TI == 0) ; // 当没有到发送的时候就while等待TI = 0; // 根据规则,手动置0(手册P235)
}void main()
{UART_Init(); // 上电初始化while(1){UART_SendByte(sec); // 自动发送sec++; // sec++Delay(1000);}
}

Delay.c:

#include <INTRINS.H>void Delay(unsigned int ms)		//@11.0592MHz
{unsigned char i, j;while (ms){_nop_();i = 2;j = 199;do{while (--j);} while (--i);ms--;}
}

Delay.h:

#ifndef __DELAY_H__
#define __DELAY_H__void Delay(unsigned int ms);#endif

效果如下(见接收缓冲区数字):

(使用串口助手时,注意要选对串口,设置相同的波特率,否则会出错)

在这里插入图片描述

10. 串口代码模块化

常用代码可以直接模块化

UART.c

#include <REGX52.H>/*** @brief 串口初始化* @param 无* @retval 调用后初始化串口*/
void UART_Init() // 4800bps@11.0592MHz
{SCON = 0x40;  // 模式 -> 0 1,8位UART,波特率可变,注意,这里REN置0表示的是不接受数据,REN置1后是0x50PCON = 0x80;  // SMOD置1表示波特率加倍TMOD &= 0x0F;		//清除定时器1模式位TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1
}/*** @brief 经串口发送数据* @param byteData表示发送的数据* @retval 发送数据范围0~255*/
void UART_SendByte(unsigned char byteData)
{SBUF = byteData; // 填充缓冲区SBUFwhile (TI == 0) ; // 当没有到发送的时候就while等待TI = 0; // 根据规则,手动置0(手册P235)
}

UART.h

#ifndef __UART_H__
#define __UART_H__void UART_Init();
void UART_SendByte(unsigned char byteData);#endif

11. 电脑向单片机发送数据控制灯亮

单片机接收数据需要中断,那么在初始化时需要将中断打开,同时REN位要置1才能接收数据,UART.c修改如下,主要是改了初始化的函数:

#include <REGX52.H>/*** @brief 串口初始化* @param 无* @retval 调用后初始化串口*/
void UART_Init() // 4800bps@11.0592MHz
{SCON = 0x50;  // 模式 -> 0 1,8位UART,波特率可变,REN=1接收数据PCON = 0x80;  // SMOD置1表示波特率加倍TMOD &= 0x0F;		//清除定时器1模式位TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xF4;		//设定定时初值TH1 = 0xF4;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1// 启用接收中断ES = 1;EA = 1;
}/*** @brief 经串口发送数据* @param byteData表示发送的数据* @retval 发送数据范围0~255*/
void UART_SendByte(unsigned char byteData)
{SBUF = byteData; // 填充缓冲区SBUFwhile (TI == 0) ; // 当没有到发送的时候就while等待TI = 0; // 根据规则,手动置0(手册P235)
}

main.c中写中断的处理

#include <REGX52.H>
#include "UART.h"
#include "Delay.h"void main()
{UART_Init();while(1){}
}void UART_Rountine(void) interrupt 4
{if (RI == 1) // 因为发送和接受触发的是同一个中断,需要把发送和接收区分开{// if 是接收中断的话P2 = ~SBUF; // 点灯UART_SendByte(SBUF); // 利用发做回复RI = 0; // 该标志位需要软件置1}	
}

取反是因为低电平点灯。

效果如下:

12. 波特率计算

根据红框部分计算:

在这里插入图片描述

以江科大视频的为例,他是12MHz的晶振,选择SMOD=1(波特率倍速)。

根据软件给TH1和TL1设置的初值看:

TL1 = 0xF4;		//设定定时初值
TH1 = 0xF4;		//设定定时器重装值

F4转10进制是243,离溢出有13,即计13μs溢出一次

则溢出率是1/13μs=13MHz=0.07692MHz

又连接到÷16:0.07692/16=0.00480769MHz=4807.69Hz(12MHz的晶振有误差)

所以这个初值就是根据这个计算方式反向算出来的

13. HEX模式与文本模式

说白了文本模式就是根据你输入的16进制内容转成ASCII码

根据11的代码及ASCII码,我们将单片机回传的结果显示为文本模式,结果如下:

在这里插入图片描述

从而可以传输一些非数字的内容,同理,用电脑给单片机发字符“B”,单片机也会根据对应的16进制点灯,并回传对应的16进制内容:

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词