stm32-3-INTERRUPT-2


1 输出比较

  1. 定时器通过对预设的比较值(CCR寄存器,输入捕获/输出比较寄存器)与定时器计数器CNT的值做匹配比较之后,并依据相应的输出模式从而实现各类输出。如PWM输出、电平翻转、单脉冲模式、强制输出等。高级定时器和通用定时器都具有4个输出比较通道, 且高级定时器的前3个通道额外拥有死区生成和互补输出的功能。

  2. PWM:脉冲宽度调制。对于惯性系统,可以通过对脉冲的宽度进行调制,从而实现等效的模拟参量,可以理解为一般只能输出3.3V(高电平)或0V(低电平),而通过PWM则可以获得等效的0-3.3V之间的电压,类比交流电中的有效电压。常用于OLED屏幕亮度调节、电机控速等。

    • 频率:$1/T_s$
    • 占空比:$T_{on}/T_s$
    • 分辨率:占空比变化步长,如占空比最小的变化的细密度.
  3. 参数计算

  • 频率: f = CK_PSC/(PSC+1)/(ARR+1)
  • 占空比:CCR/(ARR+1)
  • 分辨率:1/(ARR+1)

2 初始化

  1. 使能时钟
  2. 选择时钟源
  3. 配置时基单元
  4. 配置输出比较单元
  5. 配置对应的GPIO口为复用推挽输出
  6. 运行控制

3 PWM库函数实现

  1. 使能时钟
  2. 选择时钟源
  3. 配置时基单元
  4. 配置输出比较单元
  • 函数1-5
    • 函数原型
      • 函数1void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
      • 函数2void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
      • 函数3void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
      • 函数4void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    • 输入:TIMx选择定时器编号,TIM_OCInitStruct指向定时器输出比较初始化结构体的指针,结构体定义如下:
      typedef struct
      {
      uint16_t TIM_OCMode;        // 设置比较模式
      
      uint16_t TIM_OutputState;   // 设置输出使能
      
      uint16_t TIM_OutputNState;  // 与上边一样,高级定时器
      
      uint16_t TIM_Pulse;         // 配置CCR
      
      uint16_t TIM_OCPolarity;    // 配置极性
      
      uint16_t TIM_OCNPolarity;   // 与上边一样,高级定时器
      
      uint16_t TIM_OCIdleState;  
      
      uint16_t TIM_OCNIdleState;  // 与上边一样,高级定时器
      } TIM_OCInitTypeDef;
    • 功能:配置4个通道, 选择哪个通道就用哪个函数即可,而通道选择和GPIO口有关。
  • 函数6
    • 函数原型:void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
    • 输入:TIM_OCInitStruct指向定时器输出比较初始化结构体的指针
    • 功能:为输出比较结构体赋默认值
  • 函数7-10
    • 函数原型
      • 函数7:void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
      • 函数7:void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
      • 函数7:void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
      • 函数7:void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
    • 输入:TIMx选择定时器编号,Comparex为CCR寄存器的值
    • 功能:修改CCR寄存器值,即配置PWM占空比
  1. 配置GPIO为复用推挽输出
  2. 运行控制(启动定时器)

  3. 代码实现

  用TIM1的通道1输出频率为1kHz、占空比为50%、分辨率为1%的PWM信号.

计算:分辨率 = 1/(ARR + 1)得ARR = 100-1.
   占空比 = CCR/(ARR+1)得CCR = 50 - 1.
   频率 = PCK / (ARR+1) / (PSC + 1)得 PSC = 720-1.

void PWM_Init(void){

    // 开启时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 选择时钟源
    TIM_InternalClockConfig(TIM2);

    // 配置时基单元
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructrue;
    TIM_TimeBaseInitStructrue.TIM_Prescaler = 720 - 1// PSC
    TIM_TimeBaseInitStructrue.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructrue.TIM_Period =  100 - 1;// ARR
    TIM_TimeBaseInitStructrue.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructrue.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructrue);

    // 配置输出比较单元
    TIM_OCInitTypeDef TIM_OCInitStructrue;
    TIM_OCStructInit(&TIM_OCInitStructrue);         // 先给默认值
    TIM_OCInitStructrue.TIM_OCMode = TIM_OCMode_PWM1;           // 输出比较模式
    TIM_OCInitStructrue.TIM_OutputState = TIM_OutputState_Enable;   // 使能
    TIM_OCInitStructrue.TIM_Pulse = 50;   // CCR, 分辨率为0.01
    TIM_OCInitStructrue.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(TIM2, &TIM_OCInitStructrue);

    // 开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 配置GPIO口
    GPIO_InitTypeDef GPIO_InitStructrue;
    GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructrue);

    // 开启定时器
    TIM_Cmd(TIM2, ENABLE);
}

4 引脚重映射

  1. STM32中GPIO口引脚的复用功能都是实现规定好的,如果需要使用到同一个引脚上的不同复用功能时会产生冲突,因而需要定义引脚重映射,将引脚的复用功能重映射到其他的引脚上。引脚重映射同样也是实现设计好的,用户无法自行更改。

  2. 相关函数:void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

    • 输入:GPIO_Remap选择要进行重映射的引脚,NewState为使能或失能
    • 备注:GPIO_Remap选择引脚的同时也进行了模式选择,即部分重映射和完全重映射两种。如定时器TIM2对应的有:GPIO_PartialRemap1_TIM2部分重映射1、GPIO_PartialRemap2_TIM2部分重映射2、GPIO_FullRemap_TIM2完全重映射三种。此外,部分端口被定义为调试端口,如SW和JTAG两种,如果需要用到这些端口,首先需要通过上述函数失能调试功能使该端口变为普通GPIO口。
  3. 代码实现

    RCC_APB2PeriphClockCmd(RCC_APB2PeriphAFIO, ENABLE);   // 使能AFIO时钟,重映射是通过AFIO寄存器来实现
    GPIO_PinRemapConfig(GPIO_ParitialRemap1_TIM2, ENABLE);  // 对TIM2进行部分重映射1
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);  // 取消端口调试功能

    注意:慎用取消调试功能,因为取消后无法再通过调试端口烧写程序,只能通过串口下载。


文章作者: Vyron Su
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Vyron Su !