使用stm32f103实现LED闪烁效果(库函数)

简述
  • LED闪烁即是在一定时间间隔内通过改变io口电平,来改变LED的亮灭,以此实现闪烁的效果。
大致步奏
  • 第一步就是要配置io口:
#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的时钟
 
   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);                  //完成初始化    
 }
  • 第二步是要变换io口电平:
/*             变换电平的两个函数         */
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //置低电平  
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);   //置高电平  
  • 第三步为编写延时函数,有两种延时函数的编写方法,一种是根据系统时钟频率让系统"空跑"以达到延时效果;一种是借助于定时器实现高精度延时;
/*系统时钟为72 MHZ,可以大致精确到ms级延时*/
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 ++) {
  	/*当计数器的值减小到0的时候,CRTL寄存器的位16会置1 当置1时,读取该位会清 0*/
     while ( !((SysTick->CTRL)&(1<<16)) );
  }
  SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;// 关闭 SysTick 定时器
}
  • 通过上述三个步奏,可编写以下主函数,实现LED闪烁效果:
int main()
{
   LED_Init();
   while(1) {
      SysTick_Delay_Ms(100); //delay_ms(100);
      GPIO_SetBits(GPIOX, GPIO_Pin_X);
      SysTick_Delay_Ms(100); //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;     //选有效值1,对该场景无影响
 	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStrue);             //完成初始化配置

 	TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);                //使能定时器更新中断
 	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;          //TIM3中断
 	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //IRQ通道使能
 	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级0
 	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;       //响应优先级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;
 		/*清除标志位函数,清除TIM3的更新中断的标志位*/
 		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}
}
  • 在主函数中将时钟周期定为100ms
int main()
{
	LED_Init();
	/*公式T=(arr+1)*(PSC+1)/Tck,即(9999 + 1) * (719 + 1) / 72M = 100 ms*/
    TIM3_Init(10000-1, 720-1);
    while(1);
     
	return 0;
}
以上是对stm32f103实现LED闪烁效果的简单总结,不足之处请在评论区指出
  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值