历史上的今天
返回首页

历史上的今天

今天是:2025年01月03日(星期五)

正在发生

2020年01月03日 | STM8学习笔记---定时器输出7路PWM波

2020-01-03 来源:eefocus

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波了。如果单片机某些引脚没有输出波形,可能是定时器的功能未开启,就要检查烧写软件上的选项字设置是否正确了。

推荐阅读

史海拾趣

正泰公司的发展小趣事

正泰公司始建于1984年,初期以低压电器业务为主。随着公司业务的不断拓展,正泰逐渐将业务范围扩展至智慧能源系统领域。在这一过程中,公司深入践行“产业化、科技化、国际化、数字化、平台化”战略举措,形成了“绿色能源、智能电气、智慧低碳”三大板块。正泰的低压电器产品长期保持国内领先地位,品牌认知度和客户粘性极强,为公司后续的发展奠定了坚实的基础。

Hmc Inc公司的发展小趣事

“Future Memory Labs”公司自成立之初,就将持续创新视为企业发展的核心动力。在HMC技术的研发和应用过程中,Future Memory Labs不断投入资源,进行技术迭代和产品升级。同时,该公司还积极构建HMC技术生态,与上下游企业建立紧密的合作关系,共同推动HMC技术的普及和应用。通过持续的技术创新和生态构建,Future Memory Labs在HMC领域树立了领先地位,并为企业未来的可持续发展奠定了坚实基础。

请注意,以上故事均为虚构,旨在展示电子行业中类似HMC技术公司可能的发展路径和策略。

Electrolube公司的发展小趣事

在电子行业的激烈竞争中,Electrolube公司始终坚持以客户需求为导向,不断创新和拓展产品线。除了UVCL涂层外,公司还推出了一系列树脂、涂料和热管理解决方案的产品组合,为EV电池提供全面保护。

这些产品不仅具有优异的性能表现,而且能够满足不同客户的需求。例如,某些产品具有优异的耐高温性能,适用于高温环境下的电子设备;而另一些产品则具有出色的耐化学腐蚀性能,能够在恶劣的工作环境中保持稳定的性能。

Electrolube公司通过不断的技术创新和产品优化,成功拓展了市场份额,并在电子行业中树立了良好的品牌形象。同时,公司还积极与各大汽车制造商合作,共同推动电动汽车产业的发展。

ALLEN BRADLEY公司的发展小趣事

在电子行业中,电池管理系统(BMS)的可靠性和耐用性一直是制造商关注的焦点。Electrolube公司凭借其在材料科学领域的深厚积累,成功推出了一款名为UVCL的新型UV固化涂层。这款涂层以其独特的特性迅速在市场中脱颖而出。

UVCL涂层采用先进的UV固化技术,能够在几秒钟内完成固化过程,大大提高了生产效率。同时,它还具有高效的湿气引发的二次固化机制,确保即使在阴影区域也能实现完全固化。这一特性对于BMS等复杂电子电路的保护至关重要。

为了将UVCL涂层推向市场,Electrolube公司的研发团队与客户紧密合作,克服了客户内部没有UV固化设施的难题。他们与信誉良好的供应商合作,提供了完整的解决方案,并成功为客户提供了原型样品单元进行现场测试。测试结果显示,UVCL涂层能够为电子电路提供最高水平的保护,且操作过程简单、应用速度快。

UVCL涂层的成功推出不仅提升了Electrolube公司在电子材料领域的地位,也为公司赢得了众多客户的信赖和好评。

Boundary Devices公司的发展小趣事

近年来,电子行业面临着诸多变革和挑战,如物联网的快速发展、人工智能的崛起等。面对这些变革,Boundary Devices积极调整战略,加强在物联网和人工智能领域的研发投入,推出了一系列符合市场趋势的新产品。同时,公司还加强与高校和研究机构的合作,共同推动电子行业的创新与发展。

Henkel公司的发展小趣事

近年来,电子行业面临着诸多变革和挑战,如物联网的快速发展、人工智能的崛起等。面对这些变革,Boundary Devices积极调整战略,加强在物联网和人工智能领域的研发投入,推出了一系列符合市场趋势的新产品。同时,公司还加强与高校和研究机构的合作,共同推动电子行业的创新与发展。

问答坊 | AI 解惑

成品库存

本帖最后由 jameswangsynnex 于 2015-3-3 20:00 编辑 库存管理实践系列:电子制造商如何应用基于连带管理的JMI模式 在通讯设备制造行业中,使用的原材料以电子元器件为主,种类繁杂,材料型号众多,原材料的生产周期时间长,具有一定程度的不可 ...…

查看全部问答>

教你怎么读数据手册(中英文两个版本)

本帖最后由 paulhyde 于 2014-9-15 03:58 编辑 大家都看看吧!  …

查看全部问答>

磁珠和电感选型

磁珠和电感选型…

查看全部问答>

!!销售/收购/维修HP8712B HP 8712B,agilent 8712b网络分析仪小兵/王S:13509239856

!!销售/收购/维修HP8712B HP 8712B,agilent 8712b网络分析仪小兵/王S:13509239856 银通仪器有限公司 手机:13509239856 TEL:0769-87912629 FAX:0769-87912842 QQ:350534337 E-MAIL:yonglin__2007@126.com(下划线两横) 地址:广东省东莞 ...…

查看全部问答>

问一下高手,关于ps/2键盘的端口读写问题

     1. 当键盘的scancode 是多个字节时,他的数据是在一个中断中全部送过来的吗?      比如 像  DELETE(E0,53) 键, E0 和53 的两个字节的数据是不是在一个键盘中断中就可以通过键盘端口 ...…

查看全部问答>

LPC2214 编译通过了,但烧录到100%的时候去失败了

我用ADS写了一个工程,编译生成了一个80多K的BIN文件,把这个文件烧录进芯片时,但在刚要烧录结束时总是失败(试了很多次)。 如果我把某一个语句删除掉或移去别的地方,或取消编译选项里的优化编译,就可以顺利地通过编译和烧录。为什么会这样? ...…

查看全部问答>

TI串口转以太网的问题

大家好的,我的开发板是利尔达的串口转以太网,芯片上LM3S6432,的使用TI里面的例程,设置为静态IP。如下: g_sParameters.ulStaticIP=0xC0A80E78;g_sParameters.ulSubnetMask=0xFFFFFF00;  g_sParameters.ulGatewayIP=0xC0A80101;  ...…

查看全部问答>

EE Logic 电源功耗分析

AMS1117-3.3V    AMS1117-2.5V   AMS1117-1.2V 在TB众多的FPGA的开发板中,这三个芯片占有很大的地位,因为简单,好用。 想当初自己画FPGA开发板的时候也是直接用的这三个芯片,也没有考虑过这样的电源设计是否合理。 看来 ...…

查看全部问答>