原创 STM学习笔记(8)-用定时器实现荧火虫灯

2010-7-15 15:45 3705 9 9 分类: MCU/ 嵌入式

STM32学习笔记(8)-定时器实现荧火虫灯


       在第6篇笔记中,我用软件延时的方法实现了荧火虫,学了定时器,当然就要用一用定时器了,这里仍是用荧火虫灯为例。


       用ST库所带的例子Tim中的TimBase为例来修改,这个例子的位置以及如何建立工程请参考第7篇笔记,这里就不再重复了,下面简述一下修改的过程。


(1)       由于我的板子上的灯是由PD8~PD11来控制的,因此,要将


void RCC_Configuration(void)


中的:                                               


  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);   //打开GPIOC的时钟


改为


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);      //打开GPIOD的时钟


(2)       将四个通道全部设置为TIM_OCMode_Toggle模式,即将


/* Output Compare Timing Mode configuration: Channel1 *


  TIM_OCInitStructure.TIM_OCMode =   TIM_OCMode_Timing;


改为:


TIM_OCInitStructure.TIM_OCMode =       TIM_OCMode_Toggle;


(3)例子中原来中断产生的频率很低,是不适合于做这种荧火虫灯的,但为了比较,我只改了最后一个值:


__IO uint16_t CCR4_Val = 8192;改为


__IO uint16_t CCR4_Val = 2048;


这样,这个通道的中断频率变为


 CC4 update rate = TIM2 counter clock / CCR4_Val =  3515.6 Hz


(4)       到stm32f10x_it.c中作修改中断处理函数如下:


  uint8_t allCount=16;


  uint8_t upDown1,upDown2,upDown3,upDown4;


void TIM2_IRQHandler(void)


{ static uint8_t Count1,Count2,Count3,Count4;


  static uint8_t hCnt1,hCnt2,hCnt3,hCnt4;


  if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)


  {


    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);


       if(Count1<hCnt1)


       {     GPIO_SetBits(GPIOD, GPIO_Pin_8);  //点亮灯


       }


       else


       {     GPIO_ResetBits(GPIOD, GPIO_Pin_8);      //熄灭灯


       }


       Count1++;


      if(Count1>=allCount)


      {     Count1=0;


             if(upDown1)


              {     hCnt1++;


                     if(hCnt1>=(allCount-1))


                          upDown1=!upDown1;


              }


              else


              {     hCnt1--;


                     if(hCnt1<2)


                            upDown1=!upDown1;


              }


      }


    capture = TIM_GetCapture1(TIM2);


    TIM_SetCompare1(TIM2, capture + CCR1_Val);


  }


  else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)


  {


    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);


      if(Count2<hCnt2)


       {     GPIO_SetBits(GPIOD, GPIO_Pin_9);  //点亮灯


       }


       else


       {     GPIO_ResetBits(GPIOD, GPIO_Pin_9);      //熄灭灯


       }


       Count2++;


      if(Count2>=allCount)


      {     Count2=0;


             if(upDown2)


              {     hCnt2++;


                     if(hCnt2>=(allCount-1))


                          upDown2=!upDown2;


              }


              else


              {     hCnt2--;


                     if(hCnt2<2)


                            upDown1=!upDown1;


              }


      }


    capture = TIM_GetCapture2(TIM2);


    TIM_SetCompare2(TIM2, capture + CCR2_Val);


  }


  else if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)


  {


    TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);


       if(Count3<hCnt3)


       {     GPIO_SetBits(GPIOD, GPIO_Pin_10);       //点亮灯


       }


       else


       {     GPIO_ResetBits(GPIOD, GPIO_Pin_10);    //熄灭灯


       }


       Count3++;


      if(Count3>=allCount)


      {     Count3=0;


             if(upDown3)


              {     hCnt3++;


                     if(hCnt3>=(allCount-1))


                          upDown3=!upDown3;


              }


              else


              {     hCnt3--;


                     if(hCnt3<2)


                            upDown3=!upDown3;


              }


      }


    capture = TIM_GetCapture3(TIM2);


    TIM_SetCompare3(TIM2, capture + CCR3_Val);


  }


  else


  {


    TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);


       if(Count4<hCnt4)


       {     GPIO_SetBits(GPIOD, GPIO_Pin_11);       //点亮灯


       }


       else


       {     GPIO_ResetBits(GPIOD, GPIO_Pin_11);    //熄灭灯


       }


       Count4++;


      if(Count4>=allCount)


      {     Count4=0;


             if(upDown4)


              {     hCnt4++;


                     if(hCnt4>=(allCount-1))


                          upDown4=!upDown4;


              }


              else


              {     hCnt4--;


                     if(hCnt4<2)


                            upDown4=!upDown4;


              }


      }


    capture = TIM_GetCapture4(TIM2);


    TIM_SetCompare4(TIM2, capture + CCR4_Val);


  }


}


即将LED点亮的过程分成16(allCount)份,第一次是点亮1/16时间,而15/16的时间都是灭着的,这个1是变量hCnt来控制的,随着中断16次完毕,hCnt会加1,于是第二个周期来了,在这个周期中,LED会被点亮2/16,而14/16的时间是灭着的,依次类推,到最后会有15/16的时间被点亮,而1/16的时间是灭着的,于是就产生了渐亮效果。请原谅我在学习时的代码写得很粗糙了。


由于TIM2_CH1通道的中断频率是:


 CC1 update rate = TIM2 counter clock / CCR1_Val = 146.48 Hz


再除以16那就是:9.1Hz,闪烁现像应该很明显了。


将代码写入芯片,事实确实是TIM2_CH1(146.48Hz)和TIM2_CH2(219.7Hz)的闪烁极明显,几乎看不出渐亮的过程,亮度高时几乎全亮,亮度低时一阵狂闪。而TIM2_CH4则效果十分明显,达到了预计的要求。TIM2_CH3(439.4)呢,则介于两者之间,可以看出渐亮和渐灭的效果,但是也有很明显的闪烁效应。但在示波器(传统示波器)上,却是TIM2_CH3的效果最好,逐渐伸缩的PWM波形看得清清楚楚。


接下来就要研究TIM的PWM方式了,用PWM方式来实现同样的功能,应该很有趣。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
9
关闭 站长推荐上一条 /3 下一条