Linux入门DAY40(51 单片机入门:GPIO、中断、定时器、PWM、蜂鸣器完整梳理)

#51单片机 #GPIO #定时器 #中断 #PWM #单片机入门

前言

最近在学习 51 单片机基础,把 GPIO、外部中断、定时器、PWM、蜂鸣器这些核心概念做一次系统整理,同时结合代码踩坑记录,适合刚入门单片机的同学参考。硬件以 STC89C51/AT89C51 为主,晶振常用12MHZ和11.0592MHZ。

知识点来源课堂笔记,包含基础概念、计算公式、代码示例、常见踩坑点。

一、GPIO 通用输入输出

GPIO(General Purpose Input/Output)通用目的输入输出,是单片机和外部设备交互最基础的方式。

1. 输入模式

作用:检测引脚电平变化,典型应用:按键检测、外部电平信号采集。

51 是准双向口:做输入前,必须先向引脚写 1,内部上拉开启,才能正确读取外部电平。

复制代码
// 将P1.4~P1.7设置为输入,写1开启上拉
P1 |= (0x0F << 4);
P3 |= (1 << 5);

按键按下,引脚被拉到 GND,引脚读到低电平;按键松开,内部上拉维持高电平。

其他 MCU (STM32) 输入模式区分:上拉输入、下拉输入、浮空输入、模拟输入;输出模式:推挽输出、开漏输出、复用推挽、复用开漏。51 没有这么多模式,为准双向 IO。

2. 输出模式

输出高低电平,控制 LED、继电器、蜂鸣器等外设。

按键驱动踩坑回顾

之前写独立按键代码遇到两个致命 BUG:

  1. return 0写死返回值,无论哪个按键按下永远返回 0;
  2. 错误使用P1 & (1<<8),P1 口只有 P1.0~P1.7,没有 P1.8;
  3. 缺少机械按键软件消抖,会出现误触发。

✅ 核心要点:读引脚前写 1;增加延时消抖;正确 return 按键编号。

二、中断系统

什么是中断

当 CPU 正在执行一个任务,外部紧急事件到来打断当前程序;CPU 保存现场,跳转执行中断服务函数;处理完毕回到原来代码继续执行。

51 单片机 5 大中断源

  1. 外部中断 0:P3.2
  2. 外部中断 1:P3.3
  3. 定时器 0 中断
  4. 定时器 1 中断
  5. 串口中断
  • 外部中断:引脚电平变化触发中断。
  • 中断优先级:多个中断同时到来,优先处理优先级高的中断。
  • 中断嵌套:处理中断过程中可以响应更高优先级中断,51 最多两层嵌套。

中断完整处理流程

  1. 中断源发起中断请求;
  2. 判断 CPU 总中断开关、该中断源子开关是否打开;
  3. 判断中断优先级;
  4. 保护现场;
  5. 执行中断服务函数;
  6. 恢复现场,回到主程序断点继续运行。

IE 寄存器:中断允许寄存器;中断向量:相当于标号,CPU 依靠中断向量找到对应的中断服务函数。

外部中断 0 简单初始化模板:

复制代码
void int0_init(void)
{
    // IT0、EX0、EA 配置,开启外部中断0
}

三、定时器原理

定时器用来做精准定时,不依赖软件延时,不阻塞主循环。

51 定时器模式 1 为16 位自增计数器 ,THx存高 8 位,TLx存低 8 位;从初值不断向上计数,计到 65535 再加 1 就溢出,溢出触发定时器中断。

时钟计算(重点公式)

51 单片机:机器周期 = 晶振频率 /12

  • 晶振12MHZ:机器周期 = 12M/12 = 1MHZ,计数 + 1 花费时间:1us
  • 晶振11.0592MHZ:机器周期≈0.9MHZ,计数 + 1≈1.1us

定时时间 = 需要计数次数 × 机器周期 定时器初值 = 65535 − 需要计数次数

示例:1ms 定时计算

