学习使用的开辟板:STC89C52RC/LE52RC
编程软件:Keil5
烧录软件:stc-isp
开辟板实图:
串口
- 串口是一种应用非常广泛的通讯接口,串口本钱低、轻易使用、通讯线路简单,可实现两个装备的相互通讯
- 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块相互通讯,极大的扩展了单片机的应用范围,加强了单片机体系的硬件气力
51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通讯
硬件电路
简单双向串口通讯有两根通讯线(发送端TXD(Transmit Exchange Data)和吸收端RXD(Receive Exchange Date))
TXD和RXD要交织毗连,装备1的TXD毗连装备2的RXD,装备1的RXD毗连装备2的TXD
当只要单向传输数据时,可以只有一根通讯线
GND是肯定要毗连的,若两个装备都可以各自供电,则不须要毗连VCC
当电平尺度差别等时,还须要加电平转换芯片
电平尺度
电平尺度是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平尺度有如下三种:
- TTL电平:+5V体现1,0V体现0,一样平常用于单片机
- RS232电平:-3 ~ -15V 体现1,+3 ~ +15V 体现0,一样平常用于电脑
- RS485电平:两线压差 +2 ~ +6V 体现1,-2 ~ -6V 体现0(差分信号),一样平常用于CAN总线
前两个通讯隔断都较近,一样平常只有十几米,隔断过远传输的数据就很轻易堕落;而RS485通讯隔断远,信号可靠性高,传输隔断可达1KM以上
干系术语
- 半双工:通讯双方可以相互传输数据,但同时间只能有一段发送,另一端吸收,必须分时复用一根数据线
- 单工:通讯双方只能一方发送到另一方,不能反向传输。比如遥控器控制电视,只能遥控器向电视发送数据
- 异步:通讯双方各自约定通讯速率
- 同步:通讯双方靠一根时钟线来约定通讯速率
数据传输是依靠高低电平的,也就是电平协议。比如如下两个数据
看电平都是从高电平变为低电平,但是假如通讯速率不一样,则获取的数据不一样
通讯速率快,10大概会被分析为1100;通讯速率慢,1100也大概会被分析为10。
以是约定好通讯速率很告急
- 总线:毗连各个装备的数据传输线路(类似一条马路,把路边的住户毗连起来,使住户可以相互互换)
常见通讯接口比力
- UART:为本节学习的串口通讯接口
- I2C:板子上的C24C02使用该串口
- SPI:板子上的DS1302使用非尺度SPI
- 1-Wire:板子上的DS18B20使用该串口
常见的另有CAN总线和USB,CAN总线常用于汽车范畴
UART
51单片机的UART
STC89C52有1个UART,RXD和TXD分别和P3.0和P3.1这两个I/O口共用同一个引脚
STC89C52的UART有四种工作模式:
模式0:同步移位寄存器
模式1:8位UART,波特率可变(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变
串口参数及时序图
- 波特率:串口通讯的速率(发送和吸收各数据位的隔断时间)
- 校验位:用于数据验证,肯定步调可以知道数据是否错误,也须要双方提前协商同一校验。常用的校验如01校验,奇偶校验。9位UART就是多了一位校验位
- 克制位:用于数据帧隔断,发送多个数据,怎样隔断两个数据,就使用克制位
波特率就是上述异步双方要约定好的怎样对数据举行采样
串口收发数据,都是从低位开始
串口模式图
简单的串口模式图
UART是集成在单片机内部的,通过TXD引脚发送数据,RXD引脚吸收数据
UART可以分为三个部分,中央为定时器T1——控制波特率;左侧绿框的SBUF用于收发数据;右侧为停止体系
SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用类似的地点。写利用时,写入的是发送寄存器,读利用时,读出的是吸收寄存器
完备的串口和停止体系模式图如下:
下面通过先容干系寄存器来报告串口通讯的原理
串口干系寄存器
串行口控制寄存器SCON和PCON
STC89C52系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON和波特率选择特别功能寄存器PCON
PCON
电源控制寄存器,大概是电源控制另有剩下比特位,以是波特率选择和帧错误控制位也集成此中,淘汰资源斲丧
格式如下:
我们只要关注SMOD 和 SMOD0 即可
- SMOD:波特率选择位。当软件置SMOD = 1时,使串行通讯方式1、2、3的波特率更加;SMOD = 0,则不更加。复位时SMOD = 0
- SMOD0:帧错误检测有用控制位。当SMOD = 1,SCON寄存器中的 SM0/FE 位于 FE(帧错误检测)功能;当SMOD0 = 0,SCON的SM0/FE 用于 和 SM1 组合指定串行口的工作模式。复位时 SMOD0 = 0
SCON
用于选择串行通讯的工作方式和某些控制功能,格式如下:
- SM0/FE:当PCON寄存器的 SMOD0/FE = 1时,该位用于帧错误检测。当检测到一个无效克制位时,通过UART吸收器设置该位,必须由软件清零;当SMOD0/FE = 0,该位和 SM1 组合指定工作模式
- REN:答应/克制串行吸收控制位。由软件置位,若REN = 1即答应串行吸收数据;REN = 0则克制吸收
- SM2:答应方式2或方式3多机通讯控制位。
- TB8:在方式2或方式3,为要发送的第9位数据,按须要由软件置位或清0。可用作数据的校验位或多机通讯中体现地点帧/数据帧的标志位。
- RB8:在方式2或方式3,是吸收到的第9位数据。在方式1,若SM2=0,则RB8是吸收到的克制位。方式0不消RB8。
- TI:发送停止哀求标志位。在方式0,当串行发送数据第8位竣事时,由内部硬件置TI = 1,向主机哀求停止,相应停止后必须用软件复位,即TI = 0。在其他方式中,则在克制位开始发送时由内部硬件置位,必须用软件复位TI = 0
- RI:吸收停止哀求标志位。在方式0,当串行吸收到第8位竣事时由内部硬件自动置位 RI = 1 ,向主机哀求停止,相应停止后必须用软件复位,即RI=0。在其他方式中,串行吸收到克制位的中央时候由内部硬件置位,即RI=1,必须由软件复位,即RI=0
IE
停止答应寄存器
此中我们只关注EA 和 ES
- EA:CPU的总停止答应控制位,EA = 1,CPU开放停止;EA = 0,CPU屏蔽全部停止哀求
- ES:串行口停止答应位,ES = 1,答应串行口停止;ES = 0,克制串行口停止
注意:吸收停止和发送停止共用一个停止,在停止处理处罚函数中还须要通过RI 和 TI 的置位判断本次停止是吸收停止还是发送停止
末了我们回归模式图,讲授一下串口通讯的流程
发送数据
通过总线将数据写入SBUF,定时器1控制波特率。通过TXD发送数据,当发送数据竣事时(方式0为发完8位数据,其他方式为发送克制位时),将 TI = 1,发送停止哀求
吸收数据
RXD吸收数据,通过定时器1控制波特率,对吸收数据举行采样,存放在SBUF,当吸收数据竣事(方式0当串行发送数据第8位竣事时,在其他方式中,则在克制位开始发送时由内部硬件置位),将 RI = 1,发出停止哀求
注意:TI 和 RI 都须要由软件置0
编码
颠末上述学习,我们已经对串口有了肯定的相识,接下来就是实现串口通讯
单片机通过串口发送数据
我们使用UART串口通讯,起首要举行初始化,如:选择工作方式,初始化停止体系,设置波特率,初始化定时器
选择工作模式
涉及到SCON 和 PCON
起首是PCON的SMOD0,当 SMOD0 = 0 时,SMOD 的 SM0 才会被用来选择工作方式
其次,我们选择 8位UART,波特率可变模式,即方式1,SCON的SM0 = 0,SM1 = 1
末了,假如要答应串口吸收数据,还须要置SCON的REN = 1
初始化停止体系
起首,初始化串口收发数据的停止哀求标志位,SCON的 TI 和 RI,由硬件置1,我们初始化时清零即可:TI = 0, RI = 0
到此,SCON的设置就竣事了
总结一下,SM0 = 0, SM1 = 1, REN = 1/0, TI = 0, RI = 0,其他默以为0即可,以是SCON = 0x40/0x50
然后是停止开关
ES = 1, EA = 1
- SCON = 0x50; //选择工作方式 & 允许串口接收数据
- PCON |= 0x80; //使SM0为选择工作方式
- //中断开关
- ES = 1; //串口中断开关
- EA = 1; //总中断开关
复制代码 初始化定时器
初始化定时器可参看【51单片机】定时器
此处定时器1选择工作模式2——8位自动重装
8位自动重装
一次只对TL1或TH1计数加一
当一个溢出后,直接使用另一个计数单元的初值
- //设置定时器1
- TMOD &= 0x0F; //高4位清零
- TMOD |= 0x20; //0010,模式3——8位自动重载
- TR1 = 1; //启用定时器T1
- ET1 = 0; //禁止定时器T1中断
- //定时器初值
- TL1 = 0xF3; //设定定时初值
- TH1 = 0xF3; //设定定时器重装值
复制代码 设置波特率
我们设置波特率为4800
设置波特率须要通过设置定时器1的初始值
- TL1 = 0xF3; //设定定时初值
- TH1 = 0xF3; //设定定时器重装值
复制代码 讲授一下为什么定时器初值是这个
假设体系频率为12MHz,使用12T模式,则定时器频率为12 / 12 = 1MHz,即每1us,计数单元加1。
使用8位自动重装,256时会溢出,0xF3 = 243,256 - 243 = 13。以是定时器溢出须要13us
溢出率:1 / 13 = 0.07692
使用SMOD = 1,波特率更加(不除2)
还须要 0.07692 / 16 = 0.0048076923MHz
转化为Hz:4807.6923Hz,这个就是波特率
会存在肯定毛病
也可参看如下盘算
到此,串口的初始化就完成了
完备代码如下:
- /**
- * @brief 初始化串口
- * @parm 无
- * @retval 无
- */
- void UART_Init()
- {
- //SCON高4位分别为SM0、SM1、SM2、REN
- //SM0和SM1控制串口模式,选择01——8位UART,波特率可变
- //REN接收使能,REN = 0禁止接收,REN = 1允许接收
- //所以设置0101 0000
- SCON = 0x50;
- //PCON包含波特率和电源设置
- //前两位为SMOD和SMOD0
- //SMOD = 1波特率加倍,SMOD = 0,波特率不加倍
- //SMOD0是帧错误的,此处不用
- //所以设置1000 0000
- PCON |= 0x80;
- //设置定时器1
- TMOD &= 0x0F; //高4位清零
- TMOD |= 0x20; //0010,模式3——8位自动重载
- TR1 = 1; //启用定时器T1
- ET1 = 0; //禁止定时器T1中断
- //定时器初值
- TL1 = 0xF4; //设定定时初值
- TH1 = 0xF4; //设定定时器重装值
- //中断开关
- ES = 1; //串口中断开关
- EA = 1; //总中断开关
- }
复制代码 博主的单片机体系频率为11.0592MHz
可以使用STC-ICP天生波特率设置代码
注意:设置肯定要选择精确;代码中的AUXR寄存器为高版本单片机才有的,低版本不认识这个寄存器,可以直接删掉
串口发送数据通过赋值SBUF,数据发送完后,硬件置位TI = 1,须要我们手动对TI清零
代码如下:
- /**
- * @brief 通过串口发送一个字节数据
- * @parm Byte:要发送字节数据
- * @retval 无
- */
- void UART_SendByte(unsigned char Byte)
- {
- SBUF = Byte;
- while(TI == 0);//数据发送完,硬件置1
- TI = 0; //软件置0
- }
复制代码 模块化编程,完备代码如下:
延时模块——控制串口发送数据速率
Delay.h
- #ifndef __DELAY_H__
- #define __DELAT_H__
- void Delayms(unsigned int xms);//等待指定毫秒
- #endif
复制代码 Delay.c
- #include <INTRINS.h>
- /**
- * @brief 延迟一定时间
- * @parm 延迟的时间,单位是毫秒,范围:0 ~ 65535
- * @retval 无
- */
- void Delayms(unsigned int xms) //@11.0592MHz
- {
- while(xms--)
- {
- unsigned char i, j;
- _nop_();
- i = 2;
- j = 199;
- do
- {
- while (--j);
- } while (--i);
- }
- }
复制代码 UART串口模块
UART.h
- #ifndef __UART_H__
- #define __UART_H__
- void UART_Init();
- void UART_SendByte(unsigned char Byte);
- #endif
复制代码 UART.c
- #include <REGX52.H>/**
- * @brief 初始化串口
- * @parm 无
- * @retval 无
- */
- void UART_Init()
- {
- //SCON高4位分别为SM0、SM1、SM2、REN
- //SM0和SM1控制串口模式,选择01——8位UART,波特率可变
- //REN接收使能,REN = 0禁止接收,REN = 1允许接收
- //所以设置0101 0000
- SCON = 0x50;
- //PCON包含波特率和电源设置
- //前两位为SMOD和SMOD0
- //SMOD = 1波特率加倍,SMOD = 0,波特率不加倍
- //SMOD0是帧错误的,此处不用
- //所以设置1000 0000
- PCON |= 0x80;
- //设置定时器1
- TMOD &= 0x0F; //高4位清零
- TMOD |= 0x20; //0010,模式3——8位自动重载
- TR1 = 1; //启用定时器T1
- ET1 = 0; //禁止定时器T1中断
- //定时器初值
- TL1 = 0xF4; //设定定时初值
- TH1 = 0xF4; //设定定时器重装值
- //中断开关
- ES = 1; //串口中断开关
- EA = 1; //总中断开关
- }
- /** * @brief 通过串口发送一个字节数据 * @parm Byte 要发送字节数据 * @retval 无 */void UART_SendByte(unsigned char Byte){ SBUF = Byte; while(TI == 0);//数据发送完,硬件置1 TI = 0; //软件置0}///**// * @brief 吸收数据 模版// * @parm 无// * @retval 无// *///void UART_Routine() interrupt 4//{// if(RI == 1)//检测是否是吸收数据停止// {// RI = 0;//软件置0// }//}
复制代码 主步调——每隔一秒通过串口发送递增数据
- #include <REGX52.H>
- #include "UART.h"
- #include "Delay.h"
- /**
- * @brief 通过串口每隔1s发送递增的数据 范围:0 ~ 255
- * @parm 无
- * @retval 无
- */
- void SendIncreasingNum()
- {
- static unsigned char num;
- UART_SendByte(num++);
- Delayms(1000);
- }
- void main()
- {
- UART_Init();
- while(1)
- {
- SendIncreasingNum();
- }
- }
复制代码 使用STC-IST 的 串口助手 检察结果
注意:下面一行的设置要精确
电脑通过串口发送数据控制LED灯
电脑发送数据给单片机须要USB转串口,自带的USB线就已经实现了这一转换,以是我们直接编写单片机通过串口吸收数据的逻辑即可。
串口吸收数据会存放在SBUF,吸收完毕后会将RI置1,发出停止哀求,停止号为4,然后须要手动清零RI
代码如下:
- void UART_Routine() interrupt 4
- {
- if(RI == 1)//检测是否是接收数据中断
- {
- P2 = SBUF;
- RI = 0;//软件置0
- }
- }
复制代码 注意:P2寄存器用于控制LED亮灭,为0亮起,为1熄灭
还可以将数据重新返回给电脑,同样使用Delay 和 UART 模块,只有main.c差别
main.c
- #include <REGX52.H>
- #include "UART.h"
- #include "Delay.h"
- /**
- * @brief 接收数据,亮相应的灯,并返回数据
- * @parm 无
- * @retval 无
- */
- void UART_Routine() interrupt 4
- {
- if(RI == 1)//检测是否是接收数据中断
- {
- P2 = SBUF;
- UART_SendByte(SBUF);
- RI = 0;//软件置0
- }
- }
- void main()
- {
- UART_Init();
- while(1)
- {
-
- }
- }
复制代码 结果如下:
我们通过串口助手,发送 0xAA = 1010 1010
LED灯结果如下:
以上就是本篇博客的全部内容,感谢你的阅读
假如以为本篇文章对你有所资助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很告急。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |