李唐马 发表于 2025-5-15 09:16:30

AI8H1K08 无外部晶振,可以烧录程序,但是不能实现串口通信

有一批拆机件AI8h1k08单片机可以烧录程序,但是不能实现串口,有时乱码,有时不出现数据,猜测是不出厂固件损坏?{:4_166:}

国芯人工智能 发表于 2025-5-15 09:18:00

针对STC8H1K08单片机串口通信异常问题的技术分析及解决方案

一、问题背景分析
用户反馈的STC8H1K08单片机可正常烧录程序但无法实现稳定串口通信的现象,属于典型的异步串行通信故障。由于该型号单片机采用内置RC振荡器(最高精度±1%),其通信问题通常与时钟系统、硬件设计、软件配置等环节密切相关。结合工程经验,现从以下维度展开分析:

二、核心问题排查方向
1. 时钟系统稳定性验证
内部IRC校准机制:STC8H系列内置22.1184MHz高频IRC,需通过ISP工具进行频率校准(IRCTRIM寄存器)。若校准参数丢失或错误,可能导致实际频率偏差超出±1%的容限。
时钟分频设置:烧录时选择的系统时钟频率(如5.5296MHz/11.0592MHz)必须与程序中UART波特率计算公式匹配,任何参数偏差均会导致波特率失准。
建议操作:
   a. 使用STC-ISP工具重新校准IRC频率(勾选"IRC频率调节"选项)
   b. 通过CLKOUT引脚输出时钟信号,用示波器实测频率误差(应

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

ercircle 发表于 2025-5-15 09:24:45

换个新的上去交叉对比下

haiyang201 发表于 2025-5-15 15:12:57

使用串口烧录的吗?

李唐马 发表于 2025-5-16 08:03:31

出现乱码,不稳定

#include <STC8H.H>
#include <intrins.h>

#define FOSC 11059200L      // 系统频率
#define BAUD 9600         // 波特率

/* 系统时钟初始化 */
void Clock_Init(void)
{
    P_SW2 |= 0x80;          // 允许访问XSFR
    CLKDIV = 0x00;         // 时钟不分频
    P_SW2 &= 0x7F;         // 禁止访问XSFR
}

/* 串口初始化 */
void UART_Init(void)
{
    // 设置IO口模式
    P3M0 &= ~0x30;         // P3.0(RxD)和P3.1(TxD)设为准双向口
    P3M1 &= ~0x30;
   
    // 串口配置
    SCON = 0x50;         // 8位数据,可变波特率,允许接收
    AUXR |= 0x40;          // 定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;          // 串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;          // 清除定时器1模式位
    TMOD |= 0x20;          // 设定定时器1为8位自动重装方式
   
    // 波特率设置
    TL1 = TH1 = (256 - (FOSC/4/BAUD));// 计算重装值
   
    // 启动定时器
    ET1 = 0;               // 禁止定时器1中断
    TR1 = 1;            // 启动定时器1
   
    // 中断配置(如果需要接收)
    ES = 1;               // 使能串口中断
    EA = 1;               // 开总中断
}

/* 发送一个字节 */
void UART_SendByte(unsigned char dat)
{
    SBUF = dat;
    while(!TI);         // 等待发送完成
    TI = 0;               // 清除发送中断标志
}

/* 发送字符串 */
void UART_SendString(char *s)
{
    while(*s)             // 检测字符串结束符
    {
      UART_SendByte(*s++); // 发送当前字符
    }
}

/* 接收一个字节(查询方式) */
unsigned char UART_ReceiveByte(void)
{
    while(!RI);         // 等待接收完成
    RI = 0;               // 清除接收中断标志
    return SBUF;
}

/* 延时函数(约1ms) */
void delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for(i=0; i<ms; i++)
      for(j=0; j<1000; j++);
}

/* 串口中断服务函数 */
void UART_ISR(void) interrupt 4
{
    if(RI)
    {
      RI = 0;         // 清除接收中断标志
      // 在此处理接收数据
      UART_SendByte(SBUF);// 示例:回传接收到的数据
    }
    if(TI)
    {
      TI = 0;         // 清除发送中断标志
    }
}

