目录
一.CubeMX建项目
新建File->Project
选择芯片STM32F103C8,并点击Start Project
sys选择
RCC选择
选择端口输出设置
选择需要的端口,点击设置GPIO_OUTPUT
,我选择的是,PA4,PB1,PC15
Clock Configuration设置
Project Manager设置
创建完成并用keil打开
二、实验
LED流水灯
在main.c的while(1)循环中输入以下代码:
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);
接线图:
效果如下:
用GPIO端口完成2只LED灯的周期闪烁
在main.c文件的while(1)循环中写入:
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
HAL_Delay(100);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
HAL_Delay(100);
接线图:
效果如下;
中断控制LED闪烁
内容:用GPIO端某一管脚接2个开关(用杜邦线模拟代替)。采用中断模式编程,当2分开关接高电平时,对应的两个LED灯停止工作(即停止周期性闪烁),接低电平时,恢复工作。
我用PA5,PC15口接两个LED,PB1口设置为上升和下降沿都触发中断,基本操作与前面的项目相同,唯一不同的是,用到了中断,所以要配置中断,PB1,设置为GPIO_EXTI1
配置EXTI
在" GPIO “参数配置中设置PB1为上升沿触发,内部既不上拉也不下拉,添加用户标签” WAKEUP "(也可以在配置引脚时修改用户标签)。
PA0的" GPIO mode "设置为下降沿触发,内部既不上拉也不下拉,添加用户标签S2。
PA5和PC15两个 LED 灯设置为推挽输出模式,内部既不上拉也不下拉,分别添加用户标签为LED2和LED3。
打开生成的项目,找到stm32f1xx_it.c
在stm32f1xx_it.c文件中找到所定义的外部中断处理函数,鼠标放在‘HAL_GPIO_EXTI_IRQHandler’上按F12可以看到函数原型,外部的两个中断触发后,首先会调用 GPIO 相应引脚的外部中断处理函数
当中断发生时,调用 HAL _ GPIO _ EXTI _ Callback ()函数,但程序中只给出了一个虚函数,需要用户添加应用程序来实现相关功能。
有__weak修饰表示这个函数是弱函数,它可以被同名的函数覆盖(我们需要在用户文件中,自己再定义一个一模一样的函数,只是我们自己定义的函数,不需要指明是弱函数)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)//高电平,停止工作
{
state = 1; // 设置暂停标志
}
if(GPIO_Pin == GPIO_PIN_1)//低电平时,恢复工作
{
state = 0; // 清除暂停标志
}
}
如果按正常的思路就是,在进入中断函数后,判断中断的触发方式,然后做响应的处理,但是由于下降沿触发中断时,要求我们执行LED灯闪烁,按照这种思路那必然要在中断里面写while循环、延时函数,就会导致中断函数的执行时间过长,一般中断里停留的时间不要过长,快进快出,一般中断只是做个标记,具体执行还是放到主函数去执行,不是放在中断函数里面执行。
主函数里面,也就是while(1)里面做标志位的判断并执行相应操作。于是我在主函数里面定义了一个多文件的全局变量state
作为执行led闪烁的标志位(state为1时执行)
关于怎么让多个文件同时使用一个全局变量可参考:
多个文件中如何共用一个全局变量_不同文件定义同名的全局变量-CSDN博客
C语言 多个文件同时使用一个全局变量_c语言多个文件共用一个变量-CSDN博客
或者:
main函数
while (1)
{
if(state==0)
{
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
HAL_Delay(100);
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_15);
HAL_Delay(100);
}
}
效果如下:
led_it_blink
因为在STM32CubeMX里面设置的PA5,PC15默认为低电平,所以按照我的接线图,按复位键后,LED默认点亮,我的红线是接的3.3v,当红线刚接触到PB1口的时候(上升沿),state被置为0,开始让LED闪烁,当红线刚接触到PA0口时发现并没有变化,当红线离开PA0口时(下降沿),主程序的LED闪烁被中止。
三、波形分析
内容:在没有示波器条件下,使用Keil的软件仿真逻辑分析仪功能观察LED管脚的时序波形,分析上面作业按键中断时,LED灯的波形变化情况
设置
点击调试,并选择逻辑分析仪
点击setup,并设置观察引脚
点击run运行
可以看到初始状态为低电平,与我在STM32CubeMX中设置是一致的
当state==0,LED闪烁,PA5和PC15的电位每0.2s变化一次,与代码的电平变化一致
总结:使用HAL库进行LED点灯,不仅实现了基本的硬件控制功能,更是在此过程中掌握了高效、灵活的开发方法,为后续进行更复杂项目开发奠定了坚实基础。
参考资料:多个文件中如何共用一个全局变量_不同文件定义同名的全局变量-CSDN博客