STM8学习笔记---定时器输出7路PWM波

发布者:琴弦悠扬最新更新时间:2020-01-03 来源: eefocus关键字:STM8  定时器输出  7路PWM波 手机看文章 扫描二维码
随时随地手机看文章

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  定时器输出  7路PWM波 引用地址:STM8学习笔记---定时器输出7路PWM波

上一篇:STM8学习笔记---定时器 TIM2功能实现
下一篇:STM8学习笔记---定时器 TIM4功能实现

推荐阅读最新更新时间:2024-11-13 09:47

stm8用什么软件编程?stm8开发环境搭建手把手教程!
STM8单片机开发环境的由3部分组成:电脑端开发环境、目标板、烧录仿真器。 我们要具备以上3个条件才能开始STM8单片机的开发,下面我们为大家详细讲解下STM8的开发环境搭建。 STM8目标板: STM8 单片机系统硬件,我们最终要编程的目标。 烧录仿真器:连接电脑和目标的编译连接器,主要作用:仿真、程序烧录、软件调试。 电脑端开发环境: 单片机程序的开发是在电脑上完成的,我们需要在电脑端搭建单片机对应的开发环境。 接下来,我们就详细的给大家介绍一下STM8单片机开发环境搭建。 1.STM8目标板: 目标单片机电路板就是要开发的STM8单片机系统硬件了,如下图: 这个是我们无际单片机编程带学员研发的l
[单片机]
<font color='red'>stm8</font>用什么软件编程?<font color='red'>stm8</font>开发环境搭建手把手教程!
STM8 通用输入输出口(GPIO)
每个端口都分配的寄存器有:输出寄存器(ODR),输入寄存器(IDR),数据方向寄存器(DDR),控制寄存器1(CR1)和控制寄存器2(CR2).后面三个寄存器组和可以配置为8种GPIO的模式。一个I/O口工作在输入还是输出是取决于该口的数据方向寄存器的状态。通过在ODR、IDR中置0/1,达到数据输入输出的通断。 GPIO主要功能 可选择的输入模式:浮动输入和带上拉输入 可选择的输出模式:推挽式输出和开漏输出 数据输入和输出采用独立的寄存器 外部中断可以单独使能和关闭 输出摆率控制用以减少EMC噪声 片上外设的I/O功能复用 当作为模拟输入时可以关闭输入施密特触发器来降低功耗 在数据输出锁存时支持
[单片机]
<font color='red'>STM8</font> 通用输入<font color='red'>输出</font>口(GPIO)
定时器输出比较模式产生的PWM的频率计算
定时器的输出比较模式产生的PWM波的频率计算的公式:72M/((2*(arr+1))*(psc+1) ) 比如设置: PWM_Init(1000-1,72-1); (PWM_Init(arr,psc);) 则每路PWM频率为500Hz 。 PWM_Init(arr,psc) { TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler =psc; }
[单片机]
STM8 STVD 关于#error clnk Debug\gpiotest.lkf
之前在用stvd 在编译的时候出现的问题 ! 由于在网上找了 半天没有找到合理的解决方案 最后还是自己折腾了半天 弄出来的了 选择这里 默认是Debug 然后将他改成Release 编译一下,要是不放心 还可以Debug 一下 。 然后 再重新选回Debug ,因为再Release 下面不能调试 汗!! 然后错误就解决了!!
[单片机]
<font color='red'>STM8</font> STVD 关于#error clnk Debug\gpiotest.lkf
stm8 stvd工程头文件包含方式
方式一:在Include Files上右键 add files to folder把.h文件添加到该组下, 添加完编译成功之后,下面窗口会多出一个预处理包含路径(若有错误没有编译成功,则看不到) 方式二:project Settings-c compiler- category-Preprocessor---additional include directories,依次添加要包含的头文件路径
[单片机]
<font color='red'>stm8</font> stvd工程头文件包含方式
各种版本的ST-LINK仿真器
1、ST官方正式出版了两种仿真器:ST-LINK、ST-LINK/V2,其他型号(ST-LINK II,ST-LINK III,…)要么是国内公司生产,要么是开发板自带的; 2、在ST官网ST-LINK的状态为NRND(not recommended for new designs),官方已经不建议在新产品设计中使用该产品; 3、ST-LINK/V2是官方最新主推的STM8、STM32仿真器,内部电路、接口保护均作了改进; 还有一个支持隔离的ST-LINK/V2版本,order code是ST-Link/V2-ISOL,多用来调试STM32的马达应用。 用JLink也可以,但需要外带一个隔离板(STM32电机套件上有,要
[单片机]
各种版本的ST-LINK仿真器
STM8低功耗问题
在使用STM8S003时碰到一个问题:为了降低MCU功耗,在初始化时候禁止了施密特触发器,发现IO- PD3作为输入寄存器IDR一直为0。于是查找资料发现IO口作为输入时候必须开启施密特触发。 另外当IO口复用ADC功能时候也需要注意此寄存器设置,网上搜索问题原因的时候看到因ADC和UART复用时候关掉了触发器产生的问题,帖子如下: http://www.eepw.com.cn/article/201609/310076.htm
[单片机]
<font color='red'>STM8</font>低功耗问题
stm8 bootloader IAP升级
首先,stm8的中断向量的跳转地址是固定的。也就是说发生中断时,芯片会跳转到0x8000对应中断的偏移地址。而大部分bootloader都是在该区域实现。也就是说中断向量会被bootloader所占用。当用户程序执行中断时会跳转到bootloader程序的中断向量。也就会执行bootloader对应的中断。如果要执行用户代码区的中断函数则需要在bootloader的向量表区存放跳转置用户软件中断向量表。如下图跳转: 填写图片摘要(选填) 以上是带有bootloader的用户软件的运行步骤,这样在bootloader区按道理是无法实现中断的。因为向量表是跳转到用户软件向量表。实质上是可以同时在boot和app区实现中断的,但为了
[单片机]
<font color='red'>stm8</font> bootloader IAP升级
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved