您的位置:首页 > 科技 > IT业 > 佛山网站建设电话_营销推广外包公司_推广方案万能模板_seo关键词排名

佛山网站建设电话_营销推广外包公司_推广方案万能模板_seo关键词排名

2024/12/22 17:17:19 来源:https://blog.csdn.net/m0_64386340/article/details/143186890  浏览:    关键词:佛山网站建设电话_营销推广外包公司_推广方案万能模板_seo关键词排名
佛山网站建设电话_营销推广外包公司_推广方案万能模板_seo关键词排名

STM32中发出脉冲一般有两种方式:

1)利用定时中断输出脉冲,但是间隔的延时会影响其他主程序的进程,当控制多个电机的时候就非常不可取;

2)利用PWM脉宽调制,并通过主从定时器进行设定,好处是不占用主程序时钟,且能精准控制;

 下面以定时器1为主,定时器2为从进行配置:

PWM.c文件

#include "stm32f10x.h"   // Device header/***定时器1主模式,定时器2从模式***/
void TIM1_config(u16 Cycle)
{GPIO_InitTypeDef GPIO_InitStructure; //GPIO设置,创建结构体TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;//定时器设置结构体TIM_OCInitTypeDef  TIM_OCInitStructure; //pwm波对应设置结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_TIM1 , ENABLE); //开启时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_TimeBaseStructure.TIM_Period = Cycle-1;                                                   TIM_TimeBaseStructure.TIM_Prescaler =71;                    //设置用来作为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 = Cycle/2-1;                    //设置待装入捕获寄存器的脉冲值                                   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;      //输出极性       TIM_OC1Init(TIM1, &TIM_OCInitStructure);     //装载通道1,PA8 TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);//设置或者重置 TIMx 主/从模式//TIMx: x 可以是 2, 3 或者 4,来选择 TIM 外设//TIM_MasterSlaveMode:定时器主/从模式,TIM 主/从模式使能TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);//选择 TIMx 触发输出模式//TIMx: x 可以是 2, 3 或者 4,来选择 TIM 外设//TIM_TRGOSource:触发输出模式//TIM_TRGOSource_Update:使用更新事件作为触发输出(TRGO)//    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能或者失能 TIMx 在 CCR3 上的预装载寄存器TIM_ARRPreloadConfig(TIM1, ENABLE);  // 使能或者失能 TIMx 在 ARR 上的预装载寄存器 //允许或禁止在定时器工作时向ARR的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值
}/***定时器2从模式***/
void TIM2_config(u16 PulseNum)
{TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; //对应结构体声明NVIC_InitTypeDef NVIC_InitStructure;  //NVIC 对应结构体声明RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);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);  TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0);//选择 TIMx 输入触发源,TIM 内部触发 0      TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_External1 );// 等同 TIM2->SMCR|=0x07 //设置从模式寄存器 //   TIM2->SMCR|=0x07;                                  //设置从模式寄存器       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);
}//入口设定函数
void Pulse_output(u16 Cycle,u16 PulseNum)
{TIM1_config(Cycle); //装载   TIM_Cmd(TIM1, ENABLE);//使能TIM_CtrlPWMOutputs(TIM1, ENABLE);   //高级定时器一定要加上,主输出使能TIM2_config(PulseNum);//装载TIM_Cmd(TIM2, ENABLE);//使能TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除TIMx 的中断待处理位TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能或者失能指定的 TIMx 中断
}//中断处理函数
void TIM2_IRQHandler(void) 
{ if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)     // TIM_IT_CC1{ TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除中断标志位 TIM_CtrlPWMOutputs(TIM1, DISABLE);  //主输出使能TIM_Cmd(TIM1, DISABLE); // 关闭定时器 TIM_Cmd(TIM2, DISABLE); // 关闭定时器 TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);         } 
} 

PWM.h文件

#ifndef __PWM_H
#define __PWM_Hvoid Pulse_output(u16 Cycle,u16 PulseNum);//入口函数void TIM1_config(u16 Cycle);//1为主模式
void TIM2_config(u16 PulseNum);//2为从模式#endif 

主函数调用:

Pulse_output(1000,8000);//1KHZ,8000个脉冲

其中/TIM_SelectInputTrigger(TIM1, TIM_TS_ITR2);中的参数需要注意,参考手册查对应的可用连接,如下:

 问题:

ARR的值最高只能是65535,所以这种方法最多只能输出65535个脉冲。有待改进。

解决方法:(2024.10.26)

将需要发送的脉冲数拆分为高16位和低16位,没进入中断前将低16位装载到从定时器的ARR,第一次进入中断再将高16位装载到从定时器ARR,第二次进入中断关闭脉冲输出和定时器。

 完整代码:

#include "stm32f10x.h"   // 包含STM32F10x系列的设备头文件// 定义全局变量
volatile u16 PulseNum_High = 0;  // 高16位脉冲计数
volatile u16 PulseNum_Low = 0;   // 低16位脉冲计数
volatile int pulseStage = 0;     // 脉冲阶段标志/*** @brief 配置TIM1定时器*/
void TIM1_config(void)
{GPIO_InitTypeDef GPIO_InitStructure;  // 定义GPIO初始化结构体TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  // 定义TIM1时间基础初始化结构体TIM_OCInitTypeDef  TIM_OCInitStructure;  // 定义TIM1输出比较初始化结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);  // 使能TIM1时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // 使能GPIOA时钟// 配置GPIOA的Pin8为复用推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置TIM1时间基础TIM_TimeBaseStructure.TIM_Period = 100-1;  // 定时周期为99,即100个计数周期TIM_TimeBaseStructure.TIM_Prescaler = 720-1;  // 预分频器为719,即720分频TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频为1TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;  // 重复计数器为0TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);  // 初始化TIM1时间基础// 配置TIM1输出比较模式TIM_OCStructInit(&TIM_OCInitStructure);  // 初始化输出比较结构体TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  // 输出使能TIM_OCInitStructure.TIM_Pulse = 50;  // 比较值为50TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性为高TIM_OC1Init(TIM1, &TIM_OCInitStructure);  // 初始化TIM1通道1的输出比较模式TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);  // 使能主从模式TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);  // 选择触发输出源为更新事件TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  // 使能通道1的CCR预装载TIM_ARRPreloadConfig(TIM1, ENABLE);  // 使能自动重装载寄存器预装载TIM_CtrlPWMOutputs(TIM1, DISABLE);  // 关闭TIM1的PWM输出TIM_Cmd(TIM1, DISABLE);  // 关闭TIM1
}/*** @brief 配置TIM2定时器*/
void TIM2_config(void)
{TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  // 定义TIM2时间基础初始化结构体NVIC_InitTypeDef NVIC_InitStructure;  // 定义NVIC初始化结构体RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  // 使能TIM2时钟// 配置TIM2时间基础TIM_TimeBaseStructure.TIM_Period = 65535;  // 定时周期为65535TIM_TimeBaseStructure.TIM_Prescaler = 0;  // 预分频器为0TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频为1TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  // 初始化TIM2时间基础TIM_SelectInputTrigger(TIM2, TIM_TS_ITR0);  // 选择输入触发源为内部触发器0TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_External1);  // 选择从模式为外部触发模式1TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);  // 禁用TIM2更新中断TIM_ARRPreloadConfig(TIM2, ENABLE);  // 使能自动重装载寄存器预装载// 配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  // 配置优先级分组为2NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  // 中断通道为TIM2NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  // 抢占优先级为0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  // 子优先级为0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  // 使能中断通道NVIC_Init(&NVIC_InitStructure);  // 初始化NVICTIM_Cmd(TIM2, DISABLE);  // 关闭TIM2
}/*** @brief 输出指定周期和数量的脉冲* @param Cycle 周期值,对应TIM1的ARR* @param PulseNum 脉冲数量,最大为65535*/
void Pulse_output(u16 Cycle, u32 PulseNum)
{// 如果脉冲数量大于65535,则需要使用高位和低位计数if(PulseNum >= 65536){PulseNum_High = (PulseNum >> 16) * 65536 - 1;  // 计算高16位计数值PulseNum_Low = (PulseNum & 0xFFFF) - 1;  // 计算低16位计数值pulseStage = 0;  // 设置脉冲阶段为高16位}else{PulseNum_High = 0;  // 高16位计数值为0PulseNum_Low = (PulseNum & 0xFFFF) - 1;  // 计算低16位计数值pulseStage = 1;  // 设置脉冲阶段为低16位}TIM1_config();  // 配置TIM1TIM2_config();  // 配置TIM2TIM_Cmd(TIM2, DISABLE);  // 关闭TIM2TIM_SetAutoreload(TIM2, PulseNum_Low);  // 设置TIM2的自动重装载寄存器为低16位计数值TIM_GenerateEvent(TIM2, TIM_EventSource_Update);  // 触发TIM2更新事件以更新ARRTIM_Cmd(TIM2, ENABLE);  // 开启TIM2TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  // 清除TIM2更新中断标志TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  // 使能TIM2更新中断TIM_SetAutoreload(TIM1, Cycle);  // 设置TIM1的自动重装载寄存器为周期值TIM_GenerateEvent(TIM1, TIM_EventSource_Update);  // 触发TIM1更新事件以更新ARRTIM_SetCompare1(TIM1, Cycle / 2);  // 设置TIM1的比较值为周期值的一半,以生成50%占空比的PWMTIM_GenerateEvent(TIM1, TIM_EventSource_CC1);  // 触发TIM1捕获/比较事件TIM_CtrlPWMOutputs(TIM1, ENABLE);  // 开启TIM1的PWM输出TIM_Cmd(TIM1, ENABLE);  // 开启TIM1
}/*** @brief TIM2中断服务函数*/
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  // 检查是否为TIM2更新中断{TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  // 清除TIM2更新中断标志if (pulseStage == 0)  // 如果处于高16位计数阶段{pulseStage = 1;  // 切换到低16位计数阶段TIM_Cmd(TIM2, DISABLE);  // 关闭TIM2TIM_SetAutoreload(TIM2, PulseNum_High);  // 设置TIM2的自动重装载寄存器为高16位计数值TIM_GenerateEvent(TIM2, TIM_EventSource_Update);  // 触发TIM2更新事件以更新ARRTIM_Cmd(TIM2, ENABLE);  // 开启TIM2TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  // 清除TIM2更新中断标志TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  // 使能TIM2更新中断}else  // 如果处于低16位计数阶段{// 脉冲输出完成,停止定时器TIM_CtrlPWMOutputs(TIM1, DISABLE);  // 关闭TIM1的PWM输出TIM_Cmd(TIM1, DISABLE);  // 关闭TIM1TIM_Cmd(TIM2, DISABLE);  // 关闭TIM2TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);  // 禁用TIM2更新中断}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com