找回密码
 立即注册
楼主: yangjq

手册写不清,调试搞昏头 !都是坑! STC8G单片机SFR地址的寄存器

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2026-01-27 09:02:27
已绑定手机

5

主题

8

回帖

56

积分

注册会员

积分
56
发表于 2026-1-27 10:34:35 | 显示全部楼层
写了个测试程序,这是异常的程序,函数ChangePwm执行有问题输出脉宽明显不对
#include "stc8g.h"
#include <stdio.h>
#include <string.h>

void  PWMInit(void)
{
  CCON=0x00;       //CF:PCA计数器溢出可触发中断  CR:计数器启动,-,-,-,CCF2,CCF1,CCF0  后三位是PCA匹配或捕获标志,可触发中断
  CMOD=0x08;       //CIDL:空闲允许计数,- ,- ,-,CSPS[2:0] 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[1:0]取值:0-3 对应8,7,6,10位PWM,XCCAPH[1:0]10位PWM高2位重载,XCCAPL[1:0]10PWM高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);
}

把函数 ChangePwm改成这样,就对了
void ChangePwm(unsigned int lumin)
{
unsigned char byteh,bytel,pcapwm1;
lumin=1023-lumin;
bytel=lumin%256;
byteh=lumin/256;      //10位PWM的比较值高两位在PCA_PWM寄存器的第五位和第四位
byteh=byteh<<4;

pcapwm1=PCA_PWM1;    //注意PCA_PWM1虽然SFR地址空间,但只能整体写入
pcapwm1&=(~0x30);    //先清除
pcapwm1|=byteh;
if(lumin==1023)  pcapwm1|=0x02;   //完全关闭
else pcapwm1&=(~0x02);
PCA_PWM1=pcapwm1;
CCAP1H=bytel;
}
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2026-01-27 09:02:27
已绑定手机

5

主题

8

回帖

56

积分

注册会员

积分
56
发表于 2026-1-27 10:36:50 | 显示全部楼层
通过 汇编发现    KEIL编译后    ORL或ANL 对 PCA_PWM1无效。  PCA_PWM1位于 SFR地址空间0xf3处,正常的逻辑操作指令是可以直接寻址的
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:569
  • 最近打卡:2026-03-21 12:57:21

0

主题

74

回帖

2396

积分

金牌会员

积分
2396
发表于 2026-1-27 10:45:07 | 显示全部楼层
P_SW2 = 0x80;
极速截图202601271044.png
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:724
  • 最近打卡:2026-03-18 07:56:47
已绑定手机

97

主题

7244

回帖

1万

积分

超级版主

积分
13791
发表于 2026-1-27 10:49:56 | 显示全部楼层
高2位和低8位必须连续写,先写PCA_PWMx再写CCAPxH
读-修改-写的方式会打断这个连续的过程
  1. void PWM_Out(unsigned int pwm_0,pwm_1,pwm_2)
  2. {
  3.         unsigned char temp_l,temp_h,temp;
  4.         
  5.         temp_l=pwm_0&0x00ff;                //读pwm_0低8位赋值给temp_l
  6.         temp_h=(pwm_0&0x0300)>>4;        //读pwm_0高2位,移动到XCCAP0H(PCA_PWM0[5:4])位置,赋值给temp_h
  7.         temp=PCA_PWM0&0xcd;                        //读PCA_PWM0,XCCAP2H(PCA_PWM0[5:4])、EPC0H(PCA_PWM0[1])清零后赋值给temp
  8.         temp_h|=temp;                                //写其他位到temph
  9.         if(pwm_0==0x03ff)                        //如果pwm_0最大
  10.                 temp_h|=0x02;                        //设置EPC0H(PCA_PWM0[1])为1
  11.         PCA_PWM0=temp_h;                        //写PCA_PWM0(先写高2位)
  12.         CCAP0H=temp_l;                                //写CCAP0H(再写低8位)
  13.         
  14.         temp_l=pwm_1&0x00ff;                //读pwm_1低8位赋值给temp_l
  15.         temp_h=(pwm_1&0x0300)>>4;        //读pwm_1高2位,移动到XCCAP1H(PCA_PWM1[5:4])位置,赋值给temp_h
  16.         temp=PCA_PWM1&0xcd;                        //读PCA_PWM1,XCCAP1H(PCA_PWM2[5:4])、EPC1H(PCA_PWM1[1])清零后赋值给temp
  17.         temp_h|=temp;                                //写其他位到temph
  18.         if(pwm_1==0x03ff)                        //如果pwm_1最大
  19.                 temp_h|=0x02;                        //设置EPC1H(PCA_PWM1[1])为1
  20.         PCA_PWM1=temp_h;                        //写PCA_PWM1(先写高2位)
  21.         CCAP1H=temp_l;                                //写CCAP1H(再写低8位)
  22.         
  23.         temp_l=pwm_2&0x00ff;                //读pwm_2低8位赋值给temp_l
  24.         temp_h=(pwm_2&0x0300)>>4;        //读pwm_2高2位,移动到XCCAP2H(PCA_PWM2[5:4])位置,赋值给temp_h
  25.         temp=PCA_PWM2&0xcd;                        //读PCA_PWM2,XCCAP2H(PCA_PWM2[5:4])、EPC2H(PCA_PWM2[1])清零后赋值给temp
  26.         temp_h|=temp;                                //写其他位到temph
  27.         if(pwm_2==0x03ff)                        //如果pwm_2最大
  28.                 temp_h|=0x02;                        //设置EPC2H(PCA_PWM2[1])为1
  29.         PCA_PWM2=temp_h;                        //写PCA_PWM2(先写高2位)
  30.         CCAP2H=temp_l;                                //写CCAP2H(再写低8位)
  31. }
