文章目录[隐藏]
第一部分_串口
一、基础知识
- 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
- 单片机的
串口
可以使单片机与单片机
、单片机与电脑
、单片机与各式各样的模块
互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。 - 51单片机内部自带
UART
(Universal Asynchronous Receiver Transmitter,通用异步
收发器)可实现单片机的串口通信。
第一个 USB转换工具 相当于
第二个 陀螺仪模块,加速度传感器
第三个 蓝牙串口
小贴士:
VGA接口,相比于 串口的接口(两排) 它有三排插、孔。【用于视频传输、电脑外接显示器】
二、硬件电路
1、介绍
- 简单
双向
串口通信有2根
通信线 (发送端 TXD 和 接收端 RXD);- 发送端 TXD,Transmit eXchange Data;
- 接收端 RXD,Receive eXchange Data。
- TXD与RXD要
交叉
连接; - 当只需
单向
的数据传输时,可以直接1根
通信线; - 当
电平标准不一致
时,需要加电平转换芯片
。
2、 电平标准
- 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
TTL电平
:+5V 表示 1, 0V 表示 0 ;(对地电压)RS232电平
:-3~-15V 表示 1, +3~+15V 表示 0;(对地电压) <反逻辑
>【距离最多十多米,否则会传输出错】RS485电平
:两线压差
+2~+6V 表示 1, -2~-6V 表示 0(差分
信号)【最多传输一千多米】
三、常见的通信接口的比较
1、比较
I^2C
和SPI
的通信方式都有同步,且都带有SCL
,即时钟线
。
1.1 相关术语
-
全双工:通信双方可以在
同一时刻互相
传输数据; -
半双工:通信双方可以
互相传输数据
,但必须分时复用 1根
数据线; -
单工:通信
只能
有一方发送到另一方,不能
反向传输;【要线或者不要线,遥控器(单向)发送信号】 -
异步:通信双方各自
约定通信速率;
(时间不严格) -
同步:通信双方靠
1根时钟线
来约定通信速率;
(时间严格) -
总线:连接
各个设备
的数据传输线路 (类似于一条马路,把路边各住户连接起来,使住户可以相互交流)。
四、串口的参数及时序图
1、概念
波特
率:串口通信的速率(发送和接收各数据位的间隔时间),表示每秒钟传送码元符号的个数,是衡量数据传送速率的指标。- 比较:
比特
率:是指每秒传送的比特(bit)数。单位为 bps(Bit Per Second),比特率越高,每秒传送数据就越多。
- 比较:
- 检验位:用于数据验证;
- 停止位:用于数据帧间隔。
2、检验位
奇检验(第9位 为检验位)
但是检验也是有问题的
像下列类似的错误是
检测不出来
的,只能在一定程度上
检测数据的正误性,说明其排错率不高
输入:0000 0011 1 接收:0000 0101 1
-
检验不通过
输入:1110 0000 0 接收:1100 0000 0
输入
的时候是奇数
接收
的时候,是偶数
,明明采用的是奇检验,却出现了偶数,这就说明在传输出了问题,反馈给系统,让其重发或者是进行其它处理(我们自己定)。
3、串口的通信
顺序:从
低到高
位发,1位1位的发
五、串口模式图
SBUF(Serial Buffer):
串口数据缓存寄存器
,物理上
是两个独立
的寄存器,但占用相同的地址
。
写
操作时,写入的是发送寄存器
,读
操作时,读出的是接收寄存器
。
1、收发过程分析
串口发送的时候,先把
八位
的数据写到SBUF
中,再通过发送控制器
控制控制门
用TXD
引脚把数据送出。(发出去之后,系统就会产生 1个TI(Transmit Interrupt),执行中断函数)xxx = SBUF;//发送的时候,把SBUF赋给别的变量
中间那块是
时钟
,控制波特率
。接收的时候,由
RXT
接收数据,通过``接收控制器控制
移位寄存器把 数据存到
SBUF` 中,需要的时候把它取出来。(接收数据的时候,如果收到1个字节,系统就会产生1 个RI(Receive Interrupt),执行中断函数)SBUF = XXX;//接收的时候,把接收的数据赋给SBUF
2、定时器的中断
2.1 定时器的中断系统
2.2 串口的中断系统
TI
和RI
占用同 1个通道用
串口发送
举例子:若是发送完成,就会触发中断,然后判断是
TI
还是RI
, ≥1 只要有其中一个信号就可以使得ES
打开、EA
打开、配置ps
(但是此处我们同时只会有1个中断,所以可以不用配置 优先级,只配置ES
、EA
即可)
3、相关寄存器
PCON
电源控制控制寄存器
的前两位是和寄存器有关的SMOD
、SMOD0
;
IE
中的EA
、ES
与串口有关;
第二部分:
一、串口向电脑发送数据&电脑通过串口控制LED
1、串口向电脑发送数据
1.1看手册_串行口初始化配置
寄存器SCON
(1、配置SM0/FE
SM0/FE
FE
用于检测帧错误,适用于9位数据格式
,我们当前用的是 8位 所以可不不管它。- 但是
SM0
需要配合SM1
配置工作模式
所以
SM0=0
,SM1=1
便可工作在模式1(常用,以此为例) 中
(2、SM2
允许模式2或模式3多机通信控制位。我们只用模式1 所以用不到,不用管。
(3、REN
(Receive ENable,接收使能)(使能
,理解为开关
即可)
因为此处是
发送数据
,所以可以先 REN=0 关闭开关
。(给 1 也行,只要外接(电脑)不给它发,就不会出发)
(4、TB8
、RB8
暂时用不到,不用管。
TB8=0,RB8=0;
(5、TI
发送完了,
TI=1
,同时中断中可以判断是 发送 还是接收。发送完了以后,我们必须
在软件中将其置为 0
,因为硬件只会置1
TI=0;
(6、RI
因为我们此处是 发送输出,接收就不管它了。置为0
RI=0;
整合起来是:
二进制:0100 0000 十六进制:0x40
SCON=0X40;
1.2 看手册_串行口初始化配置
寄存器SBUF
因为
SBUF
是接收/发送缓存
,初始化的时候不用配置它。
1.3 看手册_串行口初始化配置
寄存器PCON
(1、SMOD
、SMOD0
PCON
的寄存器中只有 2位与串口有关。
看图,
SMOD=0
,不加倍;SMOD=1
加倍。
SMOD0
因为是8位数据格式,不用检测,可以置 0。
(2、IE
(Interrupt Enable)
中断开关
,此时可以不用开启中断,所以可以不配置。
整合起来是:
二进制:1000 0000 十六进制:0x80
PCON=0x80;
1.4 配置定时器自动重装模式
配置定时器1 为8位自动重装
二进制:0010 0000 十六进制:0x20
关于波特率的生成与计算:
(1、先用STC-ISP生成
加倍:为了让时钟不会过慢
(2、波特率的计算
波特率生成的地方,有
T1溢出率
、SMO
还有÷16
生成的代码中 SCON=0x50,我自己写的是 SCON=0x40 (我这里是不使能的)
(1)T1溢出率
晶振是 11.0592MHz ,12÷11.0592=1.085
十六进制 0xFA 的十进制是 250 ,我们这个计时器达到
256就会溢出
,所以这个时候,再走6个数,就会溢出,对应着的是6×1.085=6.51us ,溢出率=1/6.51us=0.153609MHz
(2)SMOD
我们此处设置的是
加倍
,即SMOD=1
,波特率
=溢出率÷16=0.153609MHz÷16=9600Hz,是我们设的波特率
也可以参考:
1.5 发送字节函数
发送的过程,我们只需要把数据写到
SBUF
中即可,一写入即可发送出去。(前提是定时器
和波特率
已经都初始化
好了)
1.6 调用写完的函数
先
初始化
,再调用
串口向电脑发送数据_执行结果:
(1、发送我们输入的数据
开发板上点击
复位
,就可以看到串口助手上的数据
(2、自动发送递增的十六进制数
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
unsigned char Sec;//定义一个 Sec(秒)
void main()
{
UART_Init();
UART_SendByte(0x11);
while(1)
{
UART_SendByte(Sec);
Sec++;
Delay(1000);
}
}
小贴士:
(1)函数模块化的时候,函数名的规范格式:模块名_功能
(2)模块化编程的时候,记得写函数的注释
2、电脑通过串口控制LED
(1、配置 REN
因为我们现在要
允许串行接收控制位
,所以要使REN=1
二进制:0101 0000 十六进制:0x50
接收完成以后,会执行中断函数
(2、配置串口中断
此处与串口有关的只有
ES
和EA
ES=1;
EA=1;
/**
* @brief 串口初始化 9600bps@11.0592MHz
* @param 无
* @retval 无
*/
void UART_Init()
{
SCON=0x50;
PCON |= 0x80;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式 //此时为模式1
TL1 = 0xFA; //设定定时初值
TH1 = 0xFA; //设定定时器重装值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
TR1 = 1; //启动定时器1
ES=1;
EA=1;
}
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
void main()
{
UART_Init();
UART_SendByte(0x11);
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) //判别输入与发送
{
P2=~SBUF;//SBUF在等号右边,说明现在是读入模式
UART_SendByte(SBUF);//单片机向电脑发送接收的文件
RI=0;
}
}
因为
发送(Transmit)
和接收(Receive)
都会触发中断,所以if(RI==1)
是为了把两者区分开
小贴士:
(1)
中断函数
最好和主函数
放在一起,因为它和主函数的耦合性
比较大;(2)
1个其它函数
最好不要在中断
函数与主
函数中同时
调用。
二、数据显示模式
- HEX模式/十六进制模式/二进制模式:以
原始数据
的形式显示; - 文本模式/字符模式:以
原始数据编码后
的形式显示。
在这里插入图片描述
文本模式:
ASCII码:转换成ASCII对应的 字符,输出
HEX模式:
其次:
版权声明:本文为CSDN博主「与太阳有关_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_55251293/article/details/122483743
第一部分_串口
一、基础知识
- 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
- 单片机的
串口
可以使单片机与单片机
、单片机与电脑
、单片机与各式各样的模块
互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。 - 51单片机内部自带
UART
(Universal Asynchronous Receiver Transmitter,通用异步
收发器)可实现单片机的串口通信。
第一个 USB转换工具 相当于
第二个 陀螺仪模块,加速度传感器
第三个 蓝牙串口
小贴士:
VGA接口,相比于 串口的接口(两排) 它有三排插、孔。【用于视频传输、电脑外接显示器】
二、硬件电路
1、介绍
- 简单
双向
串口通信有2根
通信线 (发送端 TXD 和 接收端 RXD);- 发送端 TXD,Transmit eXchange Data;
- 接收端 RXD,Receive eXchange Data。
- TXD与RXD要
交叉
连接; - 当只需
单向
的数据传输时,可以直接1根
通信线; - 当
电平标准不一致
时,需要加电平转换芯片
。
2、 电平标准
- 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
TTL电平
:+5V 表示 1, 0V 表示 0 ;(对地电压)RS232电平
:-3~-15V 表示 1, +3~+15V 表示 0;(对地电压) <反逻辑
>【距离最多十多米,否则会传输出错】RS485电平
:两线压差
+2~+6V 表示 1, -2~-6V 表示 0(差分
信号)【最多传输一千多米】
三、常见的通信接口的比较
1、比较
I^2C
和SPI
的通信方式都有同步,且都带有SCL
,即时钟线
。
1.1 相关术语
-
全双工:通信双方可以在
同一时刻互相
传输数据; -
半双工:通信双方可以
互相传输数据
,但必须分时复用 1根
数据线; -
单工:通信
只能
有一方发送到另一方,不能
反向传输;【要线或者不要线,遥控器(单向)发送信号】 -
异步:通信双方各自
约定通信速率;
(时间不严格) -
同步:通信双方靠
1根时钟线
来约定通信速率;
(时间严格) -
总线:连接
各个设备
的数据传输线路 (类似于一条马路,把路边各住户连接起来,使住户可以相互交流)。
四、串口的参数及时序图
1、概念
波特
率:串口通信的速率(发送和接收各数据位的间隔时间),表示每秒钟传送码元符号的个数,是衡量数据传送速率的指标。- 比较:
比特
率:是指每秒传送的比特(bit)数。单位为 bps(Bit Per Second),比特率越高,每秒传送数据就越多。
- 比较:
- 检验位:用于数据验证;
- 停止位:用于数据帧间隔。
2、检验位
奇检验(第9位 为检验位)
但是检验也是有问题的
像下列类似的错误是
检测不出来
的,只能在一定程度上
检测数据的正误性,说明其排错率不高
输入:0000 0011 1 接收:0000 0101 1
-
检验不通过
输入:1110 0000 0 接收:1100 0000 0
输入
的时候是奇数
接收
的时候,是偶数
,明明采用的是奇检验,却出现了偶数,这就说明在传输出了问题,反馈给系统,让其重发或者是进行其它处理(我们自己定)。
3、串口的通信
顺序:从
低到高
位发,1位1位的发
五、串口模式图
SBUF(Serial Buffer):
串口数据缓存寄存器
,物理上
是两个独立
的寄存器,但占用相同的地址
。
写
操作时,写入的是发送寄存器
,读
操作时,读出的是接收寄存器
。
1、收发过程分析
串口发送的时候,先把
八位
的数据写到SBUF
中,再通过发送控制器
控制控制门
用TXD
引脚把数据送出。(发出去之后,系统就会产生 1个TI(Transmit Interrupt),执行中断函数)xxx = SBUF;//发送的时候,把SBUF赋给别的变量
中间那块是
时钟
,控制波特率
。接收的时候,由
RXT
接收数据,通过``接收控制器控制
移位寄存器把 数据存到
SBUF` 中,需要的时候把它取出来。(接收数据的时候,如果收到1个字节,系统就会产生1 个RI(Receive Interrupt),执行中断函数)SBUF = XXX;//接收的时候,把接收的数据赋给SBUF
2、定时器的中断
2.1 定时器的中断系统
2.2 串口的中断系统
TI
和RI
占用同 1个通道用
串口发送
举例子:若是发送完成,就会触发中断,然后判断是
TI
还是RI
, ≥1 只要有其中一个信号就可以使得ES
打开、EA
打开、配置ps
(但是此处我们同时只会有1个中断,所以可以不用配置 优先级,只配置ES
、EA
即可)
3、相关寄存器
PCON
电源控制控制寄存器
的前两位是和寄存器有关的SMOD
、SMOD0
;
IE
中的EA
、ES
与串口有关;
第二部分:
一、串口向电脑发送数据&电脑通过串口控制LED
1、串口向电脑发送数据
1.1看手册_串行口初始化配置
寄存器SCON
(1、配置SM0/FE
SM0/FE
FE
用于检测帧错误,适用于9位数据格式
,我们当前用的是 8位 所以可不不管它。- 但是
SM0
需要配合SM1
配置工作模式
所以
SM0=0
,SM1=1
便可工作在模式1(常用,以此为例) 中
(2、SM2
允许模式2或模式3多机通信控制位。我们只用模式1 所以用不到,不用管。
(3、REN
(Receive ENable,接收使能)(使能
,理解为开关
即可)
因为此处是
发送数据
,所以可以先 REN=0 关闭开关
。(给 1 也行,只要外接(电脑)不给它发,就不会出发)
(4、TB8
、RB8
暂时用不到,不用管。
TB8=0,RB8=0;
(5、TI
发送完了,
TI=1
,同时中断中可以判断是 发送 还是接收。发送完了以后,我们必须
在软件中将其置为 0
,因为硬件只会置1
TI=0;
(6、RI
因为我们此处是 发送输出,接收就不管它了。置为0
RI=0;
整合起来是:
二进制:0100 0000 十六进制:0x40
SCON=0X40;
1.2 看手册_串行口初始化配置
寄存器SBUF
因为
SBUF
是接收/发送缓存
,初始化的时候不用配置它。
1.3 看手册_串行口初始化配置
寄存器PCON
(1、SMOD
、SMOD0
PCON
的寄存器中只有 2位与串口有关。
看图,
SMOD=0
,不加倍;SMOD=1
加倍。
SMOD0
因为是8位数据格式,不用检测,可以置 0。
(2、IE
(Interrupt Enable)
中断开关
,此时可以不用开启中断,所以可以不配置。
整合起来是:
二进制:1000 0000 十六进制:0x80
PCON=0x80;
1.4 配置定时器自动重装模式
配置定时器1 为8位自动重装
二进制:0010 0000 十六进制:0x20
关于波特率的生成与计算:
(1、先用STC-ISP生成
加倍:为了让时钟不会过慢
(2、波特率的计算
波特率生成的地方,有
T1溢出率
、SMO
还有÷16
生成的代码中 SCON=0x50,我自己写的是 SCON=0x40 (我这里是不使能的)
(1)T1溢出率
晶振是 11.0592MHz ,12÷11.0592=1.085
十六进制 0xFA 的十进制是 250 ,我们这个计时器达到
256就会溢出
,所以这个时候,再走6个数,就会溢出,对应着的是6×1.085=6.51us ,溢出率=1/6.51us=0.153609MHz
(2)SMOD
我们此处设置的是
加倍
,即SMOD=1
,波特率
=溢出率÷16=0.153609MHz÷16=9600Hz,是我们设的波特率
也可以参考:
1.5 发送字节函数
发送的过程,我们只需要把数据写到
SBUF
中即可,一写入即可发送出去。(前提是定时器
和波特率
已经都初始化
好了)
1.6 调用写完的函数
先
初始化
,再调用
串口向电脑发送数据_执行结果:
(1、发送我们输入的数据
开发板上点击
复位
,就可以看到串口助手上的数据
(2、自动发送递增的十六进制数
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
unsigned char Sec;//定义一个 Sec(秒)
void main()
{
UART_Init();
UART_SendByte(0x11);
while(1)
{
UART_SendByte(Sec);
Sec++;
Delay(1000);
}
}
小贴士:
(1)函数模块化的时候,函数名的规范格式:模块名_功能
(2)模块化编程的时候,记得写函数的注释
2、电脑通过串口控制LED
(1、配置 REN
因为我们现在要
允许串行接收控制位
,所以要使REN=1
二进制:0101 0000 十六进制:0x50
接收完成以后,会执行中断函数
(2、配置串口中断
此处与串口有关的只有
ES
和EA
ES=1;
EA=1;
/**
* @brief 串口初始化 9600bps@11.0592MHz
* @param 无
* @retval 无
*/
void UART_Init()
{
SCON=0x50;
PCON |= 0x80;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式 //此时为模式1
TL1 = 0xFA; //设定定时初值
TH1 = 0xFA; //设定定时器重装值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
TR1 = 1; //启动定时器1
ES=1;
EA=1;
}
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
void main()
{
UART_Init();
UART_SendByte(0x11);
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) //判别输入与发送
{
P2=~SBUF;//SBUF在等号右边,说明现在是读入模式
UART_SendByte(SBUF);//单片机向电脑发送接收的文件
RI=0;
}
}
因为
发送(Transmit)
和接收(Receive)
都会触发中断,所以if(RI==1)
是为了把两者区分开
小贴士:
(1)
中断函数
最好和主函数
放在一起,因为它和主函数的耦合性
比较大;(2)
1个其它函数
最好不要在中断
函数与主
函数中同时
调用。
二、数据显示模式
- HEX模式/十六进制模式/二进制模式:以
原始数据
的形式显示; - 文本模式/字符模式:以
原始数据编码后
的形式显示。
在这里插入图片描述
文本模式:
ASCII码:转换成ASCII对应的 字符,输出
HEX模式:
其次:
版权声明:本文为CSDN博主「与太阳有关_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_55251293/article/details/122483743
暂无评论