ARM嵌入式学习(二) --- 入门51(中断)

目录

一、GPIO

[1.1 什么是GPIO?](#1.1 什么是GPIO?)

[1.2 GPIO输入类型](#1.2 GPIO输入类型)

[1.3 GPIO输出类型](#1.3 GPIO输出类型)

[1.4 示例:检测P3_2是否为低电平](#1.4 示例:检测P3_2是否为低电平)

二、中断系统

[2.1 中断的概念](#2.1 中断的概念)

[2.2 中断源](#2.2 中断源)

[2.3 中断优先级与嵌套](#2.3 中断优先级与嵌套)

[2.4 中断向量表](#2.4 中断向量表)

[2.5 中断处理流程](#2.5 中断处理流程)

[2.6 示例:外部中断0初始化和使用](#2.6 示例:外部中断0初始化和使用)

1.查手册看外部中断默认是什么电平触发:

2.打开中断总开关:

3.选择外部中断0类型

4.初始化代码示例:

5.外部中断0的使用:

三、定时器

[3.1 定时器的作用](#3.1 定时器的作用)

[3.2 模式选择:](#3.2 模式选择:)

[3.3 定时器0的初始化和使用:](#3.3 定时器0的初始化和使用:)

1.首先将定时器TMOD寄存器的低四位置为0(高四位是定时器1):

2.开始设置定时器工作模式:16位定时器

3.设置计算出的定时器0初值

4.开启三个开关

5.示例定时器0初始化和使用:

四、PWM与蜂鸣器

[4.1 PWM简介](#4.1 PWM简介)

[4.2 应用:无源蜂鸣器发声](#4.2 应用:无源蜂鸣器发声)

[4.3 示例:输出200Hz方波,占空比50%](#4.3 示例:输出200Hz方波,占空比50%)

五、总结


一、GPIO

1.1 什么是GPIO?

GPIO(General Purpose Input Output)即通用输入输出引脚,是单片机与外部世界交互的桥梁。

  • 输入模式:检测引脚电平变化(高/低电平)

  • 输出模式:控制引脚输出高/低电平

1.2 GPIO输入类型

类型 说明
悬空输入 电平不确定,容易受干扰
上拉输入 内部接上拉电阻,默认高电平
下拉输入 内部接下拉电阻,默认低电平
模拟输入 用于ADC采集模拟信号

1.3 GPIO输出类型

类型 说明
推挽输出 可输出强高电平和强低电平
开漏输出 只能输出低电平,高电平需外接上拉电阻

1.4 示例:检测P3_2是否为低电平

复制代码
if ((P3 & (1 << 2)) == 0) {
    // P3_2 为低电平
}

二、中断系统

2.1 中断的概念

中断是指CPU正在执行任务时,收到更紧急的任务请求,暂停当前任务,转而去处理紧急任务,处理完后再返回原任务继续执行。

2.2 中断源

51单片机共有5个中断源

  • 外部中断0(INT0)

  • 外部中断1(INT1)

  • 定时器0

  • 定时器1

  • 串口

2.3 中断优先级与嵌套

  • CPU会根据中断优先级决定先处理哪个中断

  • 51单片机支持最多两层中断嵌套(arm不能嵌套)

2.4 中断向量表

本质上是一个数组,数组中存放的是中断服务函数的入口地址
中断向量:中断向量表中各中断服务函数的标号

2.5 中断处理流程

  1. 中断源发起请求

  2. 检查中断是否开启、是否被屏蔽

  3. 比较优先级

  4. 保护现场(保存当前寄存器)

  5. 执行中断服务函数

  6. 恢复现场,继续执行原任务

2.6 示例:外部中断0初始化和使用

1.查手册看外部中断默认是什么电平触发:

可以得知外部中断0是低电平触发,所以先把外部中断的引脚拉高,查看开发板原理图,找到INT0对应的引脚即P3.2

2.打开中断总开关:

寄存器IE的第八位和第1位置为1

3.选择外部中断0类型

有低电平触发和下降沿触发:

选择下降沿触发,只需要检测一下,而不是一直检测(低电平触发的话只要是低电平就会一直触发中断)

4.初始化代码示例:
复制代码
//初始化
void int0_init(void)
{
    //外部中断引脚拉高
     P3 |= (1<<2);
    //打开CPU中断总开关
    IE |= (1<<7);
    //打开外部中断开关
    IE |= (1<<0);
    //选择外部中断0类型
    TCON |= (1<<0);
}
5.外部中断0的使用:

外部中断对应按键K3

初始化按键:

复制代码
void key_init(void)
{
    
    P3 |= (0x0F <<0);//按键初始化0000 1111 
}

按下按键即触发中断,然后写一个中断函数

注意 interrupt 0一定要写在函数旁边(中断向量表,这个会把我写的函数对应到系统指定的中断0函数中去)

复制代码
void int0_handler(void)		   interrupt 0	//向量0
{
	g_n++ ;
}

三、定时器

3.1 定时器的作用

定时器能够产生一个精准的定时 ,对时序要求严格(高电平和低电平的时间必须是

精准的),常用于延时、PWM生成、计数等场景。

这里简要介绍一下时序图:

3.2 模式选择:

8位自动重装定时器:实际参与计数的只有TL0,当溢出后会将TH0的值再重新装回到TL0

这里选择的定时器模式是16位自增型计数器,从初值开始计数,溢出时触发中断。

  • 计数范围:0 ~ 65535

  • 计数频率 = 晶振频率 / 12(STC8952RC的晶振频率过大,所以用了12分频器)

  • 计数一次时间 = 1 / 计数频率

示例:1ms定时器:

晶振频率:11.0592MHz(STC8952RC)

工作频率:11.0592MHz / 12 = 0.9216MHz

计数一次时间:1 / 0.9216MHz ≈ 1.085μs

1ms所需计数次数:1000μs / 1.085μs ≈ 922

所以初值设置为:65535 - 922 = 64613

3.3 定时器0的初始化和使用:

1.首先将定时器TMOD寄存器的低四位置为0(高四位是定时器1):
复制代码
// 1. 将TMOD寄存器低4位清零
	TMOD &= ~(0x0F << 0);   
2.开始设置定时器工作模式:16位定时器
复制代码
// 2. 设置定时器工作模式:16位定时器
	TMOD |= (1 << 0);
3.设置计算出的定时器0初值
复制代码
	// 3. 设置定时器初值	  64613
	TH0 = g_i >> 8;
	TL0 = g_i;

//TH0是存低四位的数据,TL0是存高四位的数据
4.开启三个开关

开启定时器计数

CPU响应所有中断(总开关)

允许定时器0产生中断(子开关)

复制代码
  // 4. 开启定时器计数
	TCON |= (1 << 4);

	// 5. CPU响应所有中断(总开关)
	IE |= (1 << 7);

	// 6. 允许定时器0产生中断(子开关)
	IE |= (1 << 1);
5.示例定时器0初始化和使用:
复制代码
// 定时器0初始化函数
void timer0_init(void)
{
	// 1. 将TMOD寄存器低4位清零
	TMOD &= ~(0x0F << 0);          

	// 2. 设置定时器工作模式:16位定时器
	TMOD |= (1 << 0);

	// 3. 设置定时器初值	  64613
	TH0 = g_i >> 8;
	TL0 = g_i;

    // 4. 开启定时器计数
	TCON |= (1 << 4);

	// 5. CPU响应所有中断(总开关)
	IE |= (1 << 7);

	// 6. 允许定时器0产生中断(子开关)
	IE |= (1 << 1);
}

当计数到溢出后触发中断,随后执行中断函数:

复制代码
// 外部中断0服务函数
void timer0_handler(void) 	interrupt 1
{
	TH0 = g_i >> 8;  //一定要复位初值,不然定时器触发一次中断后,不会再次触发
	TL0 = g_i;
	   	
  	P2 ^= (1<<5);
}

注意:一定要复位初值,不然定时器触发一次中断后,不会再次触发

四、PWM与蜂鸣器

4.1 PWM简介

PWM(脉冲宽度调制) 脉冲宽度调制,能够产生一个方波,能够让引脚电平周期性发生变化

  • 周期:一个方波所经历的时间(从上升沿/下降沿到下一个上升沿/下降沿 )

  • 占空比:高电平在一个周期内所占的比例

4.2 应用:无源蜂鸣器发声

无源蜂鸣器需要外部提供震荡信号才能发声。通过PWM可以控制其音调和音量

特性 有源蜂鸣器 无源蜂鸣器
内部结构 内置振荡源(多谐振荡器) 没有振荡源,只有线圈和磁铁
驱动方式 通电即响(直流电压) 需要PWM方波驱动(交流信号)
频率控制 固定频率(不可变) 可通过PWM频率改变音调
声音特点 单一频率,声音单调 可发出不同音调,甚至音乐
PDF中描述 "通电后会持续发出固定频率声音" "通电后不会发出声音,需要给定一个震荡"

4.3 示例:输出200Hz方波,占空比50%

周期 = 1 / 200Hz = 0.005s

半个周期 = 0.0025s(到半个周期时定时器0中断触发后翻转电平)

计数次数 = 0.0025s / 1.085μs ≈ 2304(1.085us数值如何得出看上面定时器1ms实现)

初值 = 65535 - 2304 = 63231

在定时器中断中函数中翻转蜂鸣器引脚电平,即可输出200hz方波:

复制代码
// 定时器0服务函数
void timer0_handler(void) 	interrupt 1
{
	TH0 = g_i >> 8; //填蜂鸣器的频率所算出来的初值
	TL0 = g_i;
	   	
  	P2 ^= (1<<5);
}

五、总结

通过本文,我们系统梳理了51单片机的几个核心模块:

  • GPIO:输入输出基础

  • 中断:提升系统响应能力

  • 定时器:精准控制时间

  • PWM:实现波形输出与控制

这些知识点是嵌入式开发的入门必修课,理解它们之后,你将能更轻松地阅读芯片手册、编写底层驱动,甚至开发完整的嵌入式系统。

相关推荐
for_ever_love__2 小时前
Objective-C学习 NSArray 和 NSMutableArray 功能详解
学习·ios·objective-c
Pyeako2 小时前
自然语言学习--bert框架
人工智能·深度学习·学习·bert·lstm·自然语言学习
载数而行52010 小时前
QT的五类布局
c++·qt·学习
载数而行52010 小时前
QT的QString类
c++·qt·学习
zl_dfq11 小时前
Python学习2 之 【数据类型、运算及相关函数、math库】
学习
2301_7811435613 小时前
C语言学习笔记
笔记·学习
Alphapeople14 小时前
Isaac Sim学习
学习
蒸蒸yyyyzwd14 小时前
高并发40问学习笔记
笔记·学习
天若有情67316 小时前
循环条件隐藏陷阱:我发现了「同循环双条件竞态问题」
c++·学习·算法·编程范式·while循环··竞态