it编程 > 硬件开发 > 单片机

STC8增强型单片机进阶开发--LED呼吸灯(PWM)

77人参与 2024-08-06 单片机

知不足而奋进 望远山而前行

文章目录


前言

学习pwm(脉宽调制)是探索数字信号转模拟信号的重要一步,尤其在控制电路输出方面具有广泛的应用。本次学习将聚焦于了解pwm的基础概念、掌握在stc8h芯片上配置pwma的方法以及应用实践。通过深入学习pwm技术,您将能够控制各种设备的亮度、速度等参数,从而在工程和电子领域中做出更多创新。


目标

  1. 了解pwm基础概念和工作原理
  2. 学习如何在stc8h上配置pwma
  3. 掌握pwma的各个配置
  4. 学习如何使用pwma控制led亮度
  5. 掌握调试pwm的方法

内容

pwm基础概念

pwm全称是脉宽调制(pulse width modulation),是一种通过改变信号的脉冲宽度来控制电路输出的技术。pwm技术在工业自动化、电机控制、led调光等领域广泛应用。

pwm是一种将数字信号转换为模拟信号的技术,它通过改变信号的占空比来控制输出的电平。在stc8h中,pwm输出的频率占空比可以由程序控制,因此可以用来控制各种电机、灯光和其他设备的亮度、速度等参数。

stc8h芯片

stc8h 系列的单片机内部集成了8 通道 16 位高级pwm 定时器,分成两周期可不同的 pwm,分别命名为 pwma 和pwmb ,可分别单独设置。

第一组 pwma 可配置成4 组互补/对称/死区控制的pwm 或捕捉外部信号。

第二组 pwmb 可配置成4 路pwm 输出或捕捉外部信号。

两组 pwm 的时钟频率可分别独立设置。

pwm与引脚对应关系如下图:

pwm

pwm通道

对应引脚

pwmxp

pwmxn

pwma

pwm1p & pwm1n

p1.0

p1.1

p2.0

p2.1

pwm2p & pwm2n

p5.4

p1.3

p2.2

p2.3

pwm3p & pwm3n

p1.4

p1.5

p2.4

p2.5

pwm4p & pwm4n

p1.6

p1.7

p2.6

p2.7

p3.4

p3.3

pwmb

pwm5

p0.0

p1.7

p2.0

pwm6

p0.1

p2.1

p5.4

pwm7

p0.2

p2.2

p3.3

pwm8

p0.3

p2.3

p3.4

pwma应用

控制引脚p2.7实现led灯1的呼吸效果。

  1. 拷贝所需库文件(其他必备库请自行准备)
    1. stc8h_pwm.cstc8h_pwm.h
    2. nvic.cnvic.h
    3. switch.h
  1. 导入头文件,初始化宏及全局变量
#include "config.h"
#include "gpio.h"
#include "delay.h"
#include "nvic.h"
#include "switch.h"
#include "stc8h_pwm.h"

#define led_sw	p45

#define led1		p27
#define led2		p26
#define led3		p15

#define freq		1000

#define period 	((main_fosc / freq) - 1)	// 周期

pwmx_duty dutya;
  1. 配置gpio
void gpio_config(void) {
    gpio_inittypedef	gpio_initstructure;		//结构定义
    // led_sw
    gpio_initstructure.pin  = gpio_pin_5;		//指定要初始化的io,
    gpio_initstructure.mode = gpio_out_pp;	//指定io的输入或输出方式,gpio_pullup,gpio_highz,gpio_out_od,gpio_out_pp
    gpio_inilize(gpio_p4, &gpio_initstructure);//初始化
    // p2
    gpio_initstructure.pin  = gpio_pin_6 | gpio_pin_7;		//指定要初始化的io,
    gpio_initstructure.mode = gpio_pullup;	//指定io的输入或输出方式,gpio_pullup,gpio_highz,gpio_out_od,gpio_out_pp
    gpio_inilize(gpio_p2, &gpio_initstructure);//初始化
}
  1. 配置pwm
