STM8S003F3P6单片机共有三个定时器定时器1、定时器2、定时器4。其中定时器1为16位高级定时器,定时器2为16位通用定时器,定时器4为8位基本定时器。定时器1和定时器2可以输出PWM波。其中定时器1有4个通道,定时器2有3个通道。
现在让定时器1和定时器2所有通道同时输出PWM波。
首先初始化定时器IO口
通过最小系统图可以看出定时器通道对应的IO口为:
TIM1_CH1–>PC6,
TIM1_CH2–>PC7,
TIM1_CH3–>PC3,
TIM1_CH4–>PC4,
TIM2_CH1–>PC5,
TIM2_CH2–>PD3,
TIM2_CH3–>PA3,
将定时器对应的IO口都设置为推挽输出模式。因为要输出PWM波,IO口必须要有输出高低电平的能力。所以设置为推挽输出。
IO口初始化代码如下:
void PWM_GPIO_Init( void )
{
PC_DDR |= ( 1 << 6 ); //PC6 推挽输出
PC_CR1 |= ( 1 << 6 );
PC_DDR |= ( 1 << 7 ); //PC7 推挽输出
PC_CR1 |= ( 1 << 7 );
PC_DDR |= ( 1 << 3 ); //PC3 推挽输出
PC_CR1 |= ( 1 << 3 );
PC_DDR |= ( 1 << 4 ); //PC4 推挽输出
PC_CR1 |= ( 1 << 4 );
PC_DDR |= ( 1 << 5 ); //PC5 推挽输出
PC_CR1 |= ( 1 << 5 );
PD_DDR |= ( 1 << 3 ); //PD3 推挽输出
PD_CR1 |= ( 1 << 3 );
PA_DDR |= ( 1 << 4 ); //PA3 推挽输出
PA_CR1 |= ( 1 << 4 );
}
将定时器相关IO口都设置为推挽输出。
下来初始化定时器1
//定时器1初始化
void TIM1_Init( void )
{
PWM_GPIO_Init();
TIM1_CCMR1 = 0x60; //TIM1 CH1 输出模式 PWM1
TIM1_CCER1 |= 0x01; //CC1为输出
TIM1_CCMR2 = 0x60; //TIM1 CH2 输出模式 PWM1
TIM1_CCER1 |= 0x10; //CC2为输出
TIM1_CCMR3 = 0x60; //TIM1 CH3 输出模式 PWM1
TIM1_CCER2 |= 0x01; //CC3为输出
TIM1_CCMR4 = 0x60; //TIM1 CH4 输出模式 PWM1
TIM1_CCER2 |= 0x10; //CC4为输出
TIM1_PSCRH = 0x00;
TIM1_PSCRL = 0x00; //16M/(1+0)=16 1分频 16M
TIM1_ARRH = FRE >> 8; //设定自动重装载值高8位
TIM1_ARRL = FRE; //设置自动重装载值低8位
TIM1_BKR = 0x80; //刹车寄存器 使能OC1输出 定时器不工作时输出无效电平
TIM1_CR1 |= 0x01; //允许定时器中断
}
将定时器1的4个通道都设置为PWM1模式
当计数器的值小于比较寄存器的值时输出为有效电平,否则输出为无效电平。假如设置1为有效电平,那么0就是无效电平。如果设置0为有效电平,那么1就是无效电平。电平有效位设置是在CCER寄存器中。
CC1P是设置通道1的有效电平,CC1NP是设置通道1的互补通道有效电平。寄存器复位值为0,也就是默认高电平有效。此处用默认值就可以。
CC1E是开启通道输出PWM波功能,我们要输出PWM波就必须打开此功能。CC1E是设置打开通道1PWM输出功能,CC1NE是设置打开通道1互补输出功能。互补功能在此例程中用不到不需要打开。只需打开4个通道的PWM输出功能就可以了。
TIM1_CCMR1 = 0x60; //TIM1 CH1 输出模式 PWM1
TIM1_CCER1 |= 0x01; //CC1为输出
TIM1_CCMR2 = 0x60; //TIM1 CH2 输出模式 PWM1
TIM1_CCER1 |= 0x10; //CC2为输出
TIM1_CCMR3 = 0x60; //TIM1 CH3 输出模式 PWM1
TIM1_CCER2 |= 0x01; //CC3为输出
TIM1_CCMR4 = 0x60; //TIM1 CH4 输出模式 PWM1
TIM1_CCER2 |= 0x10; //CC4为输出
这几行代码就是设置TIM1的4个通道输出模式为PWM1模式,然后分别打开各个通道的输出功能。
下来设置定时器的自动装载值和预分频值
TIM1_PSCRH = 0x00;
TIM1_PSCRL = 0x00; //16M/(1+0)=16 1分频 16M
TIM1_ARRH = FRE >> 8; //设定自动重装载值高8位
TIM1_ARRL = FRE; //设置自动重装载值低8位
设置预分频值为0,也就是不分频,使用系统时钟,系统时钟为内部16M晶振。所以定时器1的时钟频率为16MHz,下来设置自动装载值,也就是设置PWM的输出频率。为了方便修改频率值,这块设置了一个宏定义。
#define FRE 200 //frequency 频率
FRE的值定义为200,时钟频率是16MHz,自动装载值为200,那么PWM的输出频率就为16MHz / 200 = 80KHz。所以定时器1通道的输出频率就为80KHz,由于一个定时器只有一个自动重装载寄存器,所以每个定时器的所有通道输出频率都是一样的。也就是说定时器1的通道1到通道4的输出频率都为80KHz。
设置好频率之后,使能定时器就可以了。定时器1是高级定时器,所以设置控制寄存器CR1使能计时器输出之后,还必须设置一下刹车寄存器,在刹车寄存器中开启主输出使能。
定时器开启后,下来就可以输出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;
}
//TIM1 CH3 PC3
void TIM1_CH3_OUT( unsigned int DC )
{
TIM1_CCR3H = DC >> 8;
TIM1_CCR3L = DC;
}
//TIM1 CH4 PC4
void TIM1_CH4_OUT( unsigned int DC )
{
TIM1_CCR4H = DC >> 8;
TIM1_CCR4L = DC;
}
通过4个函数单独设置通道1到通道4的占空比。
定时器1初始化完成之后,下来初始化定时器2,定时器2初始化方法和定时器1比较类似。唯一的区别就是,定时器2没有刹车寄存器,直接使能定时器输出就可以了。
定时器2初始化代码如下:
void TIM2_Init( void )
{
TIM2_CCER1 |= 0x01; //CC1输出
TIM2_CCMR1 = 0x60; //TIM2 CH1 输出模式PWM1
TIM2_CCER1 |= 0x10; //CC2输出
TIM2_CCMR2 = 0x60; //TIM2 CH2 输出模式PWM1
TIM2_CCER2 |= 0x01; //CC3输出
TIM2_CCMR3 = 0x60; //TIM2 CH3 输出模式PWM1
TIM2_PSCR = 0x01;
TIM2_ARRH = FRE >> 8;
TIM2_ARRL = FRE;
TIM2_CR1 |= 0x01;
}
//TIM2 CH1 PC5
void TIM2_CH1_OUT( unsigned int DC )
{
TIM2_CCR1H = DC >> 8;
TIM2_CCR1L = DC;
}
//TIM2 CH2 PD3
void TIM2_CH2_OUT( unsigned int DC )
{
TIM2_CCR2H = DC >> 8;
TIM2_CCR2L = DC;
}
//TIM2 CH3 PA3
void TIM2_CH3_OUT( unsigned int DC )
{
TIM2_CCR3H = DC >> 8;
TIM2_CCR3L = DC;
}
定时器2初始化完成之后,就可以在主函数中分别控制各个通道的占空比了。
#include "iostm8s103F3.h"
#include "led.h"
#include "pwm.h"
void SysClkInit( void )
{
CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率
CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频
}
void delay_ms( unsigned int ms )
{
unsigned char i;
while( ms != 0 )
{
for( i = 0; i < 250; i++ );
for( i = 0; i < 75; i++ );
ms--;
}
}
void delay_us( unsigned int Tus )
{
__asm( "nop" );
}
void main( void )
{
SysClkInit();
__asm( "sim" ); //禁止中断
LED_GPIO_Init();
TIM1_Init();
TIM2_Init();
__asm( "rim" ); //开启中断
delay_ms( 500 );
TIM1_CH1_OUT( 100 );
TIM1_CH2_OUT( 100 );
TIM1_CH3_OUT( 100 );
TIM1_CH4_OUT( 100 );
TIM2_CH1_OUT( 100 );
TIM2_CH2_OUT( 100 );
TIM2_CH3_OUT( 100 );
while( 1 )
{
LED = 0;
delay_ms(500);
LED = 1;
delay_ms(500);
}
}
定时器1和定时器2的频率可以设置不一样,但是定时器每个通道的频率不能单独设置。也就是说定时1的4个通道是一个频率,定时器2的3个通道是一个频率。每个通道的占空比可以独立控制。
在烧写程序的时候要注意一个问题:STM8单片机有些引脚默认功能不是定时器功能,需要通过设置选项字,将定时器功能打开。选项字可以在程序中通过代码设置,也可以在烧写软件上设置。一般在烧写软件上设置比较简单。
首先打开烧写软件
点击左上角第二个文件夹的按钮打开要烧写的文件,然后点右下方OPTION BYTE 选项字设置选项。
AFR7-----AFR0 就是设置每个引脚的默认功能,此处需要设置AFR0,也就是PC5引脚。
可以看到PC5、PC6、PC7引脚默认功能是SPI,而我们需要将这三个脚设置为定时器功能。
用鼠标在PC5那一行字上点一下,然后最右边会出现一个黑色小三角,然后用鼠标点一下黑色小三角。
这时就会出现一个下拉框,在下拉框中选择最下面一项。
选择好之后就可以看到PC5的默认功能为定时器2通道1,PC6的默认功能为定时器1通道1,PC7的功能为定时器1通道2。也就是说这个选项一次设置的是3个IO口的默认功能,当选择一个一个IO口的功能后,其他两个默认IO口功能都会改变。
设置好IO口默认功能后,点下载按钮下载程序就可以了。
下载按钮是第二个,红色向下箭头的图标。这样单片机就可以同时输出7路PWM波了。如果单片机某些引脚没有输出波形,可能是定时器的功能未开启,就要检查烧写软件上的选项字设置是否正确了。
上一篇:STM8学习笔记---定时器 TIM2功能实现
下一篇:STM8学习笔记---定时器 TIM4功能实现
推荐阅读最新更新时间:2024-11-13 09:47
设计资源 培训 开发板 精华推荐
- LT1761ES5-BYP/SD 演示板、SOT-23、100mA LDO 稳压器、2 个电路:低输出噪声和低电流关断
- SSM2167 具有可变压缩和噪声门控的低压麦克风前置放大器的典型应用
- 单火线30W,100W和200W3路控制器
- AR0821CSSC18SMEAH3-GEVB:带有 8MP RGB 18deg 电子卷帘快门 CMOS 图像传感器的 8.3MP 评估板
- EVAL-ADM1063TQEB,评估 ADM1063ASU 电压监控器排序器的评估板
- NCV33174DTBR2G 单+5V 交流耦合反相放大器典型应用
- LTC3245HMSE 高效降压-升压型电荷泵稳压 5V 输出的典型应用电路
- MC34072VDR2G 二阶高通有源滤波器的典型应用
- LTC2908IDDB-B1、12V、3.3V、2.5V、1.8V、1.5V、1.2V六电源监视器的典型应用电路
- LTC2908CTS8-A1、12V、2.5V、1.8V、1.5V、1.2V、1V六电源监视器的典型应用电路