复制代码



回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2026-01-27 09:02:27
已绑定手机

5

主题

8

回帖

56

积分

注册会员

积分
56
发表于 2026-1-27 10:50:08 | 显示全部楼层

尊敬的 蜗***,  PCA_PWM1 地址是0xf3,它位于SFR地址区域,并非位于扩展的XFR区域
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2026-01-27 09:02:27
已绑定手机

5

主题

8

回帖

56

积分

注册会员

积分
56
发表于 2026-1-27 11:04:33 | 显示全部楼层
Debu*** 发表于 2026-1-27 10:49
高2位和低8位必须连续写,先写PCA_PWMx再写CCAPxH
读-修改-写的方式会打断这个连续的过程

问题就是  编译器产生的汇编代码     
ANL  PCA_PWM1  #0cf   
是否算写入了PCA_PWM1?

高级语言中,改变寄存器的某些位,一般都是读取,处理,再写入,下面这种写法很常见
PCA_PWM1&=XXX    或者是PCA_OWM1|=xxx    ,
PWM1又是位于 SFR地址区 编译器编译后  就是
ANL  PCA_PWM1,#XXX  或者  ORL PCA_PWM1,#XXX

STC对于这样的指令执行结果就是寄存器不变。 对于这样的结果,需要在手册中标识清楚,要求用户显示的用  PCA_PWM1=某个值, 或者在下个流片版本中修复这个问题

点评

PCA_PWMx(高2位)有缓冲寄存器,写CCAPxH(低8位)时才会一并写入,硬件上保证原子操作,避免两个寄存器不同步导致写入错误的值  详情 回复 发表于 2026-1-27 15:27
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:670
  • 最近打卡:2026-03-21 10:38:33

9

主题

614

回帖

4288

积分

论坛元老

积分
4288
发表于 2026-1-27 11:08:33 | 显示全部楼层
某些外设相关寄存器是不能直接参与计算的,需要中间变量运算后再写入.
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2026-01-27 09:02:27
已绑定手机

5

主题

8

回帖

56

积分

注册会员

积分
56
发表于 2026-1-27 11:14:03 | 显示全部楼层
网*** 发表于 2026-1-27 11:08
某些外设相关寄存器是不能直接参与计算的,需要中间变量运算后再写入.

“某些”是指哪些?手册是否需要告诉用户?  为啥基础的51或者52  SFR支持这种操作?,手册需要告诉用户哪些操作是和原本的51核不兼容
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:359
  • 最近打卡:2026-03-20 21:53:40

844

主题

1万

回帖

2万

积分

管理员

积分
22719
发表于 2026-1-27 12:10:02 | 显示全部楼层

陈工说:
能否提供完整的可以复现问题的简单测试项目程序
上传上来,他帮您排查,您错在哪或KEIL-C51如何表现的,

否则不知你错在哪

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:307
  • 最近打卡:2026-03-19 10:21:34

84

主题

7299

回帖

1万

积分

超级版主

积分
15676
发表于 2026-1-27 13:27:52 | 显示全部楼层
不会吧?我们都是各种直接计算操作,从没出过问题:

截图202601271327476117.jpg

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-22 06:23 , Processed in 0.117012 second(s), 88 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表