简述
- LED闪烁即是在一定时间间隔内通过改变io口电平,来改变LED的亮灭,以此实现闪烁的效果。
大致步奏
#define GPIOx GPIOA
#define RCC_AHB2Periph_GPIOX RCC_APB2Periph_GPIOA
#define GPIO_PINX GPIO_Pin_9
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_AHB2Periph_GPIOX,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_PINX;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOx, &GPIO_InitStructure);
}
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 第三步为编写延时函数,有两种延时函数的编写方法,一种是根据系统时钟频率让系统"空跑"以达到延时效果;一种是借助于定时器实现高精度延时;
Void delay_ms(uint16_t time)
{
u16 i=0;
while (time--) {
i=12000;
while(i--) ;
}
}
- SysTick也是一个定时器,属于内核的外设,有关的寄存器定义和库函数都在内核相关的库文件core_cm3.h 中,可以借助systick来实现高精度延时。SysTick初始化函数static __INLINE uint32_t SysTick_Config(uint32_t ticks);若参数ticks为SystemCoreClock/1000(SystemCoreClock为系统时钟频率值,此处为72M),此时系统时钟以72M的频率计数至(72M/1000)后,把SysTick下的CTRL寄存器置1,而且读取该值时会将该值置零;周期时间为1(s)/(72M)*(72M/1000)=1(s)/1000=1ms,所以可以实现ms级延时函数。

void SysTick_Delay_Ms(uint32_t ms)
{
uint32_t i;
SysTick_Config(SystemCoreClock/1000);
for (i = 0; i < ms; i ++) {
while ( !((SysTick->CTRL)&(1<<16)) );
}
SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}
- 通过上述三个步奏,可编写以下主函数,实现LED闪烁效果:
int main()
{
LED_Init();
while(1) {
SysTick_Delay_Ms(100);
GPIO_SetBits(GPIOX, GPIO_Pin_X);
SysTick_Delay_Ms(100);
GPIO_ResetBits(GPIOX, GPIO_Pin_X);
}
return 0;
}
其他方式
- 仿照前文systick实现ms级延时的例子,我们也可以通过定时器+中断来实现闪烁效果;即配置定时器并使能中断,让定时器一段时间后进入中断,在中断函数里改变io口电平实现LED闪烁

- 配置代码如下:
void TIM3_Init(u16 arr, u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_TimeBaseInitStrue.TIM_Period = arr;
TIM_TimeBaseInitStrue.TIM_Prescaler = psc;
TIM_TimeBaseInitStrue.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStrue.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStrue);
TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void)
{
static int32_t led_turn = 1;
if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET) {
if(led_turn == 1)
GPIO_SetBits(GPIOX, GPIO_Pin_X);
else
GPIO_ResetBits(GPIOX, GPIO_Pin_X);
led_turn = -led_turn;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
int main()
{
LED_Init();
TIM3_Init(10000-1, 720-1);
while(1);
return 0;
}
以上是对stm32f103实现LED闪烁效果的简单总结,不足之处请在评论区指出