如何计算产生SPWM所需要的占空比
2016-12-01 19:25
225 查看
[cpp] view
plain copy
/** @author Mei Jilin
@date 2013/9/2
@brief 加入生成SPWM部分
**/
#include "timer.h"
#include "led.h"
static uint16_t CCR3_Val = 1800;
static uint16_t PrescalerValue = 0;
/*PWM输出配置说明,*/
/* - Prescaler = (TIM3CLK / TIM3 counter clock) - 1 选择TIMER工作在36MHZ
The TIM3 is running at 36 MHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
= 36 MHz / 3600 = 10 KHz
TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 */
/*转换周期10K*/
void PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|
RCC_APB2Periph_AFIO, ENABLE);
/* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
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);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //TIM1_CH1N
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Compute the prescaler value */
PrescalerValue = (uint16_t) (SystemCoreClock / 36000000) - 1; //TIMER2 - 36MHZ
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 3600; /*TIM3_ARR = 2879,12.5Khz*/
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 1, 2,3 and 4 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //关闭互补输出
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //这句的功能是让改变CCR2之后马上有效
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE); //TIM1需要加上这句,貌似低级定时器不需要
}
uint16_t Duty[] = {1800,1856,1912,1968,2023,2078,2131,2183,2233,2282,2329,2373,2416,2456,2493,
2528,2559,2588,2614,2636,2655,2671,2684,2692,2698,2699,2698,2692,2684,2671,2655,2636,2614,
2588,2559,2528,2493,2456,2416,2373,2329,2282,2233,2183,2131,2078,2023,1968,1912,1856,1800,
1743,1687,1631,1576,1521,1468,1416,1366,1317,1270,1226,1183,1143,1106,1071,1040,1011,985,
963,944,928,915,907,901,900,901,907,915,928,944,963,985,1011,1040,1071,1106,1143,1183,1226,
1270,1317,1366,1416,1468,1521,1576,1631,1687,1743,1799,1799};
uint16_t count = 0;
uint16_t num = sizeof(Duty)/(sizeof(Duty[0]));
void TIM1_CC_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
{
TIM1->SR = (uint16_t)~TIM_IT_CC1;
TIM1->CCR1 = Duty[count];
count++;
if(count==num)
{
count=0;
}
}
}
在上一篇文章里粘贴了STM32产生SPWM的代码,我在编写这些代码时最大的问题就是如何得到占空比,就是代码中的数组 Duty[]。他的思想就是对正弦波采样,在采样点出用PWM的占空比来代替正弦波在该点的数值。最容易想到就是用定时器的ARR值乘以sin(2*pi*f*t),就可以得到对应的寄存器CCR值。但是CCR值不能为负,所以要把sin(2*pi*f*t)变为
A*sin(2*pi*f*t)+B的形式,取A=B=0.5;那么计算公式为ARR*(0.5*sin(2*pi*f*t)+0.5),上传一个C++写的exe文件,可以帮助产生Duty[]数组.
http://download.csdn.NET/detail/mjlsuccess/6205567
软件使用vs2010编写的可能在有些电脑上无法运行,如果你装有VS2010,我可以把原工程发给你
转载于http://blog.csdn.net/mjlsuccess/article/details/11019805
自己思考:10KZ为载波(锯齿波)的频率,最终输入给电机为100HZ正弦波,则载波比为100,也就是100个数据,同时ccr不能为负值,故进行抬升,原本应该为0-1800,进行抬升1800的0.5倍
plain copy
/** @author Mei Jilin
@date 2013/9/2
@brief 加入生成SPWM部分
**/
#include "timer.h"
#include "led.h"
static uint16_t CCR3_Val = 1800;
static uint16_t PrescalerValue = 0;
/*PWM输出配置说明,*/
/* - Prescaler = (TIM3CLK / TIM3 counter clock) - 1 选择TIMER工作在36MHZ
The TIM3 is running at 36 MHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
= 36 MHz / 3600 = 10 KHz
TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 */
/*转换周期10K*/
void PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|
RCC_APB2Periph_AFIO, ENABLE);
/* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
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);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //TIM1_CH1N
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Compute the prescaler value */
PrescalerValue = (uint16_t) (SystemCoreClock / 36000000) - 1; //TIMER2 - 36MHZ
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 3600; /*TIM3_ARR = 2879,12.5Khz*/
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 1, 2,3 and 4 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //关闭互补输出
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //这句的功能是让改变CCR2之后马上有效
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE); //TIM1需要加上这句,貌似低级定时器不需要
}
uint16_t Duty[] = {1800,1856,1912,1968,2023,2078,2131,2183,2233,2282,2329,2373,2416,2456,2493,
2528,2559,2588,2614,2636,2655,2671,2684,2692,2698,2699,2698,2692,2684,2671,2655,2636,2614,
2588,2559,2528,2493,2456,2416,2373,2329,2282,2233,2183,2131,2078,2023,1968,1912,1856,1800,
1743,1687,1631,1576,1521,1468,1416,1366,1317,1270,1226,1183,1143,1106,1071,1040,1011,985,
963,944,928,915,907,901,900,901,907,915,928,944,963,985,1011,1040,1071,1106,1143,1183,1226,
1270,1317,1366,1416,1468,1521,1576,1631,1687,1743,1799,1799};
uint16_t count = 0;
uint16_t num = sizeof(Duty)/(sizeof(Duty[0]));
void TIM1_CC_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
{
TIM1->SR = (uint16_t)~TIM_IT_CC1;
TIM1->CCR1 = Duty[count];
count++;
if(count==num)
{
count=0;
}
}
}
在上一篇文章里粘贴了STM32产生SPWM的代码,我在编写这些代码时最大的问题就是如何得到占空比,就是代码中的数组 Duty[]。他的思想就是对正弦波采样,在采样点出用PWM的占空比来代替正弦波在该点的数值。最容易想到就是用定时器的ARR值乘以sin(2*pi*f*t),就可以得到对应的寄存器CCR值。但是CCR值不能为负,所以要把sin(2*pi*f*t)变为
A*sin(2*pi*f*t)+B的形式,取A=B=0.5;那么计算公式为ARR*(0.5*sin(2*pi*f*t)+0.5),上传一个C++写的exe文件,可以帮助产生Duty[]数组.
http://download.csdn.NET/detail/mjlsuccess/6205567
软件使用vs2010编写的可能在有些电脑上无法运行,如果你装有VS2010,我可以把原工程发给你
转载于http://blog.csdn.net/mjlsuccess/article/details/11019805
自己思考:10KZ为载波(锯齿波)的频率,最终输入给电机为100HZ正弦波,则载波比为100,也就是100个数据,同时ccr不能为负值,故进行抬升,原本应该为0-1800,进行抬升1800的0.5倍
相关文章推荐
- 如何计算产生SPWM所需要的占空比
- 如何计算某个sql语句所产生的redo和undo大小?
- 如何计算网站所需要的带宽
- 如何计算某个sql语句所产生的redo和undo大小?
- 云计算需要学什么课程?新手小白如何学习云计算大数据
- 如何计算一个网站需要的带宽?
- 如何计算某个sql语句所产生的redo和undo大小?
- lua如何产生随机数,以及需要注意的问题
- 如何计算下载一个文件需要多长时间?
- PWM的周期和占空比是如何计算
- Random类产生随机数,注意是从0开始的,否则需要进行相关范围调整计算
- B/S下,页面后台计算需要大量时间,前台如何显示载入中或进度条
- [每天一个知识点]24-编程技巧-如何简单计算分页等需要进1的除法
- 如何计算圆周率 Pi (π)值, 精确到小数点后 10000 位 只需要 30 多句代码!
- MATLAB产生SPWM比较占空比
- 已知Ip地址_子网掩码如何计算子网号、主机号(收集整理)
- ORACLE RAC--如何定位追踪产生的core文件
- 如何删除需要管理员权限才能删除的文件夹
- 如何计算测序深度