我们板子第一次上电的时候看到的就是LED的闪烁实验,而且还可以通过按键来调整闪烁的频率,这个板载demo的效果,两个LED交替闪烁,一般板载的demo都是通过延时的方式实现的。这次我们将通过定时的方式实现两个LED的同频闪烁,通过外部中断的方式采集按键,调整同频闪烁的频率。
我们先看一下需要使用的硬件资源:
LED:
按键:
GPIO的功能专注于具体引脚的实现,涵盖输入与输出两大核心方面。输入功能主要用于采集外部器件的状态信息(例如按键状态),而输出功能则实现对外部器件的有效控制(LED的控制)。本开发板装备了两个LED灯作为可操控的外部器件实例,同时配备一个用户按键,用于输入信号的检测。简单分析一下原理图,LD1事业绿灯,想要点亮需要PA5输出高电平,LD2为蓝灯,要点亮需要PC9输出低电平。按键按下的时候另一端是地,也就是低电平,所以对应PC13引脚的初始状态要为高电平,不过硬件中R34并没有连接,我们需要通过引脚配置内部上拉。
定时器是MCU的内部模块,通过精准计数进行计时,这就涉及到时钟的配置来计算定时器参数。
接下来我们基于板卡创建工程:
我们先看一下基于STM32Cube的模块配置,由于引脚的多样性,我们可以在引脚上直接操作:
接下来配置三个引脚,一个按键,两个LED:
配置定时器模块前先看一下时钟配置,并修改为24M,最大支持48M:
接下来配置定时器,我们选用的是定时器14,是一个普通定时器,配置的参数也比较少,定时1ms:
接下来是中断配置,实际上我们在上面的具体模块配置的时候就可以进行中断配置,也可以统一开启:
到这里硬件方面的配置已经基本完成,我们开始软件方面的操作,实际上我们实现的功能也是非常基础了,初始化和定时处理部分都已经添加了:
我们创建两个变量:
- uint16_t LED_TimeCnt_limit = 0;
- uint16_t TimeCnt = 0;
复制代码 LED的闪烁就是通过判断TimeCnt是否等于或者大于LED_TimeCnt_limit进行LED的状态翻转。
我们需要做的就是编写对应的回调函数:
- void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
- {
- if(GPIO_Pin == GPIO_PIN_13)
- {
- LED_TimeCnt_limit += 500;
- TimeCnt = 0;
- if(LED_TimeCnt_limit > 1500 )
- LED_TimeCnt_limit = 500;
- }
- }
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if (htim->Instance == TIM14) {
- HAL_IncTick();
- TimeCnt++;
- if(TimeCnt > LED_TimeCnt_limit)
- {
- HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
- HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
- TimeCnt = 0;
- }
- }
- }
复制代码 这样我们就通过定时器实现的了LED的翻转控制,这个时候我们加入串口的控制,实在是串口和这种多模式的控制太搭了,我们可以通过串口实现同样的翻转控制命令,同时也可以通过串口打印当前状态,我们试一下加入模式变量,因为要实现同步控制,必须按键和串口命令控制的对象是同一个。
配置串口2模块:
实际上在生成工程的的时候这个模块就配置了,估计当成必备选项了,行为这个串口连接的STlink:
我们先实现一下printf打印功能,加入一下代码即可:
- #if defined(__ICCARM__)
- __ATTRIBUTES size_t __write(int, const unsigned char *, size_t);
- #endif /* __ICCARM__ */
- #if defined(__ICCARM__)
- /* New definition from EWARM V9, compatible with EWARM8 */
- int iar_fputc(int ch);
- #define PUTCHAR_PROTOTYPE int iar_fputc(int ch)
- #elif defined ( __CC_ARM ) || defined(__ARMCC_VERSION)
- /* ARM Compiler 5/6*/
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #elif defined(__GNUC__)
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #endif /* __ICCARM__ */
复制代码 然后将printf与串口2关联:
- PUTCHAR_PROTOTYPE
- {
- /* Place your implementation of fputc here */
- /* e.g. write a character to the USART3 and Loop until the end of transmission */
- HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);
- return ch;
- }
复制代码 这个时候我们就可以用使用printf打印功能了。
串口的接收依然使用的是回调函数的方式,同时修改按键控制内容:
- void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
- {
- if(GPIO_Pin == GPIO_PIN_13)
- {
- LED_Mode++;
- LED_TimeCnt_limit = 500+500*LED_Mode;
- TimeCnt = 0;
- if(LED_TimeCnt_limit > 1500 )
- {
- LED_Mode = 0;
- LED_TimeCnt_limit = 500;
- }
- printf("New Mode: %d\n\r",LED_Mode);
- }
- }
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart->Instance==USART2)
- {
- if(UART2_RXData == 0x00||UART2_RXData == 0x01 || UART2_RXData == 0x02)
- {
- LED_Mode = UART2_RXData;
- printf("New Mode: %d\n\r",LED_Mode);
- LED_TimeCnt_limit = 500+500*LED_Mode;
- TimeCnt = 0;
- }
- HAL_UART_Receive_IT(&huart2, &UART2_RXData, 1);
- }
- }
复制代码 整体的效果如下,我们将操作过程和串口控制过程通过动图的方式进行展示:
整个对应的串口反应:
|