51_串口
#ifndef __USART_H_ #define __USART_H_ #include <reg51.h> void Usart_Init(void); void uart_send_byte(unsigned char i); #endif
#include "USART.h" #define Crystal_Frequency 12000000UL //使用12M晶体 #define BAUD_9600 4800UL //波特率定义为9600 /*************************************************** * 串口初始化子函数 * T1工作在方式2,波特率9600,开串口中断 ****************************************************/ void Usart_Init(void) { // EA=0; //暂时关闭中断 TMOD=0x20; //定时器1工作在模式2,自动重装模式 SCON=0x50; //串口工作在模式1 TH1=256-Crystal_Frequency /(BAUD_9600*12*16); //计算定时器重装值 TL1=256-Crystal_Frequency /(BAUD_9600*12*16); // TH1=0XF3; //计数器初始值设置,注意波特率是4800的 //TL1=0XF3; PCON|=0x80; //串口波特率加倍 //ES=1; //串口中断允许 TR1=1; //启动定时器1 //REN=1; //允许接受 //EA=1; //允许中断 } /*************************************************** * 串口发送字节子函数 * ****************************************************/ void uart_send_byte(unsigned char i) { SBUF = i; //送入发送缓冲寄存器 while(TI == 0); //判断发送是否完成 TI = 0; //清除中断标志 } /*************************************************** * 串口接受中断函数 * ****************************************************/ //void uart(void) interrupt 4 //{ // unsigned char uart_buf; //接受中断缓冲器 // if(RI) //是否到数据 // { // RI=0; //清中断请求 // uart_buf=SBUF; // } // //}
UART通信原理
通讯过程描述
- 当没有通信信号时,通信线路保持高电平。
- 发送数据之前, 先发送一个
0
表示起位,表示起始位
。 - 接着发送8位数据位,数据位是
先低后高
的顺序。 - 数据位发送完毕,再发送一个
1
表示停止位
。
通讯数据帧图
- UART完整串行数据帧:
UART模块的使用
51单片机的 UART 串口的结构由串行口控制寄存器 SCON
,发送电路
和接收电路
三部分构成。
串口控制寄存器
SCON
串行控制寄存器的位分配(地址为0x98
, 可位寻址)
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符号 | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
复位值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
位 | 符号 | 描述 |
7 | SM0 | 这两位共同决定了串口通信的模式0 ~模式 3 共 4 种模式 。 最常用的就是模式 1 ,也就是 SM0=0 SM1=1 ,其它模式从略。 |
6 | SM1 | |
5 | SM2 | 多机通信控制位(极少用),模式 1 直接清零。 |
4 | REN | 使能串行接收。由软件置位使能接收,软件清零则禁止接收。 |
3 | TB8 | 模式2 和 3 中要发送的第 9 位数据(很少用)。 |
2 | RB8 | 模式2 和 3 中接收到的第 9 位数据(很少用),模式 1 用来接收停止位。 |
1 | TI | 发送中断标志位,当发送电路发送到停止位的中间位置时,TI 由硬件置 1必须通过软件清零。 |
0 | RI | 接收中断标志位,当接收电路接收到停止位的中间位置时,RI 由硬件置 1必须通过软件清零。。 |
-
串口模式1: 1 位起始位, 8 位数据位和 1 位停止位。
- SM0 = 0; SM1 = 1;
波特率
波特率的概念
-
波特率就是发送二进制数据位所用的时间,用
baud
表示。 -
发送1位二进制数据的持续时间为1/baud
波特率计算公式
-
对于
STC89C52
单片机来说, 波特率发生器只能由定时器T1/T2产生,不能由T0产生。 -
使用T1的模式2[自动重装模式], 定时器的重载值计算公式为:
TH1=TL1=256−晶振值/12/2/16/波特率TH1=TL1=256−晶振值/12/2/16/波特率256
: 定时器模式2(8位)的溢出值晶振值
: 1105920012
: 一个机器周期(STC89C52中一个时钟周期等于12
个时钟周期, 具体看芯片手册)16
: 串口模块将一位信号采集16
次,将其中7,8,9次取出来,如果这三次中两次如果是高电平就认为这位数据是1。- 波特率: 要设定的波特率
-
电源管理寄存器
PCON
, 设置后它可以将波特率提高一倍PCON |= 0x80
- 此时波特率公式为:
TH1=TL1=256−晶振值/12/16/波特率
- 此时波特率公式为:
// 程序名称: uart/main.c // 程序简述: uart实例 /* 功能描述: 单片机usb接上计算机并实现通讯, 将其结果+1发送给计算机 实现步骤: - 1. 配置串口为模式1 - 2. 配置定时器T1为模式2 - 3. 根据波特率计算TH1和TL1的初值, 如果有需要则可以使用PCNF进行波特率加倍 - 4. 打开定时器控制寄存器, 让定时器跑起来 - 5. 开启UART中断, 1.接收并解析数据, 2.处理数据, 3.发送数据 程序注释: - 波特率计算公式: TH1 = TL1 = 256 - 晶振值 / 机器周期 / 2 / 16 / 波特率 - 机器周期: STC89C52RC的机器周期是'晶振/12' - 16: 单片机uart模块会将每一个数据位取16次, 然后判断中间值来确定是'0'还是'1' - 波特率加倍: PCON |= 0x80;那么计算公式为: - TH1 = TL1 = 256 - 晶振值/12/16/波特率 */ #include<reg52.h> #define Crystal_Frequency 11059200 // 定义当前单片机的晶振频率 #define BAUDRATE 9600 // 定义当前单片机UART所采用的波特率 void ConfigUART(unsigned int baud); // 串口初始化 void main() { EA = 1; // 打开使能总中断 ConfigUART(BAUDRATE); while(1); } /* 串口配置函数, baud-通信波特率 */ void ConfigUART(unsigned int baud) { SCON = 0x50; // 配置为串口为模式1 TMOD &= 0x0F; // 清0 T1的控制位 TMOD |= 0x20; // 配置T1为模式2 TH1 = 256 - (Crystal_Frequency / 12 / 32) / baud; // 计算T1重载值 TL1 = TH1; // 初值等于重载值 ET1 = 0; // 禁止T1中断 ES = 1; // 使能串口中断 TR1 = 1; // 启动T1 } /* 串口中断服务函数 */ void Uart_Interrupt() interrupt 4 { if (RI) {// 接收到字节 RI = 0; // 手动清零接收中断标志位 SBUF = SBUF + 1; // 接收的数据 +1 后发回,左边是发送 SBUF ,右边是接收 SBUF } if (TI) {// 字节发送完毕 TI = 0; // 手动清零 发送中断标志位 } }