要生成SPWM波,其关键是要生成一组正弦规律变化的数字,然后将数字对应成PWM输出的占空比,按照顺序输出占空比就行。生成正弦波的方法在 使用C语言产生正弦波数据 这篇博客有详细说明,这里就不说了。
本例程中生成的64个数据是:50,54,59,64,69,73,77,81,85,88,91,94,96,97,99,99,100,99,99,97,96,94,91,88,85,81,77,73,69,64,59,54,50,45,40,35,30,26,22,18,14,11,8,5,3,2,0,0,0,0,0,2,3,5,8,11,14,18,22,26,30,35,40,45
它所组成的波形为
下面看C代码的实现
u16 FRE = 500; //frequency 频率 4M / 500 = 8K
void PWM_GPIO_Init( void )
{
PC_DDR |= ( 1 << 7 ); //PC7 推挽输出
PC_CR1 |= ( 1 << 7 );
PC_ODR_ODR7 = 0;
}
void TIM1_Init( void )
{
PWM_GPIO_Init();
TIM1_CR1 = (1<<7); //自动预装载允许
TIM1_CCMR2 = (6<<4)|(1<<3)|(1<<2); //TIM1 CH2 PWM1 输出比较1预装载使能 输出比较1 快速使能
TIM1_CCER1 |= 0x10; //CC2为输出 高电平有效
TIM1_PSCRH = 0x00; //预分频 0
TIM1_PSCRL = 0x03; //16M/(1+3)=4 M
TIM1_ARRH = FRE >> 8; //设定自动重装载值高8位
TIM1_ARRL = FRE; //设置自动重装载值低8位
TIM1_BKR = 0x80; //刹车寄存器 使能OC1输出 定时器不工作时输出无效电平
TIM1_EGR = (1<<0); //产生更新事件
TIM1_CR1 |= 0x01; //使能计数器
}
//TIM1 CH2 PC7
void TIM1_CH2_OUT( unsigned int DC )
{
TIM1_CCR2H = DC >> 8; //捕获比较寄存器高8位
TIM1_CCR2L = DC; //捕获比较寄存器低8位 占空比值
}
首先初始化要用到的IO口,这里使用的是定时器1的通道2也就是PC7口,下来设置定时器1的通道2为PWM输出模式,设置PWM模式的时候要使能PWM的预装载功能,这样重新设置占空比的时候,定时器会自动装载新设置的占空比值。
将设置占空比单独封装一个函数,要改变占空比的时候,只需要调用这个函数,将占空比传递进来就行。下来在主函数中不停的按照正弦规律改变占空比值就行了。
#include "iostm8s103F3.h"
#include "pwm.h"
const unsigned int sineData[64] = {50, 54, 59, 64, 69, 73, 77, 81, 85, 88, 91, 94, 96, 97, 99, 99, 100, 99, 99, 97, 96, 94, 91, 88, 85, 81, 77, 73, 69, 64, 59, 54, 50,
45, 40, 35, 30, 26, 22, 18, 14, 11, 8, 5, 3, 2, 0, 0, 0, 0, 0, 2, 3, 5, 8, 11, 14, 18, 22, 26, 30, 35, 40, 45
};
void SysClkInit( void )
{
CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率
CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频
}
void delay_ms( unsigned int ms )
{
unsigned int i, j;
while( ms != 0 )
{
for( i = 0; i < 61; i++ )
for( j = 0; j < 50; j++ );
ms--;
}
}
void main( void )
{
unsigned char i = 0;
SysClkInit();
__asm( "sim" );
TIM1_Init();
__asm( "rim" );
while( 1 )
{
for( i = 0; i < 64; i++ )
{
TIM1_CH2_OUT( sineData[i] );
delay_ms( 1 );
}
}
}
输出PWM波形如下
在PWM输出口PC7口加上RC电路后波形如下
占空比的数值和RC电路的参数选择,根据实际项目要求自行调整。
完整工程下载链接 STM8单片机输出SPWM波