void	pwm_config(void)
{
    pwmx_initdefine		pwmx_initstructure;
		
	// 配置pwm4
    pwmx_initstructure.pwm_mode    =	ccmrn_pwm_mode2;	//模式,		ccmrn_freeze,ccmrn_match_valid,ccmrn_match_invalid,ccmrn_rollover,ccmrn_force_invalid,ccmrn_force_valid,ccmrn_pwm_mode1,ccmrn_pwm_mode2
    pwmx_initstructure.pwm_duty    =  0;								//pwm占空比时间, 0~period
    pwmx_initstructure.pwm_enoselect  = eno4p | eno4n;	//输出通道选择,	eno1p,eno1n,eno2p,eno2n,eno3p,eno3n,eno4p,eno4n / eno5p,eno6p,eno7p,eno8p
    pwm_configuration(pwm4, &pwmx_initstructure);

	// 配置pwma
    pwmx_initstructure.pwm_period   = period;					//周期时间,   0~65535
    pwmx_initstructure.pwm_deadtime = 0;					//死区发生器设置, 0~255
    pwmx_initstructure.pwm_mainoutenable= enable;			//主输出使能, enable,disable
    pwmx_initstructure.pwm_cen_enable   = enable;			//使能计数器, enable,disable
    pwm_configuration(pwma, &pwmx_initstructure);			//初始化pwm通用寄存器,  pwma,pwmb

	// 切换pwm4选择pwm4_sw_p26_p27
    pwm4_sw(pwm4_sw_p26_p27);			//pwm4_sw_p16_p17,pwm4_sw_p26_p27,pwm4_sw_p66_p67,pwm4_sw_p34_p33

	// 初始化pwma的中断
    nvic_pwm_init(pwma,disable,priority_0);
}
  1. 编写main函数

void main() {
    char direction = 1;
    u8 duty_percent = 0;// 0 -> 100

    eaxsfr();		/* 扩展寄存器访问使能, 必写! */
    gpio_config();
    pwm_config();
    ea = 1;

    // 总开关
    led_sw = 0;
    led1 = 0; // p2.7 pwm4
    led2 = 0;
    led3 = 0;

    // 循环之前,设置一次pwm(可选)
    dutya.pwm4_duty = period * duty_percent / 100;
    updatepwm(pwm4, &dutya);
    // 0 -> 100
    while(1) {
        duty_percent += direction;
        // 让duty_percent一直在0-100来回往返
        if(duty_percent >= 100) {
            duty_percent = 100;
            direction = -1;
        } else if(duty_percent <= 0) {
            duty_percent = 0;
            direction = 1;
        }
        // 修改pwm4的duty
        dutya.pwm4_duty = period * duty_percent / 100;
        updatepwm(pwm4, &dutya);
				
        delay_ms(10);
    }
}

pwm配置详解

周期

系统主频:1秒钟计数多少次。

代码中的pwm周期(pwm period),指的是按n等份切分1秒钟,每个等份的计数值。

例如上图,我们按照8等份切分1秒钟的总计数值main_fosc(主频),每个pwm周期的计数值为:

pwm_period = main_fosc / 8 = 24m / 8 = 3m = 3 000 000 单位为次。

即如果将这个3m作为period参数,可以得到pwm方波每个周期的时长为:

1 / 8 = 0.125s

代码中的配置:

#define period 	(main_fosc / freq)	// 周期
pwmx_initstructure.pwm_period   		= period - 1;

配置的是周期中的计数值。

我们的理解策略:通常我们不关心计数值,关心的是1秒钟执行多少次(即频率hz),也就是一秒钟多少个周期。

因此在代码main_fosc / 1000中的1000表示的是1秒钟多少个周期(即频率hz)。

main_fosc / 1000表示的是每个周期的计数值。那为什么要-1呢?因为计数器是从0开始计数的。

占空比

在一个pwm的周期计数中,高电平的计数时长百分比。

模式

常用的为pwm 模式 1pwm 模式 2

pwm 模式 1和pwm 模式 2是反向的,一个占空比越大越亮,一个是越小越亮。

使能pwm
pwmx_initstructure.pwm_mainoutenable= enable;			//主输出使能, enable,disable
pwmx_initstructure.pwm_cen_enable   = enable;			//使能计数器, enable,disable
pwm_configuration(pwma, &pwmx_initstructure);			//初始化pwm通用寄存器,  pwma,pwmb
引脚配置
pwm4_sw(pwm4_sw_p26_p27);

使能配置成功后,pwm才能工作。

如果运行中pwm想停止掉,也可以通过配置使能来停止。

eaxsfr扩展寄存器

由于pwm的配置相关特殊功能寄存器位于扩展ram区域,访问这些寄存器,需先将p_sw2的bit7设置为1,才可正常读写。

eaxsfr();		/* 扩展寄存器访问使能 */

详细可参见stc8手册:


总结

通过本次学习,您已经了解了pwm的基本概念和工作原理,掌握了在stc8h上配置pwma的步骤以及pwm的各种配置参数。此外,您还学会了如何利用pwm控制led的亮度,并掌握了调试pwm的方法

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

MPU6050六轴陀螺仪外围电路分析

08-06

【ESP32最全学习笔记(基础篇)——4.ESP32 引脚介绍】

08-06

单片机之蜂鸣器

08-06

(一)、为什么要学习FreeRTOS和单片机的选型?

08-06

51单片机-60秒计时

08-06

TFT驱动ST7789使用总结

08-02

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论