1ms = 1000us

  1. 12MHZ 晶振: 计数次数 = 1000us /1us =1000 初值 = 65535 −1000 = 64535 TH0 = 64535 >> 8; TL0 = 64535;
  2. 11.0592MHZ 晶振: 计数次数 = 1000 /1.1 ≈909 初值 = 65535 −909 =64626

还有 8 位自动重装模式,多用于串口波特率生成。

定时器工作流程:

  1. 设置 TH0、TL0 装载初值
  2. 打开定时器,开始计数
  3. 计数器不断自增cnt++
  4. 计数到 65535 溢出,向 CPU 申请定时器中断

四、PWM 脉冲宽度调制

PWM 输出周期性方波,不断翻转引脚电平。

  • PWM 周期:一个完整方波的时间,从上升沿到下一次上升沿。
  • 占空比:一个周期内高电平时间占整个周期的百分比。

应用场景:LED 亮度调节、屏幕背光调节、无源蜂鸣器发声、电机调速。

例题:无源蜂鸣器 200HZ,占空比 50%

周期 T = 1 / 200HZ = 0.005s 50% 占空比:高电平 = 2.5ms,低电平 = 2.5ms 12M 晶振,1us 计数一次 计数次数 = 2500 初值 = 65535 − 2500 = 63035

再举例:400HZ,占空比 50% 周期 = 1/400 =0.0025s;半周期 = 0.00125s 计数次数 = 1250;初值 = 65535‑1250=64285

五、蜂鸣器

  1. 有源蜂鸣器:自带振荡源,通电直接发出固定频率声音,只需要给高低电平控制开关。
  2. 无源蜂鸣器:内部没有震荡源,通电不会响;需要输入一定频率的方波(定时器 + PWM)才可以发声;改变 PWM 频率可以改变音调。

想要无源蜂鸣器发出指定音调:定时器输出对应频率 PWM,设置 50% 占空比驱动。

六、学习总结

  1. 51 准双向 IO 作为输入,一定要先写 1,否则读不到正确电平;
  2. 中断:中断请求→开关判断→优先级→保护现场→中断服务函数→恢复现场;
  3. 定时器核心:机器周期计算,初值公式 65535-计数次数;
  4. PWM 依靠定时器定时翻转 IO,改变频率和占空比实现调光、无源蜂鸣器发声;
  5. 机械按键必须做消抖处理,延时消抖简单,但是阻塞程序;项目中优先用定时器做非阻塞消抖。
相关推荐
jianqiang.xue11 分钟前
【CStackGUI 实战】画板 drawpad:鼠标拖拽作图、撤销 / 重做、导出 PNG
单片机·嵌入式·cstackgui·c语言gui·可视化拖拽
新晨单片机设计40 分钟前
S022A-基于STM32单片机音乐盒(数码管显示)【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·音乐盒
深圳老胡1 小时前
STM32 MCU 国产替代型号简介
笔记·stm32·单片机·代码规范
殷忆枫1 小时前
基于STM32的独居老人语音/一键双模紧急呼救系统设计与实现
stm32·嵌入式硬件·xcode
袁章根2 小时前
基于瑞昱RTL8367S交换机电路设计(一)
网络·嵌入式硬件·硬件架构·硬件工程
深圳市恒锐丰科技杨生2 小时前
EG44273 20V 低压单通道低侧栅极驱动芯片|屹晶 EGmicro
嵌入式硬件·硬件工程
搁浅小泽3 小时前
通用二极管选型设计规范
单片机·嵌入式硬件·设计规范
HRTOS3 小时前
HRTOS 4.0 将长期维护:为什么版本号不再频繁变化
经验分享·git·单片机·51单片机
深圳老胡3 小时前
STM32 在 VSCode 下 -O0 与 -Os 编译条件的区别
笔记·stm32·单片机·代码规范
智感子8 小时前
测控链路:从传感器到上位机
人工智能·嵌入式硬件·fpga开发