51单片机串口中断
51单片机串口中断
一、串口通信介绍#
随着单片机系统的广泛应用和计算机网络技术的普及,单片机与单片机或其他网络主机的通信愈来愈重要。在WIFI、蓝牙、GPS、GSM/GPRS等应用的控制都体现了串口通信的重要性。
通信的方式可以分为多种,按照数据传送方式可分为串行通信和并行通信。按照数据同步方式可分为同步通信和异步通信。按照数据的传输方向可分为单工、半双工、全双工通信。
串口通信(Serial Communication)是指外设和计算机间通过数据信号线、地线等按位进行传输数据的一种通信方式。串口是一种接口标准,规定了电气标准,例如:RS-232(RS-232的延伸)、RS-485等。
RS-232C是用正负电压来表示逻辑状态,与晶体管-晶体管逻辑集成电路(TTL)以高低电平表示逻辑状态的规定相反。而51单片机使用的就是TTL电平,所以要实现51单片机与计算机的串口通信,就需要进行TTL与RS-232C电平转换,通常使用MAX232芯片实现。
通信协议:通常遵循96-N-8-1
“96”表示通信波特率为9600;串口通信通常使用异步串口通信,所以必须保持两个设备的波特率一致。波特率常用值还有4800、115200
“N”表示无检验位,由于串口通信行相对更容易收到外部干扰导致传输数据出现偏差,在传输过程中使用校验位可以解决这个问题。
“8”表示数据位是8位。
“1”表示1位停止位。
二、串口相关的中断寄存器#
2-1 串口控制寄存器SCON(可位寻址)#
❤ SM0和SM1为工作方式选择位
❤ SM2:多机通信控制位,主要用于方式2和方式3.
❤ REN:允许串行接收位。有软件置REN=1,则启动串行口接收数据;REN=0,则禁止接收数据
❤ TB8:在方式2或方式3中,作为发送数据的第9位,也可以用软件规定其他作用
❤ RB8:在方式2或方式3中,作为接收数据的第9位
❤ TI:发送中断标志位。在方式0 时,当串行发送第8 位数据结束时,或在其它方式,串行发送开始时,由内部硬件使TI 置1,向CPU 发中断申请。在中断服务程序中,必须用软件将其清0,取消此中断申请。
❤ RI:接收中断标志位。在方式0 时,当串行接收第8 位数据结束时,或在其它方式,串行接收停止位的中间时,由内部硬件使RI 置1,向CPU 发中断申请。也必须在中断服务程序中,用软件将其清0,取消此中断申请。
2-2 电源控制寄存器PCON#
SMOD:波特率倍增位。在串口方式1、方式2、方式3 时,波特率与SMOD 有关,当SMOD=1 时,波特率提高一倍。复位时,SMOD=0
三、串口使用方法#
❤ 波特率的计算
方式0的波特率=fosc/12
方式2的波特率=[(2^SMOD)/32]*fosc
方式1的波特率=[(2^SMOD)/32]*(T1溢出率)
方式3的波特率=[(2^SMOD)/32]*(T1溢出率)
其中T1溢出率=fosc/{12*[256-(TH1)]},一般使用波特率工具计算波特率
❤ 串口初始化流程
1.确定T1的工作方式(TMOD寄存器)
2.确定串口的工作方式(SCON寄存器)
3.计算T1的初值(设定波特率),装在TH1、TL1
4.启动T1(TCON中的TR1)
5.如果使用中断,需要开启串口中断控制位(IE寄存器)
四、串口通信实验#
4-1 通过单片机每隔一定的时间发送数据给电脑串口工具#
❤ 实验目的:单片机每隔1s向电脑串口工具发送数据1,2,3,4...
代码部分:
#include <REG52.H>
unsigned char number;
//串口初始化函数
void UART_Init()
{
PCON |= 0x80; //1000 0000,使能波特率倍速位SMOD
SCON = 0x50; //0101 0000,方式1:10位异步收发器(8位数据)可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //0010 0000,方式2:定时器1为8位自动重装方式
TL1 = 0xFA; //设定 定时初值 波特率:9600
TH1 = 0xFA; //设定 定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1; //开启中断总允许
ES = 1; //开启串口中断允许
}
//串口发送函数
void uart_send_byte(unsigned char byte)
{
SBUF = byte;
while (!TI); //等待TI标志位为0
TI = 0; //TI必须使用软件清零
}
// 延时单位:100ms
void Delay(unsigned char n) //@11.0592MHz
{
while (n--)
{
unsigned char i, j;
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
}
void main()
{
uart_init ();
while (1)
{
uart_send_byte (number++);
Delay(10); //延时1s
}
}
波特率9600,51单片机晶振fosc=11.0592MHz,计算T1定时器的初始值:
-
公式:
方式1的波特率=[(2^SMOD)/32]*(T1溢出率)&& T1溢出率=fosc/{12*[256-(TH1)]}
-
求值:
9600 = [2^1/32]*{11.0592MHz/[12*(256-TH1)}
即:
9600*16*12=11.0592MHz/(256-TH1)
即:
256-TH1=11.0592MHz/(9600*16*12)
即:
TH1=256-[11.0592MHz/(9600*16*12)]=250 (十进制) = 0xFA(十六进制)
注意:上述公式是能完全整除的,说明晶振频率11.0592MHz不是随意设计的
提示:频率转换,1MHz=10^3^MHz=10^6^MHz
keil 4编译后,将生成的.hex烧录到51单片机
❤ 实验结果
在电脑上打开串口工具软件(即上位机)
4-2 通过电脑串口工具发送一段字符串给单片机,单片机原封不动的发送给电脑串口工具#
❤ 实验目的:电脑串口工具发送一段字符串给单片机,单片机原封不动的发送给电脑串口工具
❤ 实验代码:
#include <REG52.h>
//串口发送函数
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while (!TI); //等待TI标志位为0
TI = 0; //TI必须使用软件清零
}
//串口初始化函数
void UART_Init()
{
PCON |= 0x80; //使能波特率倍速位SMOD
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //方式2:定时器1为8位自动重装方式
TL1 = 0xFA; //设定 定时初值 波特率:9600
TH1 = 0xFA; //设定 定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1; //开启中断总允许
ES = 1; //开启串口中断允许
}
//串口中断函数
void UART_ReceiveByte() interrupt 4
{
unsigned char buff;
buff = SBUF;
SBUF = buff;
UART_SendByte (buff);
while (!RI); //等待RI标志位为0
RI = 0; //RI必须使用软件清零
}
int main(void)
{
UART_Init ();
while (1)
{
}
return 0;
}
keil 4编译后,将生成的.hex烧录到51单片机
❤ 实验结果
作者:caojun97
出处:https://www.cnblogs.com/caojun97/p/16851127.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!