嵌入式——单片机2

【51单片机学习笔记】蜂鸣器、UART串口通信(发送、接收)学习总结

📖今日学习:51单片机蜂鸣器驱动原理、有源/无源蜂鸣器区别;UART串口通信基础概念、寄存器配置、串口发送数据、串口接收数据,中断方式接收。

🔍文章大纲

  1. 蜂鸣器驱动(有源、无源)
  2. UART串口通信基础概念
  3. 51串口相关寄存器详解
  4. 串口配置完整流程
  5. 串口数据发送(查询方式)
  6. 串口数据接收(查询方式 + 串口中断接收)
  7. ✨学习重点汇总
  8. ⚠️易错点&踩坑记录
  9. 📝今日学习小结

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)接收引脚。
  • 电平:单片机TTL电平(0‑5V);电脑USB转串口为RS232电平,需要USB转TTL模块进行电平转换。

串口一帧数据格式:

起始位(1位低电平) + 8位数据位 + 停止位(1位高电平)

无校验位,51默认模式。

波特率 :每秒传输的比特数,常见:9600115200。通信双方波特率必须完全一致,否则乱码

晶振选择: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. 串口初始化完整流程

  1. SCON设置串口工作模式:模式1 SM0=0 SM1=1;需要接收则REN=1
  2. TMOD设置T1为模式2(8位自动重装);
  3. TH1、TL1装入波特率对应的重装初值;
  4. PCON设置SMOD波特率是否加倍;
  5. 启动定时器T1:TR1 = 1
  6. 如果使用串口中断接收 :打开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)
    {
        //主循环处理接收到的数据,不阻塞
    }
}

✨学习重点

  1. 分清有源蜂鸣器、无源蜂鸣器区别;有源蜂鸣器高低电平控制鸣叫;无源需要方波。蜂鸣器不能直接IO驱动,需要三极管驱动电路
  2. UART异步串口:TXD(P3.1)发送,RXD(P3.0)接收;通信双方波特率必须保持一致。
  3. 晶振选择:串口优先11.0592MHz,获取标准波特率;12M波特率存在误差容易乱码。
  4. 寄存器:SCON串口控制寄存器,模式1(8位UART);TI发送标志、RI接收标志,硬件置1,软件手动清零,硬件不会自动清零
  5. 波特率发生器:一般使用T1定时器模式2(8位自动重装)
  6. 串口初始化步骤:SCON配置模式 → TMOD配置T1模式 → TH1/TL1装载初值 → TR1启动T1;用中断接收需要开启ES和EA总中断。
  7. 发送:写SBUF,等待TI,手动清TI。
  8. 接收两种方式:查询轮询(占用CPU);串口中断接收(实际开发主流),中断号4,读取SBUF后RI手动清零

⚠️易错点&踩坑记录

  1. ❌蜂鸣器直接接IO引脚驱动,缺少三极管,蜂鸣器不响,甚至烧毁IO口。
  2. ❌串口通信两端波特率不一致,直接全部乱码。
  3. ❌使用12M晶振做串口,波特率误差大,出现乱码,串口优先11.0592M晶振。
  4. ❌忘记手动清零TI / RI!硬件只会置1,不会自动清零,不清零第二次收发无法进行,程序卡死。
  5. ❌T1没有设置模式2,使用模式1,波特率发生器工作异常,乱码。
  6. ❌忘记TR1=1开启定时器T1,波特率发生器没有工作,串口完全不能收发。
  7. ❌使用中断接收忘记打开ES串口中断允许,或者忘记打开总中断EA=1,收不到数据。
  8. ❌混淆引脚:TXD(P3.1)发送、RXD(P3.0)接收;硬件接线TX接模块RX,RX接模块TX,交叉连接,接反完全收不到数据。
  9. ❌串口中断服务函数写错中断号,串口中断是interrupt 4,写错中断号程序跑飞。
  10. ❌查询接收放在while死循环阻塞主程序,主循环其他逻辑无法运行;大数据接收优先选择中断方式。
  11. ❌SMOD波特率加倍位忘记设置,波特率翻倍,导致乱码。

📝今日学习小结

今天学习51单片机蜂鸣器与UART串口通信:

  1. 掌握有源/无源蜂鸣器的区别,三极管驱动有源蜂鸣器鸣叫。
  2. UART异步串口通信原理,帧格式,波特率概念;牢记硬件引脚TXD(P3.1)、RXD(P3.0),接线交叉。
  3. 掌握SCON、TMOD、TH1/TL1、IE等寄存器;串口初始化流程。
  4. 串口发送:写SBUF,等待TI标志,软件清零TI。
  5. 串口接收分为查询轮询方式和串口中断接收;工程推荐中断接收,不阻塞主循环;RI必须软件清零。
相关推荐
JNX_SEMI1 小时前
OC5138T 8V~100V超宽输入降压恒流驱动:覆盖12V汽车至72V电动车全场景
单片机·嵌入式硬件
一直C2 小时前
DS18B20数字温度传感器超详细学习笔记|51单片机单总线通信
51单片机·ds18b20·one-wire
xx~t2 小时前
嵌入式——51单片机3
linux·c语言·嵌入式硬件·51单片机
sunoo-2292 小时前
【51单片机实战】温控下位机完整实现:DS18B20采集 + 自定义二进制串口协议 + PWM声光告
笔记·学习·51单片机·串口
云栖梦泽2 小时前
网络设备驱动(1)
linux·arm开发·嵌入式硬件
每天题库3 小时前
客运从业资格证备考:题库里的高频数字题,单独整理不丢分
学习·考试·题库·考证
sunshine22 girl3 小时前
Java学习 java原理
java·开发语言·学习
conlin day3 小时前
石头记的开头,荣府初逢
经验分享·学习·程序人生
m4Rk_3 小时前
【论文阅读】Agent 记忆机制(70):RecMem——只在记忆反复出现时才调用 LLM 做巩固
论文阅读·人工智能·学习·开源·github