本帖最后由 qintian0303 于 2024-7-1 11:14 编辑
我们在第一部分实现了LED控制和按键的采集,接下来我们体验定时器的基本定时功能,实现LED的闪烁。我们在上一部分的基础上增加定时闪烁功能,例如按键按下时对应的LED开始闪烁,再按下时关闭闪烁功能。主要设计的两部分,一个是定时器的初始化以及中断处理,另一个就是按键控制的逻辑判断。
咱们先看一看板载芯片的定时器资源情况:
这次只是用定时器定时功能,所以选择基础定时器就可以,基础定时器(TIM6 / TIM7)均基于一个 16 位自动重载递增计数器和一个 16 位预分频器。
先看第一部分定时器的初始化,定时10ms:
void MM_TIM6_Init(void)
{
uint32_t TIM6_Clock;
uint16_t Prescaler;
uint16_t Period
NVIC_InitTypeDef NVIC_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
TIM6_Clock = TIM_GetTIMxClock(TIM6);
Period = 10000;
Prescaler = TIM6_Clock/10000/100;
TIM_TimeBaseStructInit(&TIM_TimeBaseStruct);
TIM_TimeBaseStruct.TIM_Prescaler = (Prescaler - 1);
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStruct.TIM_Period = (Period - 1);
TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_Div1;
TIM_TimeBaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStruct);
TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM6, ENABLE);
}
重点是操作,为了实现我们添加了部分标志位:
<article data-content="[{"type":"block","id":"C3ml-1719558559989","name":"code","data":{"wrap":false,"tokensPerLine":[],"language":"","theme":"default"},"nodes":[{"type":"block","id":"VF4X-1719558559988","name":"code-line","data":{},"nodes":[{"type":"text","id":"Wr4c-1719558559987","leaves":[{"text":"uint8_t blink_flag = 0;","marks":[]}]}]},{"type":"block","id":"odNN-1719558645342","name":"code-line","data":{},"nodes":[{"type":"text","id":"JIjd-1719558645341","leaves":[{"text":"uint8_t key1_flag = 0;","marks":[]}]}]},{"type":"block","id":"0alW-1719558646024","name":"code-line","data":{},"nodes":[{"type":"text","id":"I8PT-1719558646023","leaves":[{"text":"uint8_t key2_flag = 0;","marks":[]}]}]},{"type":"block","id":"0Nhu-1719558646026","name":"code-line","data":{},"nodes":[{"type":"text","id":"Iznk-1719558646025","leaves":[{"text":"uint8_t key3_flag = 0;","marks":[]}]}]},{"type":"block","id":"goGI-1719558646028","name":"code-line","data":{},"nodes":[{"type":"text","id":"JQOu-1719558646027","leaves":[{"text":"uint8_t key4_flag = 0;","marks":[]}]}]},{"type":"block","id":"E9zL-1719558818333","name":"code-line","data":{},"nodes":[{"type":"text","id":"2cGX-1719558818332","leaves":[{"text":"uint16_t blink_cnt = 0;","marks":[]}]}]}],"state":{}}]"><div yne-bulb-block="code" data-theme="default" style="white-space:pre-wrap;" data-language="">uint8_t blink_flag = 0;
uint8_t key1_flag = 0;
uint8_t key2_flag = 0;
uint8_t key3_flag = 0;
uint8_t key4_flag = 0;
uint16_t blink_cnt = 0;</div></article>
在外部中断中不在直接操作LED翻转,而是进行标志位的变化,定时器中断中进行定时翻转,在按键状态为1的情况下:
void EXTI4_IRQHandler(void)
{
/* K1 */
if (SET == EXTI_GetITStatus(EXTI_Line4))
{
if(key1_flag == 0)
key1_flag = 1;
else
key1_flag = 0;
EXTI_ClearITPendingBit(EXTI_Line4);
}
}
void TIM6_IRQHandler(void)
{
if (RESET != TIM_GetITStatus(TIM6, TIM_IT_Update))
{
if((blink_flag == 0)&&(key1_flag == 1||key2_flag == 1||key3_flag == 1||key4_flag == 1))
{
blink_cnt++;
if(blink_cnt>=50)
{
blink_flag =1;
blink_cnt = 0;
}
}
TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
}
}
最后在主while进行判断处理:
while (1)
{
if(blink_flag == 1)
{
if(key1_flag == 1)
MM_LED1_Toggle;
if(key2_flag == 1)
MM_LED2_Toggle;
if(key3_flag == 1)
MM_LED3_Toggle;
if(key4_flag == 1)
MM_LED4_Toggle;
blink_flag = 0;
}
}
效果视频如下:
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
|