我们在这里进行GPIO和定时器的测试,把这两个外设功能融合一起主要也是为了比较好展示,定时器属于内部模块,如果只是定时器的定时功能,实际上是不需要任何其他实际端口的,另一方面他也和其他外设比较容易融合。比如我们开头说的开发板板载demo是个LED的翻转演示,用的是延时的方法实现的,这里就可以通过定时器实现非阻塞式的LED闪烁。
GPIO的功能涉及到了具体的引脚,无外乎就是输入和输出功能,输入采集的是外部器件的状态,输出实际上就是控制外部器件的方法。本开发板配备了两个LED作为可控的外部器件,一个用户按键作为输入检测。
LED的输出控制就比较简单了,输出的电平不是高电平就是低电平,这个要和LED的状态相关联,我们看一下LED的原理图:
上图可以查看出,LD1如果需要电量就需要T2导通,而T2的控制信号就是PA5,我们需要知道的是T2的控制引脚通过R29下拉给了一个初始状态,所以当PA5给高电平,LD1就可以点亮。同理分析LD2,情况正好相反,PC9为低电平的时候LD2点亮。
输出引脚配置直接选择输出模式:
用户按键作为输入检测,原理图如下:
按键引脚连接的是PC13,如果我们配置为普通输入,采集的状态会随着按键的状态时时变化,我们操作一次按键实际上希望获取一次操作的信号就好了,这就涉及到了一种外部中断的采集方式,通过上升沿或者下降沿会触发一次,不然一直进行扫描会比较占资源。按键的上下拉配置的电容电阻都没有连接,我们还需要在配置引脚是采用内部弱上下拉的方式实现,按键另一端是地,我们就需要配置成上拉的方式,然后通过下降沿触发外部中断。
引脚需要配置为外部中断:
根据上面的分析配置引脚:
开启对应的中断:
定时器实际上直接进行配置就好,选择一个我们中意的定时器,配置时候注意定时器的时钟,系统时钟配置的是48M,如果想要定时10ms,需要对应乘积为480000:
定时器也是需要开启中断的,在达到计数说触发:
相关模块已经配置完成了,接下来我们看一下软件中是什么样的结构的?
我们可以看到初始化阶段已经添加了对应的模块:
对应的stm32c0xx_it.c中也有了中断处理函数,这里的函数实际上是在启动文件中就已经定义了的,我们可以在里面进行编写,不过目前的方式全部采用回调函数的方式进行的,我们只需要在main.c中重写回调函数就可以,这些回调函数都是弱定义的方式存在的,我们需要编写外部中断和定时器中断的回调函数:
<p>void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)</p><p>{</p><p> if(GPIO_Pin == GPIO_PIN_13)</p><p> {</p><p> LED_Mode++;</p><p> LED_Mode %= 3;</p><p> LED_TimeCnt = 0;</p><p> HAL_GPIO_TogglePin(User_LED1_GPIO_Port, User_LED1_Pin);</p><p> }</p><p>}</p><p>void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)</p><p>{</p><p> if (htim->Instance == TIM17) {</p><p> HAL_IncTick();</p><p> LED_TimeCnt++;</p><p>if(LED_Mode == 0){</p><p>if(LED_TimeCnt >= 10){</p><p>LED_TimeCnt = 0;</p><p>HAL_GPIO_TogglePin(User_LED1_GPIO_Port, User_LED1_Pin);</p><p>}</p><p>}</p><p>else if(LED_Mode == 1){</p><p>if(LED_TimeCnt >= 50){</p><p>LED_TimeCnt = 0;</p><p>HAL_GPIO_TogglePin(User_LED1_GPIO_Port, User_LED1_Pin);</p><p>}</p><p>}</p><p>else if(LED_Mode == 2){</p><p>if(LED_TimeCnt >= 100){</p><p>LED_TimeCnt = 0;</p><p>HAL_GPIO_TogglePin(User_LED1_GPIO_Port, User_LED1_Pin);</p><p>}</p><p>}</p><p> }</p><p>}</p>
上面的程序就是中断处理的回调函数,本次实现的内容都在其中实现了,实现的功能是通过按键的操作实现不同频率的LD1的闪烁,一共三个频率模式循环控制,效果如下:
|