历史上的今天
今天是:2024年09月22日(星期日)
2021年09月22日 | STM8学习笔记---PWM互补波形输出
2021-09-22 来源:eefocus
脉宽调制(PWM,Pulse Width Modulation)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
常见的用法是输出一路PWM波,可以通过调节PWM的频率和占空比来控制电路。还有另一种方法是输出一组互补的PWM波,这两个波形频率相同,相位相反,两组波形之间有死区控制时间。
STM8单片机自带PWM互补波形输出功能,通过资料可以看出 STM8共有3个死区时间可调的互补输出。

本次实验用的STMs8003单片机有2个互补输出。

PC6口和PC3口是定时器1通道1互补输出。PC7口和PC4口是定时器1通道2互补输出。
要配置输出互补PWM波,只需要在输出PWM的基础上,开启互补输出功能就行。
只需要在CCER寄存器中开启CCxNE寄存器,就能开启互补输出功能。
如果需要设置死区时间,还需要配置DTR寄存器。

下来看一下程序中如何配置
void PWM_GPIO_Init( void )
{
PC_DDR |= ( 1 << 6 ); //PC6 推挽输出
PC_CR1 |= ( 1 << 6 );
PC_DDR |= ( 1 << 3 ); //PC3 推挽输出
PC_CR1 |= ( 1 << 3 );
PC_DDR |= ( 1 << 7 ); //PC7 推挽输出
PC_CR1 |= ( 1 << 7 );
PC_DDR |= ( 1 << 4 ); //PC4 推挽输出
PC_CR1 |= ( 1 << 4 );
}
设置 IO口,将IO口设置为推挽输出。
下来初始化定时器
#define FRE 320
//定时器1初始化
void TIM1_Init( void )
{
PWM_GPIO_Init();
TIM1_CR1 = (1<<7); //自动预装载允许
//设置TIM1 CH1 与 TIM1 CH1N通道
TIM1_CCMR1 = (6<<4)|(1<<3)|(1<<2); //TIM1 CH1 PWM1 输出比较1预装载使能 输出比较1 快速使能
//TIM1_CCER1 |= 0x01; //CC1为输出 高电平有效
TIM1_CCER1 |= (1<<0)|(1<<2); //CC1为输出 OC1高电平有效 开启OC1N OC1N高电平有效
//设置TIM1 CH2 与 TIM1 CH2N通道
TIM1_CCMR2 =(6<<4)|(1<<3)|(1<<2); //TIM1 CH2 输出模式 PWM1 输出比较2预装载使能 输出比较2 快速使能
//TIM1_CCER1 |= (1<<4); //CC2为输出 关闭互补输出
TIM1_CCER1 |= (1<<4)|(1<<6); //CC2为输出 互补输出使能
TIM1_PSCRH = 0x00; //预分频 0
TIM1_PSCRL = 0x00; //16M
TIM1_ARRH = FRE >> 8; //设定自动重装载值高8位
TIM1_ARRL = FRE; //设置自动重装载值低8位
//TIM1_BKR |= (1<<7)|(1<<4); //刹车寄存器 使能OC1输出 定时器不工作时输出无效电平 开启刹车输入 刹车输入低电平有效
TIM1_BKR |= (1<<7); //主输出使能 关闭刹车输入
TIM1_DTR = 0x18; //死区时间 24*125ns=3000ns
TIM1_EGR = (1<<0); //产生更新事件
TIM1_CR1 |= 0x01; //使能计数器
}
定时器初始化完成后,用一个单独的函数来调节PWM的占空比。
//TIM1 CH1 PC6
void TIM1_CH1_OUT( unsigned int DC )
{
TIM1_CCR1H = DC >> 8; //捕获比较寄存器高8位
TIM1_CCR1L = DC; //捕获比较寄存器低8位 占空比值
}
//TIM1 CH2 PC7
void TIM1_CH2_OUT( unsigned int DC )
{
TIM1_CCR2H = DC >> 8;
TIM1_CCR2L = DC;
}
下来在主函数中调用占空比修改函数,就能设置占空比了。
void main( void )
{
SysClkInit();
__asm( "sim" ); //禁止中断
TIM1_Init();
__asm( "rim" ); //开启中断
delay_ms( 500 );
TIM1_CH1_OUT(FRE/3); //设置占空比为33%
TIM1_CH2_OUT(FRE/3);
while( 1 )
{
}
}
主函数就比较简单了,初始化完定时器,然后设置输出占空比就可以了。
下来还有一个最重要的步骤,需要配置STM8的选项字。因为互补输出不是IO口的默认功能,要使用互补输出还需要将引脚功能手动设置为互补输出。
设置选项字比较简单的方法就是通过STVP软件设置,详细设置方法参见 如何设置STM8单片机选项字 这篇博客。
打开STVP软件,然后添加要烧写的HEX文件。

