梁工 发表于 2026-1-27 13:27:52

不会吧?我们都是各种直接计算操作,从没出过问题:



乘风飞扬 发表于 2026-1-27 14:50:42

STC8G系列10位PCA型PWM占空比设置,PCA_PWMx的值要用一条指令写入,不能分多条指令去写(“读-修改-写”)。PWM在运行过程中,写入的高2位会先保存在内部的BUF里面,而没有真正写入寄存器,所以也无法读取刚才写入的高2位值。只有在写CCAPxH寄存器时,才将高2位真正写入PCA_PWMx,才能读取。
可以参考上面梁工提供的例子设置。

DebugLab 发表于 2026-1-27 15:27:32

yangjq 发表于 2026-1-27 11:04
问题就是编译器产生的汇编代码   
ANLPCA_PWM1#0cf   
是否算写入了PCA_PWM1?


PCA_PWMx(高2位)有缓冲寄存器,写CCAPxH(低8位)时才会一并写入,硬件上保证原子操作,避免两个寄存器不同步导致写入错误的值

yangjq 发表于 2026-1-27 16:29:53

神农鼎 发表于 2026-1-27 12:10
陈工说:
能否提供完整的可以复现问题的简单测试项目程序?
上传上来,他帮您排查,您错在哪或KEIL-C51如 ...
完整代码已经在主贴了,我再贴一下也行
#include "stc8g.h"
#include <stdio.h>
#include <string.h>

voidPWMInit(void)
{
CCON=0x00;       //CF:PCA计数器溢出可触发中断CR:计数器启动,-,-,-,CCF2,CCF1,CCF0后三位是PCA匹配或捕获标志,可触发中断
CMOD=0x08;       //CIDL:空闲允许计数,- ,- ,-,CSPS CCA时钟选择,ECF:计数溢出中断使能          CSPS: 0:SYSCLK/12,1:SYSCLK/2,2:T0溢出脉冲 3:ECI引脚 4:SYSCLK 5:SYSCLK/4 6:SYSCLK/6 7:SYSCLK/8   
      //位定义:-,ECOM:允许比较,CCAPP:上升沿捕获,CCAPN:下降沿捕获,MAT0:允许匹配,TOG0:允许高速脉冲输出,PWM0:PWM使能,ECCF0:允许捕获匹配中断
CCAPM1=0x42;      
      //位定义:EBS取值:0-3 对应8,7,6,10位PWM,XCCAPH10位PWM高2位重载,XCCAPL10PWM高2位比较,EPCnH最高位重载值,ECPL最高位比较值
PCA_PWM1=0xc0;   //采用10位PWM
PCA_PWM1|=0x3e;//10bit,9bit置1
CCAP1H=0xff;
CCAP1L=0xff;
CR=1;            //PWM计数器开始计数(PWM开始输出)
}

void ChangePwm(unsigned int lumin)
{
unsigned char byteh,bytel;
lumin=1023-lumin;
bytel=lumin%256;
byteh=lumin/256;      //10位PWM的比较值高两位在PCA_PWM寄存器的第五位和第四位
byteh=byteh<<4;

PCA_PWM1&=(~0x30);    //先清除
PCA_PWM1|=byteh;
if(lumin==1023)PCA_PWM1|=0x02;   //完全关闭
else PCA_PWM1&=(~0x02);
CCAP1H=bytel;
}

void main(void)
{
P3&=0xf3;
P5=0xff;

P3M0=0x0e;
P3M1=0x00;

P5M0=0x20;
P5M1=0x10;
PWMInit();
ChangePwm(900);
while(1);
}


乘风飞扬 发表于 2026-1-27 16:32:37

yangjq 发表于 2026-1-27 16:29
完整代码已经在主贴了,我再贴一下也行
#include "stc8g.h"
#include

PCA_PWMx的值用一条指令写入,像这样:
void UpdatePcaPwm(u8 PCA_id, u16 pwm_value)
{
      if(PCA_id == PCA0)
      {
                PCA_PWM0 = (PCA_PWM0 & ~0x32) | (u8)((pwm_value & 0x0300) >> 4) | (u8)((pwm_value & 0x0400) >> 9);
                CCAP0H = (u8)pwm_value;
      }
      else if(PCA_id == PCA1)
      {
                PCA_PWM1 = (PCA_PWM1 & ~0x32) | (u8)((pwm_value & 0x0300) >> 4) | (u8)((pwm_value & 0x0400) >> 9);
                CCAP1H = (u8)pwm_value;
      }
      else if(PCA_id == PCA2)
      {
                PCA_PWM2 = (PCA_PWM2 & ~0x32) | (u8)((pwm_value & 0x0300) >> 4) | (u8)((pwm_value & 0x0400) >> 9);
                CCAP2H = (u8)pwm_value;
      }
}
官网8G-8H库函数例程包里面的“STC8G_PCA.c”文件,或者独立程序“30-PCA-3路硬件PWM模式呼吸灯程序-STC8G”例子可以参考。
库函数例程包下载页面:https://www.stcai.com/khs
页: 1 2 [3]
查看完整版本: 手册写不清,调试搞昏头 !都是坑! STC8G单片机SFR地址的寄存器