计数器的值到达CCRx_1设置值时,电平会进行一次翻转。而后进入中断,输出比较回调函数函数HAL_TIM_OC_DelayElapsedCallback。如果在回调函数里重新设值CCRx_2,那么进行到达CCRx_2电平再次翻转。
计数器时钟频率CK_CNT=fck_psc/(PSC[15:0]+1) 16位分频器设置位84-1,分频后计数器时钟频率位1MHZ,周期1uS
TIM_OCMode_Toggle TIM输出比较触发模式 翻转––TIMx_CNT=TIMx_CCR1 时,OC1REF 发生翻转。至于跟PWM模式的区别见总结篇
keil ver. V5.29.0.0 cubemx ver. v5.6.0 firmware ver. FW_F4 V1.25.1
file_name: ALIENTEK_PWM pin discreble: CLK 84M
PH3 | KEY0 | PH2 | KEY1 | PC13 | KEY2 | PA0 | KEY_UP | PB1 | TIM3_CH4 | √ (脉冲)STEP PB0 | LED1 | 电机方向 PA10 | USART1_RX | PA9 | USART1_TX |
bsp_ocompare.c
#include "bsp_ocompare.h" /*全局变量*/ uint8_t dir = 0;//0:顺时钟 1:逆时钟 uint8_t ena = 0;//0:正常运行 1:停机 uint32_t Toggle_Pulse=500; __IO uint32_t pulse_count=0;/*脉冲计数,一个完整的脉冲会增加2*/ //定时器比较输出中断回调函数,在定时器计数值与捕获比较寄存器值相等时发送中断,就会调用该函数 输出比较回调,进入中断后翻转,重新设置下一次翻转值,脉冲周期位T=2*Toggle_Pulse void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { __IO uint16_t count; count = __HAL_TIM_GET_COUNTER(&htim3); __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,count+Toggle_Pulse); pulse_count++; } void bsp_InitOcompare(void) { /*初始化设置了通道的脉冲数位Toggle_Pluse,启动定时器后计数器达到Toggle_Pulse,产生中断翻转通道引脚*/ __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_4,Toggle_Pulse); HAL_TIM_Base_Start(&htim3); HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_4);//启动比较输出使能中断 }bsp_ocompare.h
#ifndef _BSP_OCOMPARE_H #define _BSP_OCOMPARE_H #include "stm32f4xx_hal.h" #include "main.h" #include "pub_gpio.h" #include "tim.h" #include "bsp_led.h" /*宏定义*/ //STEPMOTOR_OUTPUT_DISABLE() HAL_GPIO_WritePin(STEPMOTOR_ENA_PORT,STEPMOTOR_ENA_PIN,GPIO_SET); //STEPMOTOR_OUTPUT_DISABLE() HAL_GPIO_WritePin(STEPMOTOR_ENA_PORT,STEPMOTOR_ENA_PIN,GPIO_RESET); #define STEPMOTOR_DIR_REVERSAL() LED1_OFF() //翻转 #define STEPMOTOR_DIR_FORWARDL() LED1_ON() //正转 #define STEPMOTOR_MICRO_STEP 32 //步进电机驱动器细分,必须与驱动器实际设置对应 extern uint32_t Toggle_Pulse; extern uint8_t dir;//0:顺时钟 1:逆时钟 extern uint8_t ena;//0:正常运行 1:停机 extern __IO uint32_t pulse_count;/*脉冲计数,一个完整的脉冲会增加2*/ void bsp_InitOcompare(void); #endifmain函数
void main_task (void * arg) { uint8_t ucKeyCode; while(1) { ucKeyCode = bsp_GetKey(); if (ucKeyCode != KEY_NONE) { switch (ucKeyCode) { /* K1键按下,打印调试说明 */ case KEY_DOWN_K0:/*功能选择*/ printf("K1键按下\r\n"); key1_count++; if(key1_count == 5) key1_count = 1; break; case KEY_UP_K0: printf("K1键松开\r\n"); break; case KEY_LONG_K0: printf("K1键长按\r\n"); break; case KEY_DOWN_K1://功能调节 printf("K2键按下\r\n"); switch(key1_count) { case 1://加速 Toggle_Pulse -=50; if( Toggle_Pulse<300 ) Toggle_Pulse = 300; break; case 2://减速 Toggle_Pulse +=100; if(Toggle_Pulse >3500 ) Toggle_Pulse = 3500; break; case 3: //方向控制 if(dir == 0) { STEPMOTOR_DIR_REVERSAL(); //反转 dir = 1; } else { STEPMOTOR_DIR_FORWARDL();// 正转 dir = 0; } break; case 4: if(ena == 0) { // STEPMOTOR_OUTPUT_ENABLE(); ena=1; } else { pulse_count=0; // STEPMOTOR_OUTPUT_DISABLE(); } break; default: break; } break; case KEY_UP_K1: printf("K2键松开\r\n"); break; case KEY_LONG_K1: printf("K2键长按\r\n"); break; case KEY_DOWN_K2: printf("K3键按下\r\n"); break; case KEY_UP_K2: printf("K3键松开\r\n"); break; case KEY_LONG_K2: printf("K3键长按\r\n"); break; case KEY_DOWN_K3: printf("K4键按下\r\n"); break; case KEY_UP_K3: printf("K4键松开\r\n"); break; case KEY_LONG_K3: printf("K4键长按\r\n"); break; case SYS_DOWN_K0K2: printf("K0K2键按下\r\n"); break; case SYS_UP_K0K2: printf("K0K2键松开\r\n"); break; case SYS_LONG_K0K2: printf("K0K2键长按\r\n"); break; case SYS_DOWN_K1K3: printf("K1K3键按下\r\n"); break; case SYS_UP_K1K3: printf("K1K3键松开\r\n"); break; case SYS_LONG_K1K3: printf("K1K3键长按\r\n"); break; default: break; } } if(pulse_count == STEPMOTOR_MICRO_STEP*200*2*10)//转10圈后停止 一圈200步 // STEPMOTOR_OUTPUT_DISABLE(); osThreadYield(); } }