【51单片机学习笔记】蜂鸣器、UART串口通信(发送、接收)学习总结
📖今日学习:51单片机蜂鸣器驱动原理、有源/无源蜂鸣器区别;UART串口通信基础概念、寄存器配置、串口发送数据、串口接收数据,中断方式接收。
🔍文章大纲
- 蜂鸣器驱动(有源、无源)
- UART串口通信基础概念
- 51串口相关寄存器详解
- 串口配置完整流程
- 串口数据发送(查询方式)
- 串口数据接收(查询方式 + 串口中断接收)
- ✨学习重点汇总
- ⚠️易错点&踩坑记录
- 📝今日学习小结
1. 蜂鸣器驱动
有源蜂鸣器 VS 无源蜂鸣器
| 类型 | 特点 | 驱动方式 |
|---|---|---|
| 有源蜂鸣器 | 自带振荡源,给直流电平就响 | IO输出高低电平控制鸣叫/停止 |
| 无源蜂鸣器 | 无内部振荡源,需要方波信号才能发声 | 需要输出不同频率方波,可控制音调 |
开发板最常见:有源蜂鸣器 。
硬件电路:一般通过三极管驱动,IO输出低电平三极管导通,蜂鸣器鸣叫;输出高电平停止鸣叫。
sbit定义引脚示例
#include <reg52.h>
sbit beep = P1^5;
//延时函数
void delay_ms(unsigned int t)
{
unsigned int i,j;
for(i = t; i > 0; i--)
for(j = 110; j > 0; j--);
}
void main(void)
{
while(1)
{
beep = 0; //鸣叫
delay_ms(500);
beep = 1; //关闭
delay_ms(500);
}
}
注意:51单片机IO口驱动能力弱,蜂鸣器不能直接由IO口驱动,必须搭配三极管/驱动电路,直接接IO无法响,还可能烧毁IO。
2. UART串口通信基础概念
UART:通用异步收发器,异步串口通信。
- 异步:通信双方没有共用时钟信号线,依靠约定好的波特率进行采样。
- 通信两根线:
TXD发送、RXD接收。- 51单片机:
P3.1(TXD)发送引脚;P3.0(RXD)接收引脚。
- 51单片机:
- 电平:单片机TTL电平(0‑5V);电脑USB转串口为RS232电平,需要USB转TTL模块进行电平转换。
串口一帧数据格式:
起始位(1位低电平) + 8位数据位 + 停止位(1位高电平)
无校验位,51默认模式。
波特率 :每秒传输的比特数,常见:9600、115200。通信双方波特率必须完全一致,否则乱码。
晶振选择:
11.0592M,可以精准生成标准波特率;12M晶振波特率会存在误差,容易乱码,串口项目优先使用11.0592MHz晶振。
3. 51串口核心寄存器
SCON ------ 串口控制寄存器
| 位 | 符号 | 功能 |
|---|---|---|
| SM0 SM1 | 模式选择 | 0 1 → 模式1,8位UART,最常用 |
| REN | 接收使能 | REN=1允许串口接收;REN=0关闭接收 |
| TI | 发送中断标志位 | 发送完一帧硬件置1;软件手动清零TI=0 |
| RI | 接收中断标志位 | 收到一帧硬件置1;软件手动清零RI=0 |
模式1:8位异步UART,使用定时器T1作为波特率发生器。
TMOD 定时器模式寄存器
串口波特率一般使用 T1定时器模式2(8位自动重装模式),专门做波特率发生器。
TH1、TL1
T1自动重装初值,决定波特率;11.0592M晶振,9600波特,TH1 = TL1 = 0xFA。
PCON 电源寄存器
SMOD位:波特率加倍位。
SMOD=1波特率翻倍;SMOD=0不加倍,一般设置为0。
IE中断允许寄存器
ES:串口中断使能位,ES=1开启串口中断;EA:总中断开关,必须置1。
4. 串口初始化完整流程
- SCON设置串口工作模式:模式1
SM0=0 SM1=1;需要接收则REN=1; - TMOD设置T1为模式2(8位自动重装);
- TH1、TL1装入波特率对应的重装初值;
- PCON设置SMOD波特率是否加倍;
- 启动定时器T1:
TR1 = 1; - 如果使用串口中断接收 :打开
ES=1,打开总中断EA=1。
示例:11.0592M晶振,波特率9600,查询收发初始化
void uart_init(void)
{
SCON = 0x50; //模式1,REN=1允许接收
TMOD |= 0x20; //T1模式2,自动重装
TH1 = 0xFA;
TL1 = 0xFA;
PCON &= 0x7F; // SMOD=0 波特率不加倍
TR1 = 1; //启动定时器T1
}
5. 串口发送数据(查询方式)
把要发送的数据写入SBUF寄存器,硬件自动发送;发送完毕硬件将TI置1;软件手动把TI清零。
//发送单字节
void uart_send_byte(unsigned char dat)
{
SBUF = dat;
while(TI == 0); //等待发送完成
TI = 0; //软件清零发送标志位!!
}
//发送字符串
void uart_send_str(unsigned char *str)
{
while(*str != '\0')
{
uart_send_byte(*str);
str++;
}
}
void main(void)
{
uart_init();
while(1)
{
uart_send_str("Hello 51!\r\n");
delay_ms(1000);
}
}
6. 串口接收数据
6.1 查询方式接收
不断循环判断RI标志;硬件收到一帧RI置1;读取SBUF,软件清零RI。
缺点:CPU需要不停轮询,占用CPU,实际项目少用。
unsigned char uart_recv_byte(void)
{
while(RI == 0); //等待接收完成
RI = 0; //软件清零接收标志
return SBUF;
}
6.2 串口中断接收(工程最常用)
串口收到完整一帧,触发串口中断,中断号4。
注意:中断里面读取SBUF,手动软件清零RI。
初始化需要额外开启串口中断:
void uart_int_init(void)
{
SCON = 0x50;
TMOD |= 0x20;
TH1 = 0xFA;
TL1 = 0xFA;
PCON &= 0x7F;
TR1 = 1;
ES = 1; //开启串口中断
EA = 1; //开启总中断
}
unsigned char recv_dat;
//串口中断服务函数,中断号4
void uart_isr(void) interrupt 4
{
if(RI == 1) //接收中断
{
RI = 0; //必须软件清零RI
recv_dat = SBUF; //读取接收到的数据
}
//TI发送中断,发送一般不用中断
}
void main(void)
{
uart_int_init();
while(1)
{
//主循环处理接收到的数据,不阻塞
}
}
✨学习重点
- 分清有源蜂鸣器、无源蜂鸣器区别;有源蜂鸣器高低电平控制鸣叫;无源需要方波。蜂鸣器不能直接IO驱动,需要三极管驱动电路。
- UART异步串口:TXD(P3.1)发送,RXD(P3.0)接收;通信双方波特率必须保持一致。
- 晶振选择:串口优先
11.0592MHz,获取标准波特率;12M波特率存在误差容易乱码。 - 寄存器:SCON串口控制寄存器,模式1(8位UART);
TI发送标志、RI接收标志,硬件置1,软件手动清零,硬件不会自动清零! - 波特率发生器:一般使用T1定时器模式2(8位自动重装)。
- 串口初始化步骤:SCON配置模式 → TMOD配置T1模式 → TH1/TL1装载初值 → TR1启动T1;用中断接收需要开启ES和EA总中断。
- 发送:写SBUF,等待TI,手动清TI。
- 接收两种方式:查询轮询(占用CPU);串口中断接收(实际开发主流),中断号4,读取SBUF后RI手动清零。
⚠️易错点&踩坑记录
- ❌蜂鸣器直接接IO引脚驱动,缺少三极管,蜂鸣器不响,甚至烧毁IO口。
- ❌串口通信两端波特率不一致,直接全部乱码。
- ❌使用12M晶振做串口,波特率误差大,出现乱码,串口优先11.0592M晶振。
- ❌忘记手动清零
TI / RI!硬件只会置1,不会自动清零,不清零第二次收发无法进行,程序卡死。 - ❌T1没有设置模式2,使用模式1,波特率发生器工作异常,乱码。
- ❌忘记
TR1=1开启定时器T1,波特率发生器没有工作,串口完全不能收发。 - ❌使用中断接收忘记打开
ES串口中断允许,或者忘记打开总中断EA=1,收不到数据。 - ❌混淆引脚:TXD(P3.1)发送、RXD(P3.0)接收;硬件接线TX接模块RX,RX接模块TX,交叉连接,接反完全收不到数据。
- ❌串口中断服务函数写错中断号,串口中断是
interrupt 4,写错中断号程序跑飞。 - ❌查询接收放在while死循环阻塞主程序,主循环其他逻辑无法运行;大数据接收优先选择中断方式。
- ❌SMOD波特率加倍位忘记设置,波特率翻倍,导致乱码。
📝今日学习小结
今天学习51单片机蜂鸣器与UART串口通信:
- 掌握有源/无源蜂鸣器的区别,三极管驱动有源蜂鸣器鸣叫。
- UART异步串口通信原理,帧格式,波特率概念;牢记硬件引脚TXD(P3.1)、RXD(P3.0),接线交叉。
- 掌握SCON、TMOD、TH1/TL1、IE等寄存器;串口初始化流程。
- 串口发送:写SBUF,等待TI标志,软件清零TI。
- 串口接收分为查询轮询方式和串口中断接收;工程推荐中断接收,不阻塞主循环;RI必须软件清零。