PWM(Pulse Width Modulation)脉宽调制,其利用微控制器的数字输出,对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等许多领域。
解析用例:
传感器通过PWM的低电平持续时长来表述当前环境PM2.5浓度数值,在一个周期内(2000ms),低电平持续时长越短,数值越小,反之越大。
代码实现(STC版):
#include "Pwm.h"
void Pwm_Init(void)
{
//端口支持PWM通道 CFG = 0x12(PG0) 0x13(PG1) 0x14(PG2) 0x15(PG3) 0x16(PG4) 0x17(PG5)
//一个引脚适配多个通道且只能用一个通道,同一个通道适配不同引脚且只能用一个引脚
P13CFG = GPIO_PG0; //GPIO复用PG0
P1TRIS |= BIT3; //输出
P1OD &= ~BIT3; //挽推
//独立模式、边沿对齐
PWMCON = 0x00;
// BIT7BIT6 BIT5BIT4 BIT3 BIT2 BIT1 BIT0
// 保留(00) 00独立模式 0独立模式 0对称计数 0边沿对其 保留(0)
// 01互补模式 1PG0控制PG2PG4 1非对称计数 1中心对其
// 10同步模式 PG1控制PG3PG5
// 11保留
PWMPINV = 0x00;//通道x反向输出 //输出不反向
PWMCNTM |= PG0;//通道x自动加载模式
PWM01PSC = 1499;//PG0&PG1时钟预分频 Sys_Clk / (PWM01PSC + 1) = PG0&PG1_Clk
// 24M / (1499 + 1) = 16k
PWM0DIV = 0x03;//通道x时钟分频 //0x00 PGx_Clk / 2
//0x01 PGx_Clk / 4
//0x02 PGx_Clk / 8
//0x03 PGx_Clk / 16 // 16K / 16 = 1K
//0x04 PGx_Clk
//其他 Sys_Clk
}
/**
* @brief PWM数据输出
* @param ucSele:Put使能位 usPm2_5Data: PM2.5数据(0~1000)
* @retval 无
*/
void Pwm_DataOutPut(u8 ucSele, u16 usPm2_5Data)
{
xdata u16 usMsData = 1999; // 1k / (1999 + 1) = 0.5Hz
xdata u16 usDutyCycle = usPm2_5Data; //占空比
if(ucSele)
{
PWMP0H = (usMsData >> 8) & 0x00FF; //通道x周期数据寄存器
PWMP0L = usMsData & 0x00FF; //通道x时钟 / 周期+1 = 通道x频率
PWMD0H = (usDutyCycle >> 8) & 0x00FF; //通道x比较数据寄存器(占空比数据)
PWMD0L = usDutyCycle & 0x00FF; //占空比
PWMLOADEN |= PG0; //通道x数据加载使能(周期、占空比)
PWMOE |= PG0; //通道X输出使能
PWMCNTE |= PG0; //通道x计数器开启
}
else
{
PWMCNTE &= ~PG0; //通道x计数器停止
PWMLOADEN &= ~PG0; //通道x数据加载禁止(周期、占空比)
PWMOE &= ~PG0; //通道X输出禁止
PWMCNTE &= ~PG0; //通道x计数器停止
}
}