/* 主函数 */
void main(void)
{
    Clock_Init();         // 时钟初始化
    UART_Init();          // 串口初始化
   
    UART_SendString("STC8H1K08 UART Test Ready\r\n");
   
    while(1)
    {
      // 示例1:定时发送测试数据
       UART_SendString("System Running...\r\n");
      delay_ms(1000);
      
      // 示例2:查询方式接收处理
      if(RI)
      {
            RI = 0;
            UART_SendByte(SBUF);// 回显接收到的字节
      }
    }
}

李唐马 发表于 2025-5-16 08:07:14

haiyang201 发表于 2025-5-15 15:12
使用串口烧录的吗?

串口烧录用的USB Link1d,程序#include <STC8H.H>
#include <intrins.h>

#define FOSC 11059200L      // 系统频率
#define BAUD 9600         // 波特率

/* 系统时钟初始化 */
void Clock_Init(void)
{
    P_SW2 |= 0x80;          // 允许访问XSFR
    CLKDIV = 0x00;         // 时钟不分频
    P_SW2 &= 0x7F;         // 禁止访问XSFR
}

/* 串口初始化 */
void UART_Init(void)
{
    // 设置IO口模式
    P3M0 &= ~0x30;         // P3.0(RxD)和P3.1(TxD)设为准双向口
    P3M1 &= ~0x30;
   
    // 串口配置
    SCON = 0x50;         // 8位数据,可变波特率,允许接收
    AUXR |= 0x40;          // 定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;          // 串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;          // 清除定时器1模式位
    TMOD |= 0x20;          // 设定定时器1为8位自动重装方式
   
    // 波特率设置
    TL1 = TH1 = (256 - (FOSC/4/BAUD));// 计算重装值
   
    // 启动定时器
    ET1 = 0;               // 禁止定时器1中断
    TR1 = 1;            // 启动定时器1
   
    // 中断配置(如果需要接收)
    ES = 1;               // 使能串口中断
    EA = 1;               // 开总中断
}

/* 发送一个字节 */
void UART_SendByte(unsigned char dat)
{
    SBUF = dat;
    while(!TI);         // 等待发送完成
    TI = 0;               // 清除发送中断标志
}

/* 发送字符串 */
void UART_SendString(char *s)
{
    while(*s)             // 检测字符串结束符
    {
      UART_SendByte(*s++); // 发送当前字符
    }
}

/* 接收一个字节(查询方式) */
unsigned char UART_ReceiveByte(void)
{
    while(!RI);         // 等待接收完成
    RI = 0;               // 清除接收中断标志
    return SBUF;
}

/* 延时函数(约1ms) */
void delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for(i=0; i<ms; i++)
      for(j=0; j<1000; j++);
}

/* 串口中断服务函数 */
void UART_ISR(void) interrupt 4
{
    if(RI)
    {
      RI = 0;         // 清除接收中断标志
      // 在此处理接收数据
      UART_SendByte(SBUF);// 示例:回传接收到的数据
    }
    if(TI)
    {
      TI = 0;         // 清除发送中断标志
    }
}

/* 主函数 */
void main(void)
{
    Clock_Init();         // 时钟初始化
    UART_Init();          // 串口初始化
   
    UART_SendString("STC8H1K08 UART Test Ready\r\n");
   
    while(1)
    {
      // 示例1:定时发送测试数据
       UART_SendString("System Running...\r\n");
      delay_ms(1000);
      
      // 示例2:查询方式接收处理
      if(RI)
      {
            RI = 0;
            UART_SendByte(SBUF);// 回显接收到的字节
      }
    }
}

ercircle 发表于 2025-5-16 08:45:46

代码里没看到设置校验位?使用默认设置无校验位测试





haiyang201 发表于 2025-5-16 08:55:50

这里不对吧,怎么不按例程写呢

jwd 发表于 2025-5-16 09:26:33

一般通讯参数不对,用isp下载时不用管参数

李唐马 发表于 2025-5-16 11:16:07

haiyang201 发表于 2025-5-16 08:55
这里不对吧,怎么不按例程写呢

中断是一个字节反馈没没问题,字符串不行,一直乱码
页: [1] 2
查看完整版本: AI8H1K08 无外部晶振,可以烧录程序,但是不能实现串口通信