当前位置:网站首页>野火ISO-V2学习
野火ISO-V2学习
2022-08-02 03:28:00 【jualay】
1.带参数的宏定义
下面这段代码是实现单片机上三个LED灯控制的宏定义的原代码
/** the macro definition to trigger the led on or off
* 1 - off
*0 - on
*/
#define ON 0
#define OFF 1
/* 带参宏,可以像内联函数一样使用 */
#define LED1(a) if (a) \
GPIO_SetBits(GPIOB,GPIO_Pin_0);\
else \
GPIO_ResetBits(GPIOB,GPIO_Pin_0)
#define LED2(a) if (a) \
GPIO_SetBits(GPIOF,GPIO_Pin_7);\
else \
GPIO_ResetBits(GPIOF,GPIO_Pin_7)
#define LED3(a) if (a) \
GPIO_SetBits(GPIOF,GPIO_Pin_8);\
else \
GPIO_ResetBits(GPIOF,GPIO_Pin_8)
首先宏定义了ON为0,OFF为1,这是由于单片机的硬件决定的(如下图)。

注:(1)上面意思是: LED1(a) 替换后面的if...else语句,并传递参数;
(2)c语言 中 反斜杠( \)的作用:语义上表示,下一行是上一行的延续。也就是同一行。
当你的代码一行写的时候会太长,需要分行方便显示时,但代码又不能分行时,例如这里的宏定义,只能在一行定义好,那样就可以用过在结尾添加 反斜杠( \) 来换行。表示 接着下一行,就是例子中的整个 if-else 语句都被 反斜杠( \) 连接在同一行,所以替换后就仅仅一行而已。反斜杠( \) 后面不能有任何字符,包括空格。
以LED1(a)为例,上面的代码就可以这样理解了:
#define LED1(a)
if (a)
GPIO_SetBits(GPIOB,GPIO_Pin_0);
else
GPIO_ResetBits(GPIOB,GPIO_Pin_0);2.外部中断
(1)从 main 函数开始分析
int main(void)
{
LED_GPIO_Config();
LED1_ON;
CLI();
SEI();
EXTI_PC13_Config();
while(1)
{
}
}(2)配置中断函数
/**
* @brief 配置 PC13 为线中断口,并设置中断优先级
* @param 无
* @retval 无
*/
void EXTI_PC13_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/* config the extiline(PC13) clock and AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE);
/* config the NVIC(PC13) */
NVIC_Configuration();
/* EXTI line gpio config(PC13) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* EXTI line(PC13) mode config */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
EXTI_InitStructure.EXTI_Line = EXTI_Line13;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿中断
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}(3)NVIC初始化设置
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param 无
* @retval 无
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 配置P[A|B|C|D|E]13为中断源 */
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}(4)抢占优先级和响应优先级
STM32 的中断向量具有两个属性,一个为抢占属性,另一个为响应属性,其属性编号
越小,表明它的优先级别越高。而响应属性则应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达则先处理响应优先级高的中断,响应属性由NVIC_IRQChannelSubPriority参数配置。
(5)NVIC 的优先级组
在配置优先级的时候,还要注意一个很重要的问题,即中断种类的数量。NVIC 只可
以配置 16 种中断向量的优先级,也就是说,抢占优先级和响应优先级的数量由一个 4 位的
数字来决定,把这个 4 位数字的位数分配成抢占优先级部分和响应优先级部分。有 5 组分
配方式 :
第 0 组: 所有 4 位用来配置响应优先级。即 16 种中断向量具有都不相同的响应优先
级。
第 1 组:最高 1 位用来配置抢占优先级,低 3 位用来配置响应优先级。表示有 21=2 种
级别的抢占优先级(0 级,1 级),有 23=8 种响应优先级,即在 16 种中断向量之中,有
8 种中断,其抢占优先级都为 0 级,而它们的响应优先级分别为 0~7,其余 8 种中断向
量的抢占优先级则都为 1 级,响应优先级别分别为 0~7。
第 2 组:2 位用来配置抢占优先级,2 位用来配置响应优先级。即 22=4 种抢占优先
级,22=4 种响应优先级。
第 3 组:高 3 位用来配置抢占优先级,最低 1 位用来配置响应优先级。即有 8 种抢占
优先级,2 种响应 2 优先级。
第 4 组:所有 4 位用来配置抢占优先级,即 NVIC 配置的 24 =16 种中断向量都是只有
抢占属性,没有响应属性。
要配置这些优先级组,可以采用库函数 NVIC_PriorityGroupConfi g(),可输入的参数为
NVIC_PriorityGroup_0 ~ NVIC_PriorityGroup_4,分别为以上介绍的 5 种分配组。
(6)编写中断服务函数
中断服务函数的名字必须要与启动文件startup_stm32f10x_hd.s 中的中断向量表定义一致。
中断函数入口的时候要注意函数名的写法,函数名只有两种命名方法 :
EXTI0_IRQHandler ; EXTI Line 0
EXTI1_IRQHandler ; EXTI Line 1
EXTI2_IRQHandler ; EXTI Line 2
EXTI3_IRQHandler ; EXTI Line 3
EXTI4_IRQHandler ; EXTI Line 4
EXTI9_5_IRQHandler ; EXTI Line 9..5
EXTI15_10_IRQHandler ; EXTI Line 15..10
中断线在 5 之后的就不能像 0 ~ 4 那样只有单独一个函数名,都必须写成EXTI9_5_IRQHandler 和 EXTI15_10_IRQHandler 。 假 如 写 成 EXTI5_IRQHandler 、EXTI6_IRQHandler、EXTI15_IRQHandler 编译器是不会报错的,不过中断服务程序不能工作。
/// IO 线中断,中断口为PC13
//void EXTI13_IRQnHandler(void)
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line13) != RESET) //确保是否产生了EXTI Line中断
{
LED3_TOGGLE;
EXTI_ClearITPendingBit(EXTI_Line13); //清除中断标志位
}
}边栏推荐
- gradle脚本中groovy语法讲解
- 聊聊MySQL的10大经典错误
- 无源域适应(SFDA)方向的领域探究和论文复现(第一部分)
- 【萌新解题】斐波那契数列
- 管理会计(对内)指引、管理会计要素及其具体内容(可能考,考前记一下,推荐记一下四个大点即可)、
- 成本会计的概念、产品成本核算的要求、产品成本核算的对象与成本项目、产品成本的归集和分配(可能考判断)、产品成本计算方法 (三种:产品的品种(品种法),批次(分批法),步骤(分步法))
- Solve the problem that the 5+APP real machine test cannot access the background (same local area network)
- kotlin语法总结(二)
- SyntaxError: unexpected character after line continuation character
- 重点考:金融资产概述、交易性金融资产的概念、交易性金融资产的账务处理(取得、持有。出售)、
猜你喜欢
随机推荐
Windows下MySQL数据库报“ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost:8000‘ (10061)”错误解决
ArrayList LinkList效率对比
深度学习理论:model.fit 函数参数详解
完整安装 Laravel-Admin 框架
Transformer结构解析及常见问题
关于我的项目-微信小程序2(uniapp->wx小程序)
RecyclerView使用和原理解析
kotlin语法总结(一)
2021-09-04 最简单的Golang定时器应用以及最简单的协程入门儿
php的curl函数模拟post数据提交,速度非常慢
VS2017报错:LNK1120 1 个无法解析的外部命令
帧动画和补间动画的使用
保证接口数据安全的10种方案
会计凭证概述、原始凭证、原始凭证的种类、原始凭证的基本内容、原始凭证的填制要求、原始凭证的审核
Binder机制详解(一)
Syncthing文件同步方案完全攻略(亲测有效)
财产清查概述、 全面清查的情况、局部清查的情况、财产清查的方法、财产清查结果的处理
面试知识点整理:Skia 架构的场景渲染
最简单的FRP内网穿透教程
英语每日打卡









