|
在做步进电机驱动程序,想让电机按一定速度运行一定角度,于是采用了
一个主定时器产生pwm,另外一个从定时器负责发送脉冲数量的计数
STM32F103VE 时钟72MHz
实现:输出可控数量与频率的脉冲(pwm)
使用一个(主)定时器作为另一个(从)定时器的预分频器(外部时钟触发源)
本例子通过<df_MAIN_TIM_1_OR_8>修改可以实现TIM1和TIM8主的切换产生PWM信号,TIM2作为从定时器,用于对主定时器的计数,计数到达设定数量,停止pwm输出
TIM8已验证功能-ok;TIM1仿真运行正常,输出未验证
- #define df_MAIN_TIM_1 0 //主定时器1
- #define df_MAIN_TIM_8 1 //主定时器8
- #define df_MAIN_TIM_1_OR_8 df_MAIN_TIM_8 //定时器选择
- void TIM1_MasterPwmOutInit(void);
- void TIM8_MasterPwmOutInit(void);
- //TIM1_主pwm输出初始化
- void TIM1_MasterPwmOutInit(void){
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- //pwm频率=72000000/psc/arr 这里为了测试设置了1Hz用于led观测
- unsigned short arr=10000;//周期
- unsigned short psc=7200;//分频
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_TIM1 , ENABLE); //时钟使能
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //TIM1_CH4 PA11
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- TIM_TimeBaseStructure.TIM_Period = arr-1; //使用Cycle来控制频率(f=72/(71+1)/Cycle) 当Cycle为100时脉冲频率为10KHZ
- TIM_TimeBaseStructure.TIM_Prescaler = psc-1; //设置用来作为TIMx时钟频率除数的预分频值
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS= Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重复计数,一定要=0!!!(高级定时器特有)
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
-
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
- TIM_OCInitStructure.TIM_Pulse = psc/2-1; //设置待装入捕获寄存器的脉冲值(占空比:默认50%,这可也可以调节如果需要的话将它作为一个参数传入即可)
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
-
- TIM_OC4Init(TIM1, &TIM_OCInitStructure); //使能通道4
-
- TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable); //设置为主从模式
- TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update); //选择定时器1的触发方式(使用更新事件作为触发输出)
-
-
- TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能通道4预装载寄存器
-
- TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIM1在ARR上的预装载寄存器
-
- //TIM_CtrlPWMOutputs(TIM1, ENABLE); //高级定时器一定要加上,主输出使能
- }
- //TIM8_pwm输出初始化
- void TIM8_MasterPwmOutInit(void){
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- //pwm频率=72000000/psc/arr 这里为了测试设置了1Hz用于led观测
- unsigned short arr=10000;//周期
- unsigned short psc=7200;//分频
-
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟使能
-
- //PC6-CH1
- //PC7-CH2
- //PC8-CH3 cut_pwm
- //PC9-CH4 out_pwm
- //GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;//初始化GPIO
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;//初始化GPIO
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
-
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 72MHz/(psc+1)/(arr+1)=频率
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //重复计数,一定要=0!!!(高级定时器特有)<<<这里必须设置否则从计数器不正常
- TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
-
- // {//CH1
- // TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
- // TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能/失能OCx管脚
- // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //使能/失能OCxN管脚(使用OCxN必须使能TIM_OutputState)
- // TIM_OCInitStructure.TIM_Pulse = arr+1; //设置待装入捕获比较寄存器的脉冲值
- // TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
- // TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //输出极性
- // TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //BDTR寄存器的MOE为0时对应管脚状态
- // TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //BDTR寄存器的MOE为0时对应管脚状态
- // TIM_OC1Init(TIM8, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
- //
- // TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器
- // }
- // {//CH2
- // TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
- // TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能/失能OCx管脚
- // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //使能/失能OCxN管脚(使用OCxN必须使能TIM_OutputState)
- // TIM_OCInitStructure.TIM_Pulse = arr+1; //设置待装入捕获比较寄存器的脉冲值
- // TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
- // TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //输出极性
- // TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //BDTR寄存器的MOE为0时对应管脚状态
- // TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //BDTR寄存器的MOE为0时对应管脚状态
- // TIM_OC2Init(TIM8, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
- //
- // TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器
- // }
- {//CH3
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能/失能OCx管脚
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //使能/失能OCxN管脚(使用OCxN必须使能TIM_OutputState)
- TIM_OCInitStructure.TIM_Pulse = arr/2-1; //设置待装入捕获比较寄存器的脉冲值 占空比
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
- TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //输出极性
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //BDTR寄存器的MOE为0时对应管脚状态
- TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //BDTR寄存器的MOE为0时对应管脚状态
- TIM_OC3Init(TIM8, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
-
- TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器
- }
- {//CH4
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能/失能OCx管脚
- TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //使能/失能OCxN管脚(使用OCxN必须使能TIM_OutputState)
- TIM_OCInitStructure.TIM_Pulse = arr/2-1; //设置待装入捕获比较寄存器的脉冲值 占空比
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
- TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //输出极性
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; //BDTR寄存器的MOE为0时对应管脚状态
- TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //BDTR寄存器的MOE为0时对应管脚状态
- TIM_OC4Init(TIM8, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
-
- TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能TIMx在CCR2上的预装载寄存器
- }
-
- TIM_ARRPreloadConfig(TIM8, ENABLE); //使能TIMx在ARR上的预装载寄存器
-
-
- // TIM_CtrlPWMOutputs(TIM8, ENABLE); //TIM8->BDTR|=1<<15; 主输出MOE
-
- // TIM_Cmd(TIM8, ENABLE); //使能TIMx外设
- TIM_SetCompare3(TIM8,arr/2-1); //TIM8->CCR2 = x;更改占空比(设置范围0~arr)
- TIM_SetCompare3(TIM8,arr/2-1); //TIM8->CCR2 = x;更改占空比(设置范围0~arr)
-
- }
- {//设置为主从模式
- TIM_SelectMasterSlaveMode(TIM8, TIM_MasterSlaveMode_Enable); //设置为主从模式
- TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update); //选择定时器1的触发方式(使用更新事件作为触发输出)
- }
-
- }
- //TIM2从计数定时器初始化
- //设定脉冲数量后面可以通过TIM_SetAutoreload(TIM2,X);修改,这里预设了一个数值
- void TIM2_SlaveCountInit(void){
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- unsigned short PulseNum = 65535; //预设脉冲数
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2的时钟
-
- TIM_TimeBaseStructure.TIM_Period = PulseNum-1; //脉冲数
- TIM_TimeBaseStructure.TIM_Prescaler =0;
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
- #if (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_1)
- TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0); //选择定时器2的输入触发源(内部触发(TIM1))
- #elif (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_8)
- TIM_SelectInputTrigger(TIM2, TIM_TS_ITR1); //选择定时器2的输入触发源(内部触发(TIM8))
- #endif //df_MAIN_TIM_1_OR_8
-
- TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_External1); //TIM2->SMCR|=0x07;设置从模式寄存器(SMS[2:0]:111 外部时钟模式1)
-
- TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE); //更新中断失能
-
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure); //定时器2中断初始化
- }
- //定时器_主从_pwm计数_初始化
- void TIM_MasterSlave_PWMCount_Init(void){
- TIM2_SlaveCountInit(); //初始化 (从定时器)
- TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位
- TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能更新中断
-
- #if (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_1)
- TIM1_MasterPwmOutInit(); //使能定时器1(主定时器)
- #elif (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_8)
- TIM8_MasterPwmOutInit(); //使能定时器1(主定时器)
- #endif //df_MAIN_TIM_1_OR_8
- }
- //定时器_主从_pwm计数_开始
- //PulseNum :用于设定输出脉冲的数量
- void TIM_MasterSlave_PWMCount_Start(unsigned short PulseNum){
- PulseNum = (PulseNum>1?PulseNum-1:PulseNum); //这里的数值不能为0,为0后TIM2将失效; 设置数-1为需要的脉冲数
- TIM_Cmd(TIM2, ENABLE); //使能TIM2 (从定时器)
- TIM_SetAutoreload(TIM2,PulseNum); //设置脉冲数量
- TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能更新中断
-
- #if (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_1)
- TIM_Cmd(TIM1, ENABLE); //使能定时器1
- TIM_CtrlPWMOutputs(TIM1, ENABLE); //高级定时器一定要加上,主输出使能
- #elif (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_8)
- TIM_Cmd(TIM8, ENABLE); //使能定时器8
- TIM_CtrlPWMOutputs(TIM8, ENABLE); //高级定时器一定要加上,主输出使能
- #endif //df_MAIN_TIM_1_OR_8
- }
- //当TIM的CNT寄存器的值到达设定的Update值会触发更新中断,此时设定的脉冲数已输出完毕,关闭TIM1和TIM2
- void TIM2_IRQHandler(void){
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET){ //TIM_IT_Update
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除中断标志位
- #if (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_1)
- TIM_CtrlPWMOutputs(TIM1, DISABLE); //主输出失能
- TIM_Cmd(TIM1, DISABLE); //关闭定时器
- #elif (df_MAIN_TIM_1_OR_8 == df_MAIN_TIM_8)
- TIM_CtrlPWMOutputs(TIM8, DISABLE); //主输出失能
- TIM_Cmd(TIM8, DISABLE); //关闭定时器
- #endif //df_MAIN_TIM_1_OR_8
- TIM_Cmd(TIM2, DISABLE); //关闭定时器
- TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE); //关闭TIM2更新中断
- }
- }
- u8 ksw=0;
- void tim_test_co(void){
- TIM_MasterSlave_PWMCount_Init();//初始化
- while(1)
- {
- if(ksw){
- ksw = 0;
- TIM_MasterSlave_PWMCount_Start(3);//启动3个pwm
- }
- }
- }
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|