8G系列的PCA/CCP/PWM, 10位PWM
用下述程序使用PCA/CCP/PWM模块发送10位PWM,程序逻辑都是对的,这个我经过反复验证,当我用电位器进行调节时,输出的波形频率是对的,
占空比只能打到24%,并不能跟着采样值一直打到100%,
想问一下我这个程序有什么问题,还是其他?
leitang 发表于 2024-4-7 19:21
梁工,我按你的说法,加了一个延时,确实是可以了,但还是pwm还有很明显的抖动,这个如何处理
10位PWM例程写好了,测试无任何问题,
P1.2接电位器输入ADC2,10位ADC结果送PCA2-P3.7输出10位PWM,
下载选择11.0592MHz主频的话,PWM频率就是11059200/1024=10800Hz。
用户请先别修改程序, 直接下载"ADC.hex"测试.
下载时选择主频11.0592MHZ(其它频率也可以)。
本程序演示ADC2(P1.2)接电位器并将ADC值送给
10位PWM2输出(P3.7-PCA2).
请看视频:
void PCA_Init()
{
CCON=0x00;//关闭PCA计数器,清除相关标志位
CMOD=0x0a;//PCA时钟源为系统时钟4分频
CL=0x00;//计数器清零
CH=0x00;
/*------------------------PWM2部分-----------------------------*/
CCAPM2 = 0x40;//使能PCA模块2_PWM输出
CCAP2L=0X00; //捕获比较寄存器低8位,比较值
CCAP2H=0X00; //捕获比较寄存器高8位,重装值
PCA_PWM2=0xC0;//10位PWM输出
// CCAPM2=0x42; //使能PCA模块2_PWM输出
}
void PWM2_Set_Duty(u16 Duty)
{
//注意:在更新 10 位 PWM 的重载值时,必须先写高两位 XCCAPnH,再写低 8 位 CCAPnH。
// CCAPM2 &= 0x40; //使能PCA模块2_PWM输出
PCA_PWM2&= ~(3<<4); //清零重装值高2位
PCA_PWM2|=(Duty>>4)&0x30; //设置新的重装值高2位
CCAP2H = Duty; //重装值低8位
CCAPM2 = 0x42; //使能PCA模块2_PWM输出
CR = 1; //启动计数器
}
//***************主函数**********************
void main()
{
u16 a;
P3M0 &= ~0x0c; P3M1 |= 0x0c; //IO口初始化
P5M0 |= 0x30; P5M1 &= ~0x30;
p1 = 0; //单片机工作指示灯
p2 = 0; //清除mos管的干扰(只在测试程序时使用)
PCA_Init(); //PCA初始化,打开PWM模块
while (1)
{
Get_ADC(0x02); //启动AD采样,打开采样通道2
a = ~(ADC_RES << 8| ADC_RESL); //将AD采样的值付给a,并取反,使其占空比随着采样电压的增大而变大
PWM2_Set_Duty(a); //跟随AD采样值打占空比
}
} 可能是我描述不详细,大概就是低位CCAP2H里的值正常跟随采样值走,但高位每一次赋值的时候都感觉把高位清零了,而且此时正好也是低位数据全为零的状态,所以占空比就会突然从24%下降到0%,然后继续增大采样值就会从零在慢慢打到24%,我想请问一下,如何解决这个问题
神农鼎 发表于 2024-4-5 20:03
大佬,这个10位pwm的范例程序我用过,但是10位打满占空比和前面的不一样,他需要另一个寄存器来放入高两位,也就是PCA_PWM2这个寄存器中的xccapnh,我是按照数据手册给的要求编写的
#include "reg51.h"
#include "intrins.h"
sfr CCON = 0xd8;
sbit CF = CCON^7;
sbit CR = CCON^6;
sbit CCF2 = CCON^2;
sbit CCF1 = CCON^1;
sbit CCF0 = CCON^0;
sfr CMOD = 0xd9;
sfr CL = 0xe9;
sfr CH = 0xf9;
sfr CCAPM0= 0xda;
sfr CCAP0L= 0xea;
sfr CCAP0H= 0xfa;
sfr PCA_PWM0 =0xf2;
sfr CCAPM1= 0xdb;
sfr CCAP1L= 0xeb;
sfr CCAP1H= 0xfb;
sfr PCA_PWM1 =0xf3;
sfr CCAPM2= 0xdc;
sfr CCAP2L= 0xec;
sfr CCAP2H= 0xfc;
sfr PCA_PWM2 =0xf4;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
CCON = 0x00;
CMOD = 0x08; //PCA时钟为系统时钟
CL = 0x00;
CH = 0x00;
//--6位PWM--
CCAPM0 = 0x42; //PCA模块0为PWM工作模式
PCA_PWM0 = 0x80; //PCA模块0输出6位PWM
CCAP0L = 0x20; //PWM占空比为50%[(40H-20H)/40H]
CCAP0H = 0x20;
//--7位PWM--
CCAPM1 = 0x42; //PCA模块1为PWM工作模式
PCA_PWM1 = 0x40; //PCA模块1输出7位PWM
CCAP1L = 0x20; //PWM占空比为75%[(80H-20H)/80H]
CCAP1H = 0x20;
//--8位PWM--
//CCAPM2 = 0x42; //PCA模块2为PWM工作模式
//PCA_PWM2 = 0x00; //PCA模块2输出8位PWM
//CCAP2L = 0x20; //PWM占空比为87.5%[(100H-20H)/100H]
//CCAP2H = 0x20;
//--10位PWM--
CCAPM2 = 0x42; //PCA模块2为PWM工作模式
PCA_PWM2 = 0xc0; //PCA模块2输出10位PWM
CCAP2L = 0x20; //PWM占空比为96.875%[(400H-20H)/400H]
CCAP2H = 0x20;
CR = 1; //启动PCA计时器
while (1);
}
{:4_167:} 神农鼎 发表于 2024-4-5 20:28
大佬,我这个不是单纯的只要发10位pwm波,这个我已经验证过了,是完全可行的,我前面还有一个AD采样,我想的是让采样值控制10位pwm的占空比,现在就是我的高两位的值好像赋不上取又好像是被清零了,我就想问问大佬我这个程序的问题