1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
SPWM在单向逆变器中运用的比较多,在电能与电机控制领域现在大都是用SVPWM。先学好spwm,为以后的进阶做准备!本文主要是我学习spwm的一些理解,然后后通过实例代码生成spwm,可以直接复制测试。
一。什么是SPWM 要说SPWM先得说PWM,英文全名Pluse Width Modulation,即脉冲宽度调制,实际上就是周期的矩形波,然后每个周期的占空比都可以自己设置就叫调制。比如Buck电路中开关管的PWM波,当输入不变时可以将它的占空比从40%变到60%就能提高母线输出电压。 图一 。占空比固定pwm波与载波 而SPWM前面加了个S(Sine),即正弦脉宽调制,意思就是:还是这个周期的矩形波,但不同的是占空比不是如40%固定的,而是按照正弦规律变化的。 SPWM一般由三角波(载波)和正弦波(调制波)比较而成。硬件生成方法是将三角波和正弦波加入比较器得到;软件是通过定时器或者Epwm模块,按照中央计数模式生成三角波,经由CCR比较模块动作产生对应高低电平,即SPWM。 如图,我们将正弦函数和三角载波都归一化处理,正弦波幅值要小于三角波,这里取0.8。在一个很小的Δt时段内正弦函数值和占空比的值相等。例如图中Δt时段正弦波的值是0.8左右(A点电压值),它的矩形波占空比也是80%。同时我们可以看出矩形波的频率和三角波相等。正弦波被三角波“切割”成高频的spwm,用以控制开关管,然后spwm通过低通滤波滤除高次谐波后,得到原来的正弦波。图示情况下从0开始半个期内SPWM占空比是0-》0.8-》0按照正弦函数变化,要得到某时的占空比,得到此时的sine值就可以了,sine值可以事先放入表中。 二.SPWM软件生成 利用单片机输出PWM波,然后让占空比正弦规律变化。 实现步骤可以简单分为三步,以stm32为例: (1)生成载波。比如要生成一个10KHZ的三角波,将计数器设置加减计数、周期设为1/10K就ok啦。这样生成的三角波的幅值是多少呀,3.3V?其实在单片机里面都是数字信号,三角波最高点的时候可以用一个计数值来表示,比如8400,最低点是0。不用管他的电压是多少。 (2)生成正弦波。这一步用软件生成一个正弦表即可。比如将正弦波取200个点,即将一个正弦分割成200份,每个点代表一个幅值。用离散的数字量表达正弦模拟量。 (3)将正弦波和三角波进行比较。 a.什么时候进行比较。设置计数值达到比较值产生动作。 b.比较完之后,需要改变比较值,用于下一个周期进行比较(比较值可以理解为占空比),比较值查正弦表获得,这样就生成了占空比正弦规律变化的SPWM。 C.调制度m。m=正弦表最大值/三角波最大计数值。 如正弦表最大值4200,三角波最大计数值8400,m=4200/8400=0.5,此时spwm最大占空比为50%,设置m=1,spwm最大占空比为100%。 如图所示,要注意因为是单极性调制,spwm和三角载波都是大于0的。在单相全桥逆变电路中,开关管交替导通时输出电压Ud自然会倒过来为负,Ud经过滤波就是一个正弦波。 三。实例分析 下面我们来看一个例子,来生成一个开环的三相spwm。单相逆变需生成两组相差180度的spwm,三相即生成三组两两相差120度的spwm,且每组的spwm都是互补的。 如图,将生成的三组spwm分别加到1、2、3组桥臂,每组spwm互补防止了同一桥臂上下管同时导通会引起短路。 uint16_t Counter_sine1 = 0; //A相 uint16_t Counter_sine2 = 83; //滞后A相120度 uint16_t Counter_sine3 = 166; //超前A相120度 /** * 说明 TIM1GPIO初始化 CH1--A8 CH2--A9 CH3--A10 * CH1N-B13 CH2N-B14 CH3N-B15 * * 入口参数 None * * 出口参数 None **/ void TIM1_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9| GPIO_Pin_10; 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| GPIO_Pin_14 | GPIO_Pin_15; GPIO_Init(GPIOB, &GPIO_InitStructure); } #define CKTIM ((u32)72000000uL) //主频 #define PWM_PRSC ((u8)0) //TIM1分频系数 #define PWM_FREQ ((u16) 10000) //PWM频率(Hz) #define PWM_PERIOD ((u16) (CKTIM / (u32)(2 * PWM_FREQ *(PWM_PRSC+1)))) #define MODULAT (float)0.7 //调制度 /** * 说明 TIM1模式 * * 入口参数 None * * 出口参数 None **/ void TIM1_Mode_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM1_BDTRInitStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseStructure.TIM_Period = PWM_PERIOD; //计数周期 TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRSC; //分频系数 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //配置为PWM模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能CHx的PWM输出 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//互补输出使能,使能CHxN的PWM输出 TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; TIM_OC1Init(TIM1, &TIM_OCInitStructure); //配置CH1 TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC2Init(TIM1, &TIM_OCInitStructure); //配置CH2 TIM_OCInitStructure.TIM_Pulse = 0; TIM_OC3Init(TIM1, &TIM_OCInitStructure); //配置CH3 //死区时间 TIM1_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM1_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM1_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; TIM1_BDTRInitStructure.TIM_DeadTime = 360; //设置死区时间 TIM1_BDTRInitStructure.TIM_Break = TIM_Break_Disable; TIM1_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; TIM1_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; TIM_BDTRConfig(TIM1, &TIM1_BDTRInitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //4个抢先级、4个子优先级 NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM1,TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3,ENABLE); //使能中断 TIM_CtrlPWMOutputs(TIM1, ENABLE); //PWM输出使能 TIM_Cmd(TIM1, ENABLE); //使能TIM1 } void TIM1_PWM_Init(void) { TIM1_GPIO_Config(); TIM1_Mode_Config(); } //定时器1中断服务函数 void TIM1_CC_IRQHandler(void) { if(Counter_sine1》=250) { Counter_sine1 = 0; } if(Counter_sine2》=250) { Counter_sine2 = 0; } if(Counter_sine3》=250) { Counter_sine3 = 0; } //CCR1 if (TIM_GetITStatus(TIM1, TIM_IT_CC1)!=RESET) { TIM_SetCompare1(TIM1,(uint32_t)(talab[Counter_sine1])*MODULAT); //A相 Counter_sine1++; TIM_ClearITPendingBit(TIM1 , TIM_IT_CC1); } //CCR2 if (TIM_GetITStatus(TIM1, TIM_IT_CC2) !=RESET) { TIM_SetCompare2(TIM1,((uint32_t)talab[Counter_sine2])*MODULAT); //B相 Counter_sine2++; TIM_ClearITPendingBit(TIM1 , TIM_IT_CC2); } //CCR3 if (TIM_GetITStatus(TIM1, TIM_IT_CC3) !=RESET) { TIM_SetCompare3(TIM1,(uint32_t)(talab[Counter_sine3])*MODULAT); //C相 Counter_sine3++; TIM_ClearITPendingBit(TIM1 , TIM_IT_CC3); } } int const talab[250]= { 100 , 102 , 108 , 116 , 126 , 140 , 154 , 172 , 194 , 216 , 242 , 270 , 300 , 334 , 370 , 408 , 448 , 490 , 536 , 582 , 632 , 684 , 738 , 794 , 854 , 914 , 976 ,1040 ,1108 ,1176 , 1246 ,1320 ,1394 ,1470 ,1548 ,1626 ,1708 ,1790 ,1874 ,1960 , 2046 ,2136 ,2224 ,2316 ,2408 ,2502 ,2596 ,2690 ,2786 ,2884 , 2982 ,3080 ,3180 ,3280 ,3382 ,3482 ,3584 ,3686 ,3788 ,3892 , 3994 ,4096 ,4200 ,4304 ,4406 ,4508 ,4612 ,4714 ,4816 ,4918 , 5018 ,5120 ,5220 ,5320 ,5418 ,5516 ,5614 ,5710 ,5804 ,5898 , 5992 ,6084 ,6176 ,6264 ,6354 ,6440 ,6526 ,6610 ,6692 ,6774 , 6852 ,6930 ,7006 ,7080 ,7154 ,7224 ,7292 ,7360 ,7424 ,7486 , 7546 ,7606 ,7662 ,7716 ,7768 ,7818 ,7864 ,7910 ,7952 ,7992 , 8030 ,8066 ,8100 ,8130 ,8158 ,8184 ,8206 ,8228 ,8246 ,8260 , 8274 ,8284 ,8292 ,8298 ,8300 ,8300 ,8298 ,8292 ,8284 ,8274 , 8260 ,8246 ,8228 ,8206 ,8184 ,8158 ,8130 ,8100 ,8066 ,8030 , 7992 ,7952 ,7910 ,7864 ,7818 ,7768 ,7716 ,7662 ,7606 ,7546 , 7486 ,7424 ,7360 ,7292 ,7224 ,7154 ,7080 ,7006 ,6930 ,6852 , 6774 ,6692 ,6610 ,6526 ,6440 ,6354 ,6264 ,6176 ,6084 ,5992 , 5898 ,5804 ,5710 ,5614 ,5516 ,5418 ,5320 ,5220 ,5120 ,5018 , 4918 ,4816 ,4714 ,4612 ,4508 ,4406 ,4304 ,4200 ,4096 ,3994 , 3892 ,3788 ,3686 ,3584 ,3482 ,3382 ,3280 ,3180 ,3080 ,2982 , 2884 ,2786 ,2690 ,2596 ,2502 ,2408 ,2316 ,2224 ,2136 ,2046 , 1960 ,1874 ,1790 ,1708 ,1626 ,1548 ,1470 ,1394 ,1320 ,1246 , 1176 ,1108 ,1040 , 976 , 914 , 854 , 794 , 738 , 684 , 632 , 582 , 536 , 490 , 448 , 408 , 370 , 334 , 300 , 270 , 242 , 216 , 194 , 172 , 154 , 140 , 126 , 116 , 108 , 102 , 100 }; TIM1设置为中央计数模式,开启互补通道,设置死区时间,死区时间是多少个时钟计数周期,比如TIM1计数周期是72M,设置为72就是1000ns。 spwm频率设置为10k,然后TIM1每个通道的比较值达到时更新比较值。 调制度m范围为0~1,设为0.7。 正弦调制波的频率是自己设置的,方法是f=载波频率/表中点数,这里设置的是载波频率10K,取250个点 得到的正弦频率就是40HZ,改变载波频率为50*250就得到了50hz的正弦波输出。正弦表可以用取点工具。 将程序下载到stm32f103单片机,PA8、PA9两个引脚输出spwm波形是相差120度的,如图。 互补通道波形相反,且有死区时间。 将以上程序加到一起就可以实现啦! 刚学习不久,有很多不足之处还请大家多多包涵和指正。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1763 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1617 浏览 1 评论
1059 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
723 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1670 浏览 2 评论
1933浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
726浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
592浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
550浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 13:39 , Processed in 3.439271 second(s), Total 46, Slave 40 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号