实例 通过配置 LED 灯和定时器,使所有的 LED 灯间隔 1 秒钟闪烁。
电路分析 打开蓝桥杯开发板的电路图,可以看到板载的 8 个可编程 LED 灯公共端接到 3V3,故 LED 灯均为低电平点亮,另一端通过 HC573 锁存器连接到电路的 H D0-H D7, 由 H D0-H D7 通过跳线帽连接到 M PC8-M PC15,锁存器的使能端 N LE 由跳线帽连接到 M PD2 电路上,LCD 和 LED 共用 PC8-PC15 引脚,当 N LE 为高电平时,此时可以通过 PC8-PC15 改变 LED 灯的状态,当 N LE 为低电平时,无论 PC8-PC15 如何改变,均不会影响 LED 灯的状态。
工程建立 从官方提供的赛点资源中,拷贝 8 - 液晶驱动参考例程,打开其中的工程文件,作为本次的工程基础。
添加库函数 本例中使用到了定时器来控制灯的翻转时间,故要添加以下库函数:
初始化 LED 编写 LED 初始化函数,程序代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void LED_Init (void ) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; GPIO_Init(GPIOD,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=0xFF00 ; GPIO_Init(GPIOC,&GPIO_InitStructure); GPIO_SetBits(GPIOD,GPIO_Pin_2); GPIO_SetBits(GPIOC,0xFF00 ); GPIO_ResetBits(GPIOD,GPIO_Pin_2); }
通常题目要求上电初始化时关闭所有无关外设,开发板在默认状态下 LED 灯为上电点亮,通过程序的 18-23 行实现上电关闭。
配置定时器 下面配置定时器 1 来实现计时功能。 初始化定时器 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 void Timer1_Init (void ) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); TIM_TimeBaseStructure.TIM_Period = 1000 -1 ; TIM_TimeBaseStructure.TIM_Prescaler = 72 -1 ; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter=0 ; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE); TIM_Cmd(TIM1,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0 ; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ClearFlag(TIM1,TIM_FLAG_Update); }
特别提醒 对于高级定时器 TIM1 和 TIM8,一定要对成员变量 TIM_RepetitionCounter 进行配置。 该变量用于配置 TIMx->RCR 寄存器,其作用简单来说就是重复计数,即为重复溢出多少次产生一次溢出中断,其具体作用可参考 STM32F1 数据手册,需要特别注意的是,如果不对该寄存器进行配置,上电的时候寄存器值可是随机的,导致定时结果不准确:
1 TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //使用定时器1和8时要添加这一句
声明 1 秒钟定时标志的全局变量:
配置定时器 1 中断:
1 2 3 4 5 6 7 8 9 10 11 12 13 void TIM1_UP_IRQHandler (void ) { static u16 cnt=0 ; if (TIM_GetITStatus(TIM1,TIM_IT_Update)==SET) { TIM_ClearITPendingBit(TIM1,TIM_IT_Update); if (++cnt>=1000 ) { cnt=0 ; Flag1s=1 ; } } }
修改主程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int main (void ) { u8 LED_Status=0 ; SysTick_Config(SystemCoreClock/1000 ); Delay_Ms(200 ); STM3210B_LCD_Init(); LCD_Clear(Black); LCD_SetBackColor(Black); LCD_SetTextColor(White); Timer1_Init(); LED_Init(); while (1 ) { if (Flag1s) { Flag1s=0 ; LED_Status=~LED_Status; GPIO_SetBits(GPIOD,GPIO_Pin_2); GPIO_WriteBit(GPIOC,0xFF00 ,LED_Status); GPIO_ResetBits(GPIOD,GPIO_Pin_2); } } }
下载测试 将程序通过 Colink 下载到开发板中,可以看到所有的 LED 以 1 秒钟的间隔进行闪烁。