然后切换到 OPTION BYTE界面

AR7 ---- AR0就是设置IO口默认功能选项。

点一下AFR7后面选项那个倒三角符号

然后在出现的下拉框中选择 Port C3 Alternate Function = TIM1_CH1N,Port C4 Alternate Function = TIM1_CH2N选项。
这个选项的意思就是将PC3设置为定时器1通道1互补输出功能,将PC4设置为定时器1通道2互补输出功能。而默认选项的是将PC3设置为定时器1通道3,将PC4设置为定时器1通道4。
如果不设置选项字,刚才的程序烧写后,单片机的PC3和PC4引脚是没有任何波形输出的。
按照同样的方法设置AFR0选项,将PC6和PC7设置为定时器功能。

设置完成后如下图所示

只需要设置AFR7和AFR0两个选项就行,其他的为默认值。如果互补输出时用到了刹车功能,这里就还要设置一个AFR4选项。本次实验中没有用到刹车功能,所以就不需要设置AFR4。设置完成后烧写程序就行。
输出波形如下所示

可以看到两个波形是互补输出的,但是两个波形占空比相差比较大,这是因为为了方便观察,将死区时间设置的比较大,代码中的死区时间为3us。
在代码中将死区时间设置为250ns

再看下输出波形

死区时间设置比较小的时候,输出的波形,看起来基本对称了。
这时PWM的互补输出功能就成功实现了。
史海拾趣
|
小可刚接触USB(ez usb 68013)开发,遇到一个问题百思不得其解,想向大家讨教一下: 我用的是公板的驱动和固件,在应用程序里开双线程读数据(inBulkControl.pipeNum=1,),如果在读取的过程中再发送数据(outBulkControl.pipeNum=0),有时程序会停在读取数 ...… 查看全部问答> |
|
看了[url=http://www.hzlitai.com.cn/article/ARM9-article/1685.html][/url]尝试让系统睡眠 ; Sometimes it is not working in cache mode. So I modify to jump to ROM area. ldr ...… 查看全部问答> |
|
最近要做DMA,有点疑惑向大家请教。 我有一个ARM处理器,支持外部DMA,我的ARM会和一个FPGA相连,从FPGA里面DMA出数据来。从硬件上来说,ARM的片选3接到了FPGA上面,我想应该是基于片选3的地址空间来读数据,对吧。如果从FPGA来DMA数据,我是不是 ...… 查看全部问答> |
|
用pb定制操作系统,用的是s3c2400+arm9,分辨率320x240,现在想使屏幕转转90度,没有用自带的显示驱动,用的是sm501显示芯片及驱动。请高手指教!… 查看全部问答> |
|
Driver studio 在VS2005下build出现问题 刚开始接触驱动程序的编写,想在winXP下用VS2005来写编写一些驱动,但是出现了一些问题。 我安装那三个文件的顺序是这样子的: 1。VS2005 在D盘 2。DDK (Windows XP SP1 DDK),装在F盘 ...… 查看全部问答> |
|
SD卡本身有SDIO和SPI两种接口,ti给出的解决方案是SPI接口的驱动SLAA281b, 但是本身没有文件系统,在和PC交互数据的时候不太方便。在ti原驱动上, 挂了FATFS的文件系统,FATFS本身是开源的,我用得是v0.8。中间提供几个和 底层驱动的调用函数就 ...… 查看全部问答> |






