1、串行口(serial)介绍
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
STC89C52系列单片机内部集成有一个功能很强的全双工串行通信口UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),与传统8051单片机的串口完全兼容。设有2个互相独立的接收、发送缓冲器,可以同时发送和接收数据。发送缓冲器只能写入而不能读出,接收缓冲器只能读出而不能写入,,因而两个缓冲器可以共用一一个地址码(99H)。两个缓冲器统称串行通信特殊功能寄存器SBUF。
- 管脚:STC89C52系列单片机串行口对应的硬件部分对应的管脚是P3.0/RxD和P3.1/TxD。
- 串口通信优点:STC89C52系列单片机的串行通信口,除用于数据通信外,还可方便地构成一一个或多个并行I/O口,或作串一并转换,或用于扩展串行外设等。·
STC89C52中UART的四种工作模式
串行通信设有4种工作方式,其中两种方式的波特率是可变的,另两种是固定的,以供不同应用场合选用。波特率由内部定时器/计数器产生,用软件设置不同的波特率和选择不同的工作方式。主机可通过查询或中断方式对接收/发送进行程序处理,使用十分灵活。
- 模式0:同步移位寄存器
- 模式1:8位UART,波特率可变(常用)
- 模式2:9位UART,波特率固定
- 模式3:9位UART,波特率可变
串口硬件电路
- 简单双向串口通信有两根通信线(发送端TXD和接收端RXD)
- TXD与RXD要交叉连接
- 当只需单向的数据传输时,可以直接一根通信线
- 当电平标准不一致时,需要加电平转换芯片
电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
- TTL电平:+5V表示1,0V表示0
- RS232电平:-3~-15V表示1,+3~+15V表示0
- RS485电平:两线压差+2~+6V表示1,-2~-6V表示0(差分信号)
常用通信接口比较
通信中常用术语
- 全双工:通信双方可以在同一时刻互相传输数据
- 半双工:通信双方可以互相传输数据,但必须分时复用一根数据线
- 单工:通信只能有一方发送到另一方,不能反向传输
- 异步:通信双方各自约定通信速率
- 同步:通信双方靠一根时钟线(如上图中的SCL,SCLK)来约定通信速率
- 总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)
串口模式图
串口和中断系统
2、串行口相关寄存器
SCON (Serial Control)串行口控制
PCON(power control)电源控制
IE(interrupt enable)中断使能
TMOD 定时器模式选择
使用的是定时器1,8位自动装载定时器
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF3; // 设定定时初值
TH1 = 0xF3; //设定定时器重装值
TCON 定时器控制寄存器
3、串口实践——串口向电脑发送数据
实现功能:单片机每隔一秒给电脑发送一个递增的字节数据
串口初始化函数:
#include <REGX52.H>
/**
* @brief 串口初始化,4800bps@12.000MHz
* @param 无
* @retval 无
*/
void UART_Init() // 4800 bps @12.000MHZ
{
// 第一步、串口寄存器配置
SCON = 0x50; // 0101 0000 01表示方式一, 1表示REN 接收使能
PCON = 0x80; // 1000 0000 设置SMOD=1 ,即波特率加倍
//第二步、 定时器1 的配置
TMOD &= 0x0F;
TMOD |= 0x20; // 设置定时器1 为8位自动重载模式
// 初始值根据设定的波特率进行赋值
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while(TI == 0);
TI = 0;
}
主函数:
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main()
{
UART_Init(); //串口初始化
while(1)
{
UART_SendByte(Sec); //串口发送一个字节
Sec++; //Sec自增
Delay(1000); //延时1秒
}
}
4、串口实践——电脑通过串口向单片机发送数据
实现功能:电脑向单片机发送字节数据,控制LED灯的亮灭,此时需要用到中断
串口初始化函数:
#include <REGX52.H>
/**
* @brief 串口初始化,4800bps@12.000MHz
* @param 无
* @retval 无
*/
void UART_Init() // 4800 bps @12.000MHZ
{
// 第一步、串口寄存器配置
SCON = 0x50; // 0101 0000 01表示方式一, 1表示REN 接收使能
PCON = 0x80; // 1000 0000 设置SMOD=1 ,即波特率加倍
//第二步、 定时器1 的配置
TMOD &= 0x0F;
TMOD |= 0x20; // 设置定时器1 为8位自动重载模式
// 初始值根据设定的波特率进行赋值
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
/*为什么要用中断?检测电脑是否发送数据,一定发送数据则
触发中断 */
// 第三步、中断的配置
ES = 1; // 串行口中断允许位
EA = 1; // 中断系统总开关
}
主函数:
#include <REGX52.H>
#include "Delay.h"
#include "UART.h"
void main()
{
UART_Init(); //串口初始化
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) // 接受完成时触发中断,因为发送也会触发中断
{
P2 = SBUF;
RI = 0;
}
}
波特率计算方式(8位自动重装):
以初始值 TL1 = 0xF3; TH1 = 0xF3; 计数13个数就会溢出
而12MHZ单片机,即1微秒就会计数一次,溢出就是13微秒
波特率 = 1÷ 13us ÷ 16 = 4807.69 HZ
所以赋 初始值 TL1 = 0xF3; TH1 = 0xF3;波特率就是 4800HZ
此时误差率为: 7.69 ÷ 4800 = 0.16%