历史上的今天
今天是:2024年12月29日(星期日)
2021年12月29日 | STM32F103单片机PWM单脉冲输出模式
2021-12-29 来源:eefocus
通常输出PWM波形的时候是一直输出的。但是在电机控制中往往只需要输出一定个数的脉冲,不需要一直输出,那么这就需要每次输出PWM时,输出的脉冲个数可控。要实现这个功能,一般有三种方法。
方法一:
void TIM1_PWM_Init(u16 arr, u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitSturcture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE);
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);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0x00;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
TIM_OCStructInit(& TIM_OCInitSturcture);
TIM_OCInitSturcture.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitSturcture.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitSturcture.TIM_Pulse = 0;
TIM_OCInitSturcture.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM1, &TIM_OCInitSturcture);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(TIM1, ENABLE); //主输出使能
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM1, ENABLE); //使能计数器
TIM_SetCompare1(TIM1, arr / 2);
}
void TIM1_UP_IRQHandler(void)
{
static u16 y;
if(TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM1, TIM_IT_Update );
y++;
if(y > 60) //设置输出脉冲数
{
y = 0;
TIM_Cmd(TIM1, DISABLE);
}
}
}
这个方法实现的原理最简单,就是开启PWM输出的更新中断功能,当计时器值重新加载一次时,就会产生一个中断,就代表输出了一个脉冲。这样每进一次中断,就统计一次中断次数,当中断的次数和需要的脉冲数相等时就关闭PWM的输出。这样也就实现了指定脉冲输出的功能。
方法二:
void PWMS8_Init(u32 Cycle, u32 PulseNum)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = Cycle; //频率
TIM_TimeBaseStructure.TIM_Prescaler = 71; //分频值 72M/(71+1) = 1M
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = PulseNum - 1; //输出脉冲个数
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
TIM_GenerateEvent(TIM8, TIM_EventSource_Update);
TIM_InternalClockConfig(TIM8);
TIM_SelectOCxM(TIM8, TIM_Channel_2, TIM_OCMode_PWM2);
/* PWM1 Mode configuration: Channel2 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = Cycle / 2; // 低电平时间 占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_Low;
TIM_OC2Init(TIM8, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM8, ENABLE);
/* TIM8 enable counter */
TIM_CtrlPWMOutputs(TIM8, ENABLE);
TIM_SelectOnePulseMode(TIM8, TIM_OPMode_Single);
TIM_Cmd(TIM8, ENABLE);
}
在方法一中是通过代码自己统计ARR的装载次数,而单片机内部也自带了这个功能,方法二中就直接使用这个系统自带的功能。这个功能就是重复计数器。



在初始化时将要输出的脉冲个数写入到重复计数器中,这样系统就会自动统计输出PWM的脉冲个数,当输出脉冲个数完成后就会自动停止PWM输出。
方法三:
/***********************TIM1初始化函数*************************/
/****参数:****************************************************/
/******u32 Cycle用于设定计数频率(计算公式:Cycle=1Mhz/目标频率)*/
/****返回值:**************************************************/
/******无*****************************************************/
void TIM1_config(u32 Cycle)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_TIM1 , ENABLE); //时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM1_CH1 PA10
GPIO_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; //使用Cycle来控制频率(f=72/(71+1)/Cycle) 当Cycle为100时脉冲频率为10KHZ
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_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = Cycle/2-1; //设置待装入捕获寄存器的脉冲值(占空比:默认50%,这可也可以调节如果需要的话将它作为一个参数传入即可)
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性
TIM_OC3Init(TIM1, &TIM_OCInitStructure); //使能通道1
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable); //设置为主从模式
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update); //选择定时器1的触发方式(使用更新事件作为触发输出)
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能通道1预装载寄存器
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIM1在ARR上的预装载寄存器
}
/***********************TIM2初始化函数*************************/
/****参数:****************************************************/
/******u32 PulseNum用于设定脉冲数量****************************/
/****返回值:*************************************************/
/******无*****************************************************/
void TIM2_config(u32 PulseNum)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2的时钟
TIM_TimeBaseStructure.TIM_Period = PulseNum; //脉冲数
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); //选择定时器2的输入触发源(内部触发(TIM1))
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;
史海拾趣
|
大家好,现在学习实践I2C总线方面的知识。这个过程中遇到的问题还希望能够得到大家的指教,谢谢! 下面这段话摘自“I2C总线规范”, “在SCL线是高电平时SDA线从高电平向低电平切换,这个情况表示起始条件。 在SCL线是高电平时SDA线由低电平向 ...… 查看全部问答> |
|
VMware+RH9+skyeye1.2 仿真lcd出现segmentation fault VMware+RH9+skyeye1.2 仿真lcd出现segmentation fault 配置文件内容: cpu: arm720t mach: ep7312 mem_bank: map=M, type=R, addr=0x0, size=0xC0000 mem_bank: map=M, type=R, addr=0x000C0000, size=0x00340000, fil ...… 查看全部问答> |
|
小弟毕业设计就快完了,搞的是PPC2003软件设计。在开发过程中,现在还留了点问题下来。 一、有没有能够实现将某个文件中所有的EXE文件,文件名及文件路径存入一个表中的操作或是函数; 二、我用的是VS2005自带的仿真上的数据库,没有另外安装 ...… 查看全部问答> |
|
我使用sim3000的gprs模块,昨天已经可以用ip地址访问我在花生壳上注册的地址了.然后我尝试用域名的形式访问网络.先 at+cipshut,关闭连接 然后 配置dns服务器 at+cdnscfg=\"202.96.128.56\" 然后设置为域名访问方式at+cdnsorip=1 最后使用域名访 ...… 查看全部问答> |
|
现在我用的是网口调试,经常出现下了一半就下不下去了 重起一次机器就好了 这样用就太不稳定了 想用USB的方法进行在线调试 但不知道怎么下手 麻烦各位大侠指点指点了 小女子先谢谢了哈… 查看全部问答> |
|
我用51单片机与pc机进行串口通讯,上位机软件用的是出口调试助手3.0,下位机是我自己编的,主要目的是pc向单片机发个数据,单片机接收后向p2口输出,之后再把接收到的数据发给pc。但是我发现pc上发出与收到的数据总是不一致。例如,我用pc输出字符 ...… 查看全部问答> |
|
最近在学linux驱动开发,在做中断程序的时候不知道为什么就是进不了中断服务函数,下面贴出源码,希望各位大侠们给点帮助,不胜感激~ //s3c2440_key.c(底层驱动程序) //#include #include #include #include #include //#include # ...… 查看全部问答> |
|
tms320vc5509A做25MHz带宽的软件无线电处理能力够不? tms320vc5509A做25MHz带宽的软件无线电处理能力够不?以下哪种方式比较好?通过5509的usb接口和外部进行数据通讯,5509自带的adc接音频输入。不知道下面一种通过什么算法可以实现单边带?上面一种好像找不到那么低速的IQ输出的dds。另希望论坛能支 ...… 查看全部问答> |




