本篇文章由 VeriMake 旧版论坛中备份出的原帖的 Markdown 源码生成
原帖标题为:以 CH549 为例的 51 教程 | 图文 4. 脉冲宽度调制 PWM
原帖网址为:https://verimake.com/topics/259 (旧版论坛网址,已失效)
原帖作者为:Xy(旧版论坛 id = 73,注册于 2020-10-15 13:03:26)
原帖由作者初次发表于 2021-08-19 15:39:05
📇 点此回到教程主索引
目录
PWM 介绍
PWM 具体代码解析
makefile 的修改方法
实验现象
PWM 介绍
Pwm(Pulse width modulation)中文名为脉冲宽度调制。

pwm的目的是为了调节功率,具体工作方式建议参考视频。
pwm的参数:
占空比指的是在一个周期内高电平时间占整个周期时间的比例,充分的反应了功率的控制情况。
频率为周期的倒数。
PWM 具体代码解析
编写的pwm例程使用的是沁恒官方提供的库,我们将CH549_PWM.c文件放在source文件夹中,将将CH549_PWM.h文件放在inc文件夹中。
<!--
-->
main.c
/**
******************************************************************
* @file main.c
* @author xy
* @version V1.0
* @date 2021-3-31
* @brief 呼吸灯
******************************************************************
* @attention
* verimake 用于ch549例程
* 使用pwm外设让板子上的灯展示呼吸灯的效果
******************************************************************
*/
#include <CH549_sdcc.H> //ch549的头文件,其中定义了单片机的一些特殊功能寄存器
#include <CH549_PWM.H> //CH549官方提供库的头文件,定义了一些关于pwm初始化,设置等函数
/********************************************************************
* TIPS:
* 引脚 功能
* P2.5 PWM0
* P2.4 PWM1
* P2.3 PWM2
* P2.2 PWM3
* P2.1 PWM4
* P2.0 PWM5
* P2.6 PWM6
* P2.7 PWM7
*********************************************************************/
/********************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数
* 输 入 : 时间
* 输 出 : 无
********************************************************************/
void delay(long int i)
{
while(i--);
}
/*******************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
********************************************************************/
void main()
{
SetPWMClkDiv(4); //PWM时钟配置,Fsys/4,Fsys默认为12Mhz
SetPWMCycle256Clk(); //PWM周期 Fsys/4/256
/* 启动通道 */
PWM_SEL_CHANNEL(CH3,Enable); //对ch3,即p2.2,即led的pwm外设初始化
while(1)
{
int i = 0;
/*配置占空比使得led灯从灭逐步到亮*/
for ( i = 0; i <= 256; i++)
{
SetPWM3Dat(i);//配置占空比,占空比等于i/256
delay(1000);
}
/*配置占空比使得led灯从亮逐步到灭*/
for ( i = 256; i >= 0; i--)
{
SetPWM3Dat(i);//配置占空比,占空比等于i/256
delay(1000);
}
}
}
代码的重要部分
频率配置
SetPWMClkDiv(4); //PWM时钟配置,Fsys/4,Fsys默认为12Mhz
SetPWMCycle256Clk(); //PWM周期 Fsys/4/256
通过这两个函数配置pwm信号的频率,可以改变第一句的输入变量来达到控制频率的目的,在这里pwm的频率则是12Mhz/4/256。
初始化
PWM_SEL_CHANNEL(CH3,Enable); //对ch3,即p2.2,即led的pwm外设初始化
对led对应的pwm3通道初始化,如果想要同时初始化多个通道则可以使用"|"连接。
配置占空比
SetPWM3Dat(i);//配置占空比,占空比等于i/256
设定pwm信号的占空比,占空比为输入变量除以256。
整个main函数
/*******************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
********************************************************************/
void main()
{
SetPWMClkDiv(4); //PWM时钟配置,Fsys/4,Fsys默认为12Mhz
SetPWMCycle256Clk(); //PWM周期 Fsys/4/256
/* 启动通道 */
PWM_SEL_CHANNEL(CH3,Enable); //对ch3,即p2.2,即led的pwm外设初始化
while(1)
{
int i = 0;
/*配置占空比使得led灯从灭逐步到亮*/
for ( i = 0; i <= 256; i++)
{
SetPWM3Dat(i);//配置占空比,占空比等于i/256
delay(1000);
}
/*配置占空比使得led灯从亮逐步到灭*/
for ( i = 256; i >= 0; i--)
{
SetPWM3Dat(i);//配置占空比,占空比等于i/256
delay(1000);
}
}
}
通过循环让占空比逐渐变高又逐渐变低的过程。
makefile 的修改方法
对makefile文件进行配置
#使用的编译器
CC = sdcc
#传入的c文件名
TARGET_ARCH = my
C_SOURCES = \
usr/main.c \
source/CH549_PWM.c\
C_INCLUDES = \
-Iinc \
-Isource \
CFLAGS=$(C_INCLUDES)
cname = my
proj = output
tmpdir = Build
usrdir = usr
all : $(tmpdir)/$(cname).ihx $(tmpdir)/$(cname).hex
OBJECTS = $(addprefix $(tmpdir)/,$(notdir $(C_SOURCES:.c=.rel)))
vpath %.c $(sort $(dir $(C_SOURCES)))
$(tmpdir)/%.rel: %.c Makefile | $(tmpdir)
$(CC) -c $(CFLAGS) $< -o $@
$(tmpdir)/$(cname).ihx: $(OBJECTS)
$(CC) $^ -o $(tmpdir)/$(cname).ihx
$(tmpdir)/%.hex: $(tmpdir)/%.ihx | $(tmpdir)
packihx $< $@ > $(tmpdir)/$(cname).hex
$(tmpdir):
mkdir $@
.PHONY : clean
clean :
rm $(tmpdir)/*.hex
rm $(tmpdir)/*.rel
rm $(tmpdir)/*.rst
rm $(tmpdir)/*.sym
rm $(tmpdir)/*.mem
rm $(tmpdir)/*.map
rm $(tmpdir)/*.lst
rm $(tmpdir)/*.lk
rm $(tmpdir)/*.ihx
rm $(tmpdir)/*.asm
在makefile文件的第八行C_SOURCES的中添加source/CH549_PWM.c\,将CH549_PWM.c增加到编译范围内。
实验现象
将程序编译下载进开发板之后,我们就可以看到板子上的灯“呼吸”起来了。