16399812@qq.com 发表于 前天 11:35

stc8g1k08A 配置内部晶振后串口输出显示不正常

我用stc8g1k08A默认晶振,使用默认配置方式,定时器中断中,串口能正常打印输出,但是键入如下配置后,串口打印输出是乱码,什么原因啊?麻烦帮我分析下:


/***************************主函数区域****************************/
void main(void)
{
        u8 i;
//------------------选择22.1184MHZ----------加入如下6行后,定时器输出是乱码------------------       
        P_SW2=0X80;
        CLKDIV=0X02;    //0X04;
        IRTRIM=T22M_ROMADDR;
        VRTRIM=VRT20M_ROMADDR;
        IRCBAND=0X00;
        CLKDIV=0;
//----------------------------------------------------       
//      HIRCCR = 0x80; //启动内部 IRC
//      while (!(HIRCCR & 1)); //等待时钟稳定
//      CLKDIV = 4;
//      CLKSEL = 0x00; //选择内部 IRC ( 默认 )       
       
       
       
       
        io_init();

       
        delay(5);                        //等待I/O模式配置稳定
        RED=1;GREEN=1;BLUE=1;        //上电后熄灭RGB灯
        UART1_init();        //串口1初始化
UART2_init();               

        Time0_init();        //定时计数器0初始化
        EA=1;                                        //打开单片机总中断开关EA
        TR0=1;                                //定时器0开始计时       
       

       
        delay(100);                //等待配置稳定
printf("**************************************************\r\n");

while(1)
        {
               
               
               
               

if(time_1s_flag==1)
       {
                time_1s_flag=0;
               k++;// SendData(0xaa);
                  printf("|测试定时器0输出------------------------%d-----:\r\n ",k);
//          SendData(0xaa);
       }   

国芯人工智能 发表于 前天 11:38

您好,关于您在使用 STC8G1K08A 单片机时,配置内部晶振后串口输出出现乱码的问题,以下将从多个角度进行专业分析,帮助您排查问题原因。

一、问题描述总结
使用默认晶振配置时,串口输出正常;
加入如下配置代码后,串口输出乱码:
c
PSW2 = 0X80;
CLKDIV = 0X02;   
IRTRIM = T22MROMADDR;
VRTRIM = VRT20MROMADDR;
IRCBAND = 0X00;
CLKDIV = 0;
串口初始化代码未更改;
问题出现在定时器中断中串口打印输出异常。

二、问题可能原因分析

1. 系统时钟配置错误导致波特率偏差

串口通信依赖于准确的系统时钟(SYSCLK)和波特率设置。若您修改了系统主频(例如从默认的 11.0592MHz 改为 22.1184MHz 或其他频率),但未同步更新串口波特率寄存器的设置,则会导致串口通信速率不匹配,表现为乱码。

建议检查以下内容:
系统时钟频率是否与串口波特率计算一致;
UART初始化函数中是否使用了正确的系统时钟值;
是否使用了固定波特率除数(如使用定时器1模式2),而未根据新的主频重新计算。

2. CLKDIV 设置不当导致系统时钟分频错误

您在代码中对 CLKDIV 进行了两次写入:
c
CLKDIV = 0x02;
...
CLKDIV = 0;

这可能导致系统时钟分频系数被覆盖,实际运行频率与预期不符。

建议:
确认 CLKDIV 的最终值是否符合预期;
CLKDIV = 0x02 表示系统时钟为 SYSCLK/3,CLKDIV = 0 表示 SYSCLK/1;
确保在设置完 CLKDIV 后没有被意外修改;
推荐将 CLKDIV 的设置放在最后,避免被其他配置影响。

3. IRTRIM / VRTRIM 配置不当导致时钟精度下降

您使用了:
c
IRTRIM = T22MROMADDR;
VRTRIM = VRT20MROMADDR;

这两个寄存器用于校准内部时钟频率。但需注意:
T22MROMADDR 和 VRT20MROMADDR 是否为芯片内部预存的校准值;
是否在使用前确认了该芯片支持该频率的校准值;
如果校准值不正确或未启用内部高频时钟(HIRC),可能导致系统时钟不稳定或频率不准。

建议:
确保 IRTRIM 和 VRTRIM 的值是芯片出厂校准值;
可以通过示波器测量系统时钟引脚(如使用 XTAL 引脚作为时钟输出)来验证实际主频;
若不确定校准值是否正确,可尝试使用默认高频 IRC(HIRC)进行测试。

4. CLKSEL 未设置导致时钟源选择错误

您注释掉了以下代码:
c
// HIRCCR = 0x80; //启动内部 IRC
// while (!(HIRCCR & 1)); //等待时钟稳定
// CLKDIV = 4;
// CLKSEL = 0x00; //选择内部 IRC ( 默认 )

这部分代码是标准的时钟初始化流程,用于选择内部高频时钟源并等待其稳定。

问题可能在于:
您设置了 CLKDIV 和 IRCBAND,但未明确设置 CLKSEL 来选择当前使用的时钟源;
若未正确切换时钟源,可能导致系统运行在错误的时钟上,进而影响串口波特率和定时器中断时间。

建议:
在设置完时钟相关寄存器后,明确设置 CLKSEL 以选择正确的系统时钟源;
建议在设置完所有时钟配置后添加延时或等待时钟稳定标志。

三、推荐调试步骤

步骤 1:确认系统主频是否设置正确

可通过以下方式验证:
使用定时器测量一个已知时间(如 1ms);
或使用示波器测量定时器中断的输出频率;
或通过串口输出一个固定频率的调试信息(如每秒输出一次 "Hello");
若输出频率明显不一致,说明系统时钟设置有误。

步骤 2:检查串口波特率配置是否匹配当前主频

例如,若使用定时器1生成波特率:

c
TH1 = TL1 = 256 - (SYSCLK / 12 / 32 / BAUD);

请确认 SYSCLK 是否与当前主频一致(如 22.1184MHz)。

步骤 3:逐步注释时钟配置代码进行排查

逐一注释以下代码,观察串口是否恢复正常:

c
PSW2=0X80;
CLKDIV=0X02;   
IRTRIM=T22MROMADDR;
VRTRIM=VRT20MROMADDR;
IRCBAND=0X00;
CLKDIV=0;

以确定是哪一行配置导致了问题。

四、优化后的配置建议

以下是一个推荐的配置流程(假设目标系统时钟为 22.1184MHz):

c
PSW2 = 0x80;         // 解锁寄存器
CLKDIV = 0;         // 不分频,系统时钟为 IRC 主频
IRTRIM = T22MROMADDR; // 设置 IRC 校准值
VRTRIM = VRT20MROMADDR;
IRCBAND = 0x00;       // 选择 IRC 频段
CLKSEL = 0x00;      // 选择内部 IRC 为系统时钟源
PSW2 = 0x00;         // 锁定寄存器

同时确保在串口初始化时使用正确的系统时钟值。

五、总结

| 可能原因 | 是否排查 | 建议操作 |
|----------|----------|-----------|
| 波特率配置不匹配 | ✅ | 检查串口初始化代码中的 SYSCLK 和波特率计算 |
| CLKDIV 设置错误 | ✅ | 确认最终 CLKDIV 值是否与预期一致 |
| IRTRIM / VRTRIM 值不正确 | ✅ | 确认是否为芯片出厂校准值 |
| 未设置 CLKSEL 导致时钟源错误 | ✅ | 明确设置 CLKSEL 选择系统时钟源 |
| 未等待时钟稳定 | ✅ | 增加延时或等待 HIRCCR 稳定标志 |

六、结语

STC8系列单片机的时钟系统较为灵活但也复杂,建议在配置时严格按照数据手册流程操作,尤其是时钟切换和校准步骤。若您方便提供串口初始化函数和定时器中断函数,我可以进一步分析是否存在其他潜在问题。

如需进一步协助,请提供以下信息:

1. 串口初始化函数;
2. 定时器中断服务函数;
3. 实际使用的系统主频和波特率;
4. 使用的开发环境(如 Keil、SDCC)和编译器版本。

祝您调试顺利!

[本文内容由国芯人工智能辅助生成,仅供参考]

乘风飞扬 发表于 前天 12:09

你的串口波特率发生器参数是按照22.1184MHz计算出来的吗?

16399812@qq.com 发表于 前天 13:06

#define FOSC 11059200UL   //系统外部时钟频率(无符号长整型)
#define BAUD 9600         //欲配置的串口通信波特率值
//   串口波特率发生器参数是按照11.0592MHz计算出来的
/****************************************************************/
//串口1初始化函数UART1_init(),无形参,无返回值
/****************************************************************/
void UART1_init(void)
{
        SCON=0x50;        //8位数据,可变波特率,允许接收
        AUXR|=0x40;        //定时器1时钟为Fosc,即1T
        AUXR&=0xFE;        //串口1选择定时器1为波特率发生器
        TMOD&=0x0F;        //设定定时器1为16位自动重装方式
        TL1=(65536-(FOSC/4/BAUD));   //设置波特率重装值
TH1=(65536-(FOSC/4/BAUD))>>8;//设置波特率重装值
        ET1=0;                        //禁止定时器1中断
        TR1=1;                        //启动定时器1
ES=1;                                //使能UART中断开关ES
EA=1;                                //使能单片机总中断开关EA
}

DebugLab 发表于 前天 21:30

检查时钟和波特率设置是否匹配


_奶咖君_ 发表于 昨天 11:31

还有一件事,CLKDIV一般ISP软件会给你配置好,软件上虽然写得是IRC的配置,实际上配置的结果已经是分频之后的时钟了,除非你自己清楚的明白,CLKDIV应该怎么改,否则就不要去操作他
页: [1]
查看完整版本: stc8g1k08A 配置内部晶振后串口输出显示不正常