你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32 普通定时器

[复制链接]
大碗刚 发布时间:2017-12-26 14:25
本帖最后由 大碗刚 于 2017-12-27 09:01 编辑

转载于whsh304的博客
STM32 普通定时器         (2011-03-22 09:37:59)[url=]转载[/url]

标签: 杂谈分类: STM32学习笔记

STM32 系列的 CPU,有多达 8 个定时器,其中 TIM1 和 TIM8 是能够产生三对 PWM 互补输出的高级定时器,常用于三相电机的驱动,它们的时钟由 APB2的输出产生。其它 6 个为普通定时器,时钟由 APB1 的输出产生。如图1.
当 APB1 的预分频系数为 1 时,这个倍频器不起作用,定时器的时钟频率等于 APB1 的频率;当 APB1
的预分频系数为其它数值(即预分频系数为 2、4、8 或 16)时,这个倍频器起作用,定时器的时钟频率等于 APB1 的频率两倍。
当 AHB=72MHz 时,APB1 的预分频系数必须大于 2,因为APB1 的最大频率只能为 36MHz。如果 APB1 的预分频系数=2,则因为这个倍频器,TIM2~7 仍然能够得到 72MHz 的时钟频率。
一、通用定时器
定时器编程,就是中断的编程。因为使用定时器必定要使用到中断(pwm没用到中断)。
步骤一   系统配置 SystemInit();,包括时钟 RCC 的配置,倍频到 72MHZ。
步骤二   GPIO 的配置,使用函数为 GPIO_Config();         输出LED对应的引脚以及输出模式
步骤三   嵌套中断控制器的配置
关键点是NVIC_InitStructure.NVIC_IRQChannel = TIMx_IRQChannel;      //通道
其它的配置都差不多。
步骤四   定时器的初始化配置,使用 Timer_Config();。OK,关键部分出来了。(来自芯达)
我们来看下实现过程:
void Timer_Config(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
TIM_DeInit(TIM2);
TIM_TimeBaseStructure.TIM_Period=2000;    //自动重装载寄存器的值
TIM_TimeBaseStructure.TIM_Prescaler= (36000 - 1);         //时钟预分频数
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;     //采样分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//清除溢出中断标志
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2, ENABLE);
/开启时钟
}
我们每个语句都来解释一下。首先我们想使用定时器,就必须使能定时器的时钟,这就是函 CC_APB1PeriphClockCmd();  ,  通  过  它  开  启CC_APB1Periph_TIM2。TIM_DeInit( TIM2);  该函数主要用于复位 TIM2 定时器,使之进入初始状态。之后我们对自动重装载寄存器赋值,TIM_Period 的大小实际上表示的是需要经过 TIM_Period 次计数后才会发生一次更新或中断。接下来需要设置时钟预分频数IM_Prescaler,这里有一个公式,我们举例来说明:例如时钟频率=72MHZ/(时钟预分频+1)。说明当前设置的这个 TIM_Prescaler,直接决定定时器的时钟频率。通俗点说,就是一秒钟能计数多少次。比如算出来的时钟频率是 2000,也就是一秒钟会计数 2000 次,而此时如果 TIM_Period 设置为 4000,即 4000 次计数后就会中断一次。由于时钟频率是一秒钟计数 2000 次,因此只要 2 秒钟,就会中断一次。
步骤五   编写中断服务程序。同样需要注意的,一进入中断服务程序,第一步要做的,就是清除掉中断标志位。由于我们使用的是向上溢出模式,因此使用的函数应该是:TIM_ClearITPendingBit(TIM2 ,TIM_FLAG_Update);。芯达 STM32开发板实现的中断服务程序如下:
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) {
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
switch(state){
case 0:

GPIO_ResetBits(GPIOB , GPIO_Pin_8);
GPIO_SetBits(GPIOB, GPIO_Pin_9);
GPIO_SetBits(GPIOE, GPIO_Pin_0);
GPIO_SetBits(GPIOE, GPIO_Pin_1);
break;
...
default:
break;
}
if(++state >= 4){      //state在中断函数中定义为全局变量
state = 0;
}
}
}
二、输出比较模式
1.   选择计数器时钟(内部,外部,预分频器)
2.   将相应的数据写入TIMx_ARR和TIMx_CCRx寄存器中
3.   如果要产生一个中断请求和/或一个DMA请求,设置CCxIE位和/或CCxDE位。
4.   选择输出模式,例如:必须设置OCxM=’011’、OCxPE=’0’、CCxP=’0’和CCxE=’1’,当计数器CNT与CCRx匹配时翻转OCx的输出管脚,CCRx预装载未用,开启OCx输出且高电平有效。
5.   设置TIMx_CR1寄存器的CEN位启动计数器
TIMx_CCRx寄存器能够在任何时候通过软件进行更新以控制输出波形,条件是未使用预装载寄存器(OCxPE=’0’,否则TIMx_CCRx影子寄存器只能在发生下一次更新事件时被更新)。下图给出了一个例子。入图2.
file:///C:\Users\lenovo\AppData\Roaming\Tencent\Users\974670111\QQ\WinTemp\RichOle\JR_$B}_I4UT8XL]KINAK%$1.png
程序:(库里有提供)
int main(void)
{

  RCC_Configuration();

  NVIC_Configuration();

  GPIO_Configuration();


  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler =0;      //时钟频率
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  TIM_PrescalerConfig(TIM3, 4, TIM_PSCReloadMode_Immediate);  // TIM 预分频值即时装入

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;  //TIM_OCMode 选择定时器模式:TIM 输出比较时间模式
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;     //设置了待装入捕获比较寄存器的脉冲值
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // TIM 输出比较极性高
  TIM_OC3Init(TIM3, &TIM_OCInitStructure);  //根据 TIM_OCInitStruct 中指定的参数初始化外设 TIMx
  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);   //失能 TIMx 在 CCR3 上的预装载寄存器

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
  TIM_OC4Init(TIM3, &TIM_OCInitStructure);   //根据 TIM_OC4InitStruct 中指定的参数初始化外设 TIM3
  TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable); //失能 TIMx 在 CCR4 上的预装载寄存器

  TIM_ITConfig(TIM3, TIM_IT_CC3 | TIM_IT_CC4 , ENABLE);

  TIM_Cmd(TIM3, ENABLE);
  while (1);
}
中断it.c中
void TIM3_IRQHandler(void)
{
  if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
   
    GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_0)));//设置或者清除指定的数据端口位:取反
    capture = TIM_GetCapture3(TIM3);   //获得 TIM3 输入捕获 3 的值
    TIM_SetCompare3(TIM3, capture + CCR3_Val); //设置 TIM3 捕获比较 3 寄存器值
  }
  else if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
   
    GPIO_WriteBit(GPIOB, GPIO_Pin_1, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_1)));
    capture = TIM_GetCapture4(TIM3);
    TIM_SetCompare4(TIM3, capture + CCR4_Val);
  }
}
三、PWM输出
脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。
在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1)或’111’(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。必须设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄存器,最后还要设置TIMx_CR1寄存器的ARPE位使能自动重装载的预装载寄存器。
OCx的极性可以通过软件在TIMx_CCER寄存器中的CCxP位设置,它可以设置为高电平有效活或低电平有效。TIMx_CCER寄存器中的CCxE位控制OCx输出使能。
在PWM模式(模式1或模式2)下,TIMx_CNT和TIM1_CCRx始终在进行比较,(依据计数器的计数方向)以确定是否符合TIM1_CCRx≤TIM1_CNT或者TIM1_CNT≤TIM1_CCRx。如图3.
程序:
int main(void)
{

  RCC_Configuration();

  GPIO_Configuration();


  TIM_TimeBaseStructure.TIM_Period = 999;  //在下一个更新事件装入活动的自动重装载寄存器周期的值
  TIM_TimeBaseStructure.TIM_Prescaler = 0; //  设置了用来作为 TIMx 时钟频率除数的预分频值
  TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置了时钟分割
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  //TIM_OCMode
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;      //设置了待装入捕获比较寄存器的脉冲值
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM_OCPolarity :TIM 输出比较极性高
  TIM_OC3Init(TIM3, &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能或者失能 TIM3 在 CCR3 上的预装载寄存器

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
  TIM_OC4Init(TIM3, &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

  TIM_Cmd(TIM3, ENABLE);
  while (1)
  {}
}
它不需要中断程序。输出的是占空比为50%和25%的方波信号。


1.png
2.png
3.png

评分

参与人数 1 ST金币 -5 收起 理由
zero99 -5 图挂了,也太不认真了

查看全部评分

收藏 评论0 发布时间:2017-12-26 14:25

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版