CH559L单片机PWM功能和示例介绍
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CH559L单片机PWM功能和示例介绍相关的知识,希望对你有一定的参考价值。
【CH559L单片机】PWM功能和示例介绍
- 📍本示例资源来源于WCH官方:
https://www.wch.cn/products/CH559.html
- 📌CH559开发板《【硬件开源电路】CH559L开发板和CH55x_DAP-Link二合一开发板分享》
⛳PWM 功能
📝CH559 的 Timer3 具有 16 位 PWM 功能,除此之外还有另外 2 路 8 位 PWM,PWM 可以选择默认的输出极性为低电平或者高电平,可以动态修改 PWM 的输出占空比,通过简单 RC 电阻电容进行积分低通滤波后,即可获得各种输出电压,相当于低速数模转换器 DAC。
- 🌿PWM3 输出占空比= T3_FIFO / T3_END,支持范围 0%到 100%,如果 T3_FIFO 数值大于 T3_END
则按 100%处理。 - 🌿PWM1 输出占空比= PWM_DATA / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA 数值大于
PWM_CYCLE 则按 100%处理。 - 🌿PWM2 输出占空比= PWM_DATA2 / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA2 数值大于
PWM_CYCLE 则按 100%处理。
🔖实际应用中,建议允许 PWM 引脚输出并且设置 PWM 输出引脚为推挽输出模式。
🍂PWM1 和 PWM2 相关寄存器介绍
- 🌿PWM2 数据寄存器(PWM_DATA2):
- 🌿PWM1 数据寄存器(PWM_DATA):
- 🌿PWM 控制寄存器(PWM_CTRL):
- 🌿PWM 时钟分频设置寄存器(PWM_CK_SE):
- 🌿PWM 循环周期寄存器(PWM_CYCLE):
🌲Timer3 配置图
🍃PWM3
🌿PWM3利用的是Timer3 的 FIFO 计数器的功能输出对应的占空比。PWM3 输出占空比= T3_FIFO / T3_END,支持范围 0%到 100%,如果 T3_FIFO 数值大于 T3_END则按 100%处理。
由于PWM3使用了定时3,没有在下面的示例代码中有体现,放在了定时器3的示例代码中。
⛳PWM1和PWM2频率设置方法
- 通过PWM 时钟分频设置寄存器:
PWM_CK_SE
来设置分频系数,范围0 - 255
。
🎯PWM引脚映射
- 📜PWM默认输出引脚:
P12
、P24
、P25
- 🎉如果使能了PWM映射,那么PWM输出引脚将切换到对应的引脚上。
#define PWMPINAlter( ) P4_DIR |= bPWM2_ | bPWM1_;PIN_FUNC |= bPWM1_PIN_X; //设置PWM引脚映射
映射关系
P45 ----> PWM2
P43 ----> PWM1
P42 ----> PWM3
⌛PWM循环周期
🌿通过PWM 循环周期寄存器:
PWM_CYCLE
设置,设置范围:0 - 100
🍭PWM1
和PWM2
占空比调节设置
🌿通过PWM1 数据寄存器
和PWM2 数据寄存器:PWM_DATA
和PWM_DATA2
。支持范围 0%到 100%,如果PWM_DATA、 PWM_DATA2 数值大于PWM_CYCLE 则按 100%处理。
📖PWM1
和PWM2
输出示例
🌿
PWM1
和PWM2
输出频率为500Hz
,占比0%-99%递增、递减输出。
- 时钟采用的是内部时钟:
12MHz
/********************************** (C) COPYRIGHT *******************************
* File Name : PWM.C
* Author : WCH
* Version : V1.3
* Date : 2016/6/24
* Description : CH559 PWM接口函数
PWM3 输出占空比= T3_FIFO / T3_END,支持范围 0%到 100%,如果 T3_FIFO 数值大于 T3_END
则按 100%处理。
PWM1 输出占空比= PWM_DATA / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA 数值大于
PWM_CYCLE 则按 100%处理。
PWM2 输出占空比= PWM_DATA2 / PWM_CYCLE,支持范围 0%到 100%,如果 PWM_DATA2 数值大于
PWM_CYCLE 则按 100%处理。
实际应用中,建议允许 PWM 引脚输出并且设置 PWM 输出引脚为推挽输出模式。
*******************************************************************************/
#include "..\\DEBUG.C" //调试信息打印
#include "..\\DEBUG.H"
static UINT8 Duty=5;
#pragma NOAREGS
#define SetPWMClk(CK_SE) (PWM_CK_SE = CK_SE) //分频,默认时钟Fsys ,MAX=255
#define SetPWMCycle(Cycle) (PWM_CYCLE = Cycle)//设置循环周期
#define SetPWM1Dat(dat) (PWM_DATA = dat) //设置PWM输出占空比
#define SetPWM2Dat(dat) (PWM_DATA2 = dat)
#define PWMPINAlter( ) P4_DIR |= bPWM2_ | bPWM1_;PIN_FUNC |= bPWM1_PIN_X; //设置PWM引脚映射
/*******************************************************************************
* Function Name : InitPWM1(UINT8 polar)
* Description : PWM1初始化函数
* Input : polar=0选择默认低电平,高电平输出有效;
polar=1选择默认高电平,低电平输出有效;
* Output : None
* Return : None
*******************************************************************************/
void InitPWM1(UINT8 polar)
PWM_CTRL &= ~bPWM_CLR_ALL; //清空FIFO和计数
PWM_CTRL &= ~bPWM_MOD_MFM;
PWM_CTRL |= bPWM_IE_END; //使能PWM计数周期完成中断
PWM_CTRL |= bPWM_OUT_EN; //PWM1输出使能
PWM_CTRL |= bPWM_IF_END; //清除所有的中断标志
if(polar)
PWM_CTRL |= bPWM_POLAR; //低电平有效
else
PWM_CTRL &= ~bPWM_POLAR; //高电平有效
/*******************************************************************************
* Function Name : InitPWM2(UINT8 polar)
* Description : PWM初始化函数
* Input : polar=0选择默认低电平,高电平输出有效;
polar=1选择默认高电平,低电平输出有效;
* Output : None
* Return : None
*******************************************************************************/
void InitPWM2(UINT8 polar)
PWM_CTRL &= ~bPWM_CLR_ALL; //清空FIFO和计数
PWM_CTRL &= ~bPWM_MOD_MFM;
PWM_CTRL |= bPWM_IE_END; //使能PWM计数周期完成中断
PWM_CTRL |= bPWM2_OUT_EN; //PWM2输出使能
PWM_CTRL |= bPWM_IF_END; //清除所有的中断标志
if(polar)
PWM_CTRL |= bPWM2_POLAR; //低电平有效
else
PWM_CTRL &= ~bPWM2_POLAR; //高电平有效
/*******************************************************************************
* Function Name : PWMInterrupt(void)
* Description : PWM中断服务程序
*******************************************************************************/
void PWMInterrupt( void ) interrupt INT_NO_PWM1 using 1 //PWM1&2中断服务程序,使用寄存器组1
if(PWM_CTRL & bPWM_IF_END)
Duty +=1;
Duty %=100;
PWM_DATA = Duty;
PWM_DATA2 = 100-Duty;
PWM_CTRL |= bPWM_IF_END;//PWM 循环周期结束中断标志位清零
printf("PWM1_DATA:%03u ,PWM2_DATA:%03u \\n",(UINT16)PWM_DATA,(UINT16)PWM_DATA2);
void main( )
// UINT8 i;
mDelaymS(30); //上电延时,等待内部晶振稳定,必加
CfgFsys( );
PORT_CFG &= ~bP2_OC;
P2_DIR |= bPWM1 | bPWM2; //P24 P25 开启PWM建议设置引脚为推挽输出
mInitSTDIO( ); //串口0,可以用于调试
printf("start ...\\n");
#if 0
PWMPINAlter( ); //引脚映射
#endif
SetPWMClk(240);//设置PWM1&2的时钟分频系数为12,f=Fose/240=50KHz,最大分频数:255
InitPWM1(1);//PWM1初始化,低电平有效
InitPWM2(0);//PWM2初始化,高电平有效
SetPWMCycle(100); //设置循环周期f/100,支持范围 0%到 100%
IE_PWM1 = 1; //使能PWM1中断
PWM_DATA = Duty;
PWM_DATA2 = 100-Duty;
// SetPWM1Dat(Duty); //PWM1占空比设置50/100
// SetPWM2Dat(100-Duty); //PWM1占空比设置50/100
EA = 1; //中断总开关
while(1)
- 🌿通过逻辑分析仪测得频率
- 🌿通过串口打印实时动态变化的PWM1和PWM2占空比值
- 输出呼吸灯效果
- 🌿如果想输出1KHz的PWM,那么,设置:
SetPWMClk(120);
即可。 - 🌿如果想输出10KHz的PWM,那么,设置:
SetPWMClk(12);
即可。 - 🌿如果想输出20KHz的PWM,那么,设置:
SetPWMClk(6);
即可。
🔖如果时钟配置成24MHz,那么对应的输出频率将翻倍。
📝时钟配置函数
/*******************************************************************************
* Function Name : CfgFsys( )
* Description : CH559时钟选择和配置函数,默认使用内部晶振12MHz,如果定义了FREQ_SYS可以
根据PLL_CFG和CLOCK_CFG配置得到,公式如下:
Fsys = (Fosc * ( PLL_CFG & MASK_PLL_MULT ))/(CLOCK_CFG & MASK_SYS_CK_DIV);
具体时钟需要自己配置
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void CfgFsys( )
#if OSC_EN_XT
SAFE_MOD = 0x55; //开启安全模式
SAFE_MOD = 0xAA;
CLOCK_CFG |= bOSC_EN_XT; //使能外部晶振
mDelaymS(10);
SAFE_MOD = 0x55; //开启安全模式
SAFE_MOD = 0xAA;
CLOCK_CFG &= ~bOSC_EN_INT;
SAFE_MOD = 0x00;
#else
SAFE_MOD = 0x55; //开启安全模式
SAFE_MOD = 0xAA;
CLOCK_CFG &= ~MASK_SYS_CK_DIV;
// CLOCK_CFG |= 6; //配置系统时钟48MHz
// CLOCK_CFG |= 8; //配置系统时钟36MHz
// CLOCK_CFG |= 10; //配置系统时钟28.8MHz
// CLOCK_CFG |= 12; //配置系统时钟24MHz
// CLOCK_CFG |= 16; //配置系统时钟18MHz
CLOCK_CFG |= 24; //内部时钟频率是 12MHz
/*56MHz
// CLOCK_CFG &= ~MASK_SYS_CK_DIV;
// CLOCK_CFG |= 6; //配置系统时钟56MHz
PLL_CFG = 0xFC;
*/
SAFE_MOD = 0xFF; //关闭安全模式
// 如果修改主频,要同时修改FREQ_SYS,否则会造成延时函数不准
#endif
以上是关于CH559L单片机PWM功能和示例介绍的主要内容,如果未能解决你的问题,请参考以下文章