基于正点原子探索者开发板(STM32F407ZGT6)
代码文件:
链接:https://pan.baidu.com/s/1PsnWg_g7Dty-eOfZP8iC_Q?pwd=hy9g
提取码:hy9g
一、GPIO基本原理
GPIO:通用输入输出端口
可以理解为一个输出电平的点,你可以让他输出高电平或低电平,并可以设置上拉下拉(默认高电平、默认低电平)
工作模式分为四个大类:输入模式,输出模式,复用模式、模拟输入输出
输入模式:捕获电平变化
输出模式:控制电平变化,选择推挽模式,开漏模式用于通信之中
复用模式:其他外设占用该引脚
模拟输入输出:AD and DA模式专用
二、cubemx配置——GPIO
目标:使用GPIO的改变电平功能使LED灯进行闪烁
找到原理图中的LED(不同板子引脚使用不一样),查到需要控制PF9,PF10即可
在右下角选择PF9,PF10,设置为输出模式
选择初始电平为高电平:初始LED灭
不上拉也不下拉:由于我们一直控制着电平变化,所以无所谓,单片机采用的是弱上下拉,如果我们控制了引脚,则约等于设置了也无效果
User Label:写为对应的LED,这样会非常方便移植,例如你想换个引脚来控制外部LED,那么就可以直接把那个引脚的User Label改为对应LED的名字,代码不需要改变
这样GPIO控制引脚的设计就设计完成了,生成代码即可。
三、代码编写——GPIO
GPIO的API
DeInit:使对应GPIO引脚恢复为默认的配置
Init:使用结构体来初始化GPIO(cubemx会配置好,不需要再配置)
ReadPin:读取对应GPIO引脚的电平状态
WritePin:设置对应GPIO引脚的电平状态
TogglePin:翻转电平状态
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
可以看到,当我们使用UserLabel之后,对应的GPIO宏定义就是被重定义为更一般的名称,移植代码会变得非常方便。
代码实现
HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);
HAL_Delay(500);
注意:要在user code begin while与user code begin end之间写代码,不然修改cubemx重新生成代码之后就会被清楚。
四、EXTI基本原理
EXTI:外部中断
外部中断的作用:就是可以检测电平的变化,检测到之后进入中断回调函数,在该回调函数中,实现我们要实现的功能。
中断触发方式:上升沿触发、下降沿触发和双边沿触
上升沿触发:当PA0从低电平跳变到高电平,则会自动触发EXTI0的中断,其他两种类似
它把每个GPIO相同引脚号分配为一组,用一个多路选择器选出一个,来作为EXTI引脚,例如用PA0做EXTI引脚后PB0就无法使用了,所以最多16个外部中断。EXTI所管理的16个外部中断线只提供7个中断通道。EXTI0-EXTI4有独立的中断通道,独立的中断处理函数。EXTI5-EXTI9共享1个中断通道,共享中断处理函数,EXTI10-EXTI15共享1个中断通道,共享中断处理函数。
代码执行过程:
可以看到,中断通用处理函数中会先判断是否有中断,然后帮我们清除中断标志位,所以我们只管判断是哪个中短线触发的然后编写执行代码即可。
中断回调函数弱若定义的,我们可以在main下面重写一下,就可以自己配置中断回调函数了。
五、cubemx配置——EXTI
目标:利用按键来改变GPIO引脚变化,并设置EXTI检测电平变化,回调函数中来改变LED灯亮灭,用KEY0来同时改变LED0、LED1
找到原理图中的KEY:
选择GPIO_EXTI4功能
按照原理图,按下按键后引脚被拉到低电平,那么我们应该选择上拉模式,让他默认为高电平,然后检测它的下降沿。
NVIC使能EXTI4的中断线
六、代码编写——EXTI
EXTI的API
HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
代码实现
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == KEY0_Pin) //按键按下
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
}
}
}
注意:
HAL_Delay函数本质也是打断程序去执行延时操作,那么,就一定要让系统滴答定时器抢占优先级高于外部中断的抢占优先级(数字越小级别越高),下面是配置优先级步骤:
先修改为抢占优先级与响应优先级各用2位配置(可以不改)
默认系统滴答定时器是最低,我们要把它改为1,然后外部中断比它低一个等级——2即可
有什么bug直接发在评论区