找回密码
 立即注册
查看: 56|回复: 4

8G1K08A串口问题求助

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-07-29 10:27:44

1

主题

19

回帖

251

积分

中级会员

积分
251
发表于 3 天前 | 显示全部楼层 |阅读模式
#include "STC8G.h"
#include "intrins.h"

// 宏定义
#define FOSC        11059200UL  // 晶振频率(11.0592MHz)
#define BAUD        9600        // 波特率
#define WDT_TIMEOUT 0x07        // 看门狗超时时间(0x07对应最长超时,约18ms@11.0592MHz

// 全局变量:5秒计时计数器(定时器0每10ms中断一次,累计500次为5秒)
unsigned int count_5s = 0;
// 待发送的数据
unsigned char sendData[] = {0x3A, 0x16, 0xA0, 0x01, 0x01, 0xB8, 0x00, 0x0D, 0x0A};
#define DATA_LEN    sizeof(sendData)/sizeof(sendData[0])

// 初始化看门狗
void WDT_Init(void) {
    WDT_CONTR = WDT_TIMEOUT;  // 设置超时时间
    WDT_CONTR |= 0x10;        // 启动看门狗
    EA = 1;                   // 允许总中断(看门狗溢出会复位,无需中断使能)
}

// 喂狗函数(定时调用,防止看门狗复位)
void WDT_Feed(void) {
    WDT_CONTR |= 0x08;  // 重新装载看门狗计数器
}

// 初始化定时器0(用于10ms定时中断)
void Timer0_Init(void) {
    TMOD &= 0xF0;  // 清除定时器0配置
    TMOD |= 0x01;  // 定时器0工作在方式1(16位定时)
    // 计算初值(10ms@11.0592MHz,12T模式)
    TH0 = (65536 - (FOSC / 12 / 100)) / 256;  // 100Hz = 10ms
    TL0 = (65536 - (FOSC / 12 / 100)) % 256;
    ET0 = 1;       // 允许定时器0中断
    TR0 = 1;       // 启动定时器0
    EA = 1;        // 允许总中断
}

// 定时器0中断服务函数(每10ms触发一次)
void Timer0_ISR(void) interrupt 1 {
    // 重新装载初值
    TH0 = (65536 - (FOSC / 12 / 100)) / 256;
    TL0 = (65536 - (FOSC / 12 / 100)) % 256;

    count_5s++;        // 每10ms计数+1
    if (count_5s >= 500) {  // 500*10ms = 5000ms = 5秒
        count_5s = 0;       // 重置计数器
    }

    WDT_Feed();  // 每10ms喂一次狗(远小于看门狗超时时间)
}

// 初始化串口
void UART_Init(void) {
    // 配置TXD引脚(P3.1)为推挽输出
    P3M0 = 0x02;  // P3.1推挽输出
    P3M1 = 0x00;

    // 配置波特率(定时器1方式2)
    TMOD &= 0x0F;
    TMOD |= 0x20;  // 定时器1方式2(8位自动重装载)
    TH1 = (unsigned char)(256 - (FOSC / (BAUD * 12 * 16)));
    TL1 = TH1;
    TR1 = 1;       // 启动定时器1

    SCON = 0x50;   // 串口方式1(8位数据)
    ES = 0;        // 关闭串口中断(仅发送)
}

// 串口发送单个字节
void UART_SendByte(unsigned char dat) {
    SBUF = dat;
    while (!TI);  // 等待发送完成
    TI = 0;       // 清除标志位
}

// 发送数据数组
void UART_SendArray(unsigned char *arr, unsigned char len) {
    unsigned char i;
    for (i = 0; i < len; i++) {
        UART_SendByte(arr);
    }
}

void main(void) {
    UART_Init();    // 初始化串口
    Timer0_Init();  // 初始化定时器0(10ms中断)
    WDT_Init();     // 初始化并启动看门狗

    while (1) {
        if (count_5s == 0) {  // 每5秒触发一次发送
            UART_SendArray(sendData, DATA_LEN);
            // 发送完成后等待计数器重新计数,避免重复发送
            while (count_5s == 0);
        }
    }
}
我让串口发送0x3A, 0x16, 0xA0, 0x01, 0x01, 0xB8, 0x00, 0x0D, 0x0A,使用11059200频率下载,接收的字符串不对,当我把下载频率调331776就真确了,请问下是那里出错了

回复

使用道具 举报 送花

3

主题

247

回帖

-795

积分

等待验证会员

积分
-795
发表于 3 天前 | 显示全部楼层
STC8G1K08A串口问题求助回复如下:

尊敬的用户,您好!

感谢您提交关于STC8G1K08A串口通信的问题。根据您提供的代码片段,我们对代码逻辑、配置以及潜在问题进行了分析,并针对可能存在的问题给出以下专业建议。

一、代码结构与配置分析

您在代码中使用了#include "STC8Gh"和#include "intrinsh"头文件,这是STC8系列单片机的标准头文件,用于访问寄存器和内置函数。但需要注意的是,intrinsh.h并非标准头文件,可能是误写或非官方库文件。建议确认是否为intrins.h(用于内联汇编函数),并确保开发环境正确配置。

二、串口初始化问题

您的代码片段中并未完整展示串口初始化部分,仅展示了定时器0和看门狗的配置。因此无法判断串口是否正确配置。以下为标准的STC8G1K08A串口初始化步骤:

1. 设置波特率:通过定时器1或模式2进行串口波特率设置。
2. 配置串口工作方式:选择方式0、方式1、方式2或方式3。
3. 使能串口中断(如需)。
4. 开启串口接收/发送功能。

三、常见串口问题排查建议

1. 波特率不匹配:请检查实际使用的晶振频率是否与代码中定义的FOSC一致。若使用外部晶振,请确保其稳定性和准确度。

2. 串口未正确初始化:请补充完整的串口初始化代码,例如:
  1. c
  2. void UARTInit(void) {
  3.     SCON = 0x50;        // 设置为方式1(8位异步串行通信)
  4.     TMOD |= 0x20;       // 定时器1工作方式2
  5.     TH1 = 0xFD;         // 波特率9600(基于11.0592MHz)
  6.     TL1 = 0xFD;
  7.     TR1 = 1;            // 启动定时器1
  8.     ES = 1;             // 使能串口中断
  9.     EA = 1;             // 允许全局中断
  10. }
复制代码

3. 串口发送逻辑缺失:当前代码中仅有数据数组sendData[],但未看到发送函数实现。请补充串口发送函数,例如:
  1. c
  2. void UARTSendByte(unsigned char data) {
  3.     SBUF = data;
  4.     while (!TI);        // 等待发送完成
  5.     TI = 0;             // 清除发送标志
  6. }
  7. void UARTSendString(unsigned char str, unsigned int len) {
  8.     for (unsigned int i = 0; i < len; i++) {
  9.         UARTSendByte(str[i]);
  10.     }
  11. }
复制代码

4. 看门狗配置问题:您已启用看门狗,但未提供喂狗机制的具体调用位置。建议在主循环中定期调用WDTFeed(),以避免因长时间未喂狗导致复位。

四、其他建议
调试工具:建议使用示波器或逻辑分析仪检测串口TXD引脚信号,确认是否有数据输出。
电源稳定性:确保MCU供电电压稳定,避免因电压波动导致通信异常。
引脚配置:确认串口TXD和RXD引脚是否已正确配置为输出和输入模式。

五、总结

综上所述,您的代码存在以下潜在问题:
串口初始化未完整;
缺乏串口发送函数;
看门狗喂狗机制未明确调用位置;
intrinsh.h可能为误写。

建议您完善串口初始化代码,添加发送函数,并确保看门狗定时喂狗。如仍存在问题,可进一步提供完整代码或硬件连接图以便深入分析。

如需进一步技术支持,欢迎随时联系国芯人工智能团队。

祝您开发顺利!

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:253
  • 最近打卡:2025-07-31 08:55:10
已绑定手机

78

主题

2294

回帖

5226

积分

荣誉版主

无情的代码机器

积分
5226
发表于 3 天前 | 显示全部楼层

开EAXFR:
截图202507291104296714.jpg
小工具计算波特率:
截图202507291101423147.jpg

截图202507291101519422.jpg

不建议在声明时赋初值,最好改在函数内赋值,data的直接被清零了:
截图202507291104391151.jpg
  1. #include "STC8G.h"
  2. #include "intrins.h"
  3. // 宏定义
  4. #define FOSC        11059200UL  // 晶振频率(11.0592MHz)
  5. #define BAUD        9600        // 波特率
  6. #define WDT_TIMEOUT 0x07        // 看门狗超时时间(0x07对应最长超时,约18ms@11.0592MHz)
  7. // 全局变量:5秒计时计数器(定时器0每10ms中断一次,累计500次为5秒)
  8. unsigned int count_5s = 0;
  9. // 待发送的数据
  10. unsigned char xdata sendData[] = {0x3A, 0x16, 0xA0, 0x01, 0x01, 0xB8, 0x00, 0x0D, 0x0A};
  11. #define DATA_LEN    sizeof(sendData)/sizeof(sendData[0])
  12. // 初始化看门狗
  13. void WDT_Init(void) {
  14.     WDT_CONTR = WDT_TIMEOUT;  // 设置超时时间
  15.     WDT_CONTR |= 0x10;        // 启动看门狗
  16.     EA = 1;                   // 允许总中断(看门狗溢出会复位,无需中断使能)
  17. }
  18. // 喂狗函数(定时调用,防止看门狗复位)
  19. void WDT_Feed(void) {
  20.     WDT_CONTR |= 0x08;  // 重新装载看门狗计数器
  21. }
  22. // 初始化定时器0(用于10ms定时中断)
  23. void Timer0_Init(void) {
  24.     TMOD &= 0xF0;  // 清除定时器0配置
  25.     TMOD |= 0x01;  // 定时器0工作在方式1(16位定时)
  26.     // 计算初值(10ms@11.0592MHz,12T模式)
  27.     TH0 = (65536 - (FOSC / 12 / 100)) / 256;  // 100Hz = 10ms
  28.     TL0 = (65536 - (FOSC / 12 / 100)) % 256;
  29.     ET0 = 1;       // 允许定时器0中断
  30.     TR0 = 1;       // 启动定时器0
  31.     EA = 1;        // 允许总中断
  32. }
  33. // 定时器0中断服务函数(每10ms触发一次)
  34. void Timer0_ISR(void) interrupt 1 {
  35.     // 重新装载初值
  36.     TH0 = (65536 - (FOSC / 12 / 100)) / 256;
  37.     TL0 = (65536 - (FOSC / 12 / 100)) % 256;
  38.     count_5s++;        // 每10ms计数+1
  39.     if (count_5s >= 500) {  // 500*10ms = 5000ms = 5秒
  40.         count_5s = 0;       // 重置计数器
  41.     }
  42.     WDT_Feed();  // 每10ms喂一次狗(远小于看门狗超时时间)
  43. }
  44. // 初始化串口
  45. void UART_Init(void) {
  46.     // 配置TXD引脚(P3.1)为推挽输出
  47.     P3M0 = 0x02;  // P3.1推挽输出
  48.     P3M1 = 0x00;
  49.     // 配置波特率(定时器1方式2)
  50. //    TMOD &= 0x0F;
  51. //    TMOD |= 0x20;  // 定时器1方式2(8位自动重装载)
  52. //    TH1 = (unsigned char)(256 - (FOSC / (BAUD * 12 * 16)));
  53. //    TL1 = TH1;
  54. //    TR1 = 1;       // 启动定时器1
  55. //    SCON = 0x50;   // 串口方式1(8位数据)
  56. //    ES = 0;        // 关闭串口中断(仅发送)
  57.         
  58.                 PCON &= 0x7F;                //波特率不倍速
  59.         SCON = 0x50;                //8位数据,可变波特率
  60.         AUXR |= 0x40;                //定时器时钟1T模式
  61.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  62.         TMOD &= 0x0F;                //设置定时器模式
  63.         TMOD |= 0x20;                //设置定时器模式
  64.         TL1 = 0xDC;                        //设置定时初始值
  65.         TH1 = 0xDC;                        //设置定时重载值
  66.         ET1 = 0;                        //禁止定时器中断
  67.         TR1 = 1;                        //定时器1开始计时
  68.         
  69. //        SCON = 0x50;                //8位数据,可变波特率
  70. //        AUXR |= 0x40;                //定时器时钟1T模式
  71. //        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  72. //        TMOD &= 0x0F;                //设置定时器模式
  73. //        TL1 = 0xE0;                        //设置定时初始值
  74. //        TH1 = 0xFE;                        //设置定时初始值
  75. //        ET1 = 0;                        //禁止定时器中断
  76. //        TR1 = 1;                        //定时器1开始计时
  77. }
  78. // 串口发送单个字节
  79. void UART_SendByte(unsigned char dat) {
  80.     SBUF = dat;
  81.     while (!TI);  // 等待发送完成
  82.     TI = 0;       // 清除标志位
  83. }
  84. // 发送数据数组
  85. void UART_SendArray(unsigned char *arr, unsigned char len) {
  86.     unsigned char i;
  87.     for (i = 0; i < len; i++) {
  88.         UART_SendByte(arr[i]);
  89.     }
  90. }
  91. void main(void) {
  92.                         P_SW2=0x80;
  93.                 P0M0 = 0x00; P0M1 = 0x00;
  94.                 P1M0 = 0x00; P1M1 = 0x00;
  95.                 P2M0 = 0x00; P2M1 = 0x00;
  96.                 P3M0 = 0x00; P3M1 = 0x00;
  97.                 P4M0 = 0x00; P4M1 = 0x00;
  98.                 P5M0 = 0x00; P5M1 = 0x00;
  99.                 P6M0 = 0x00; P6M1 = 0x00;
  100.                 P7M0 = 0x00; P7M1 = 0x00;
  101.         
  102.     UART_Init();    // 初始化串口
  103.     Timer0_Init();  // 初始化定时器0(10ms中断)
  104.     WDT_Init();     // 初始化并启动看门狗
  105.     while (1) {
  106.         if (count_5s == 0) {  // 每5秒触发一次发送
  107.             UART_SendArray(sendData, DATA_LEN);
  108.             // 发送完成后等待计数器重新计数,避免重复发送
  109.             while (count_5s == 0);
  110.         }
  111.     }
  112. }
复制代码




三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:450
  • 最近打卡:2025-07-31 12:37:07

8

主题

384

回帖

2724

积分

金牌会员

积分
2724
发表于 3 天前 | 显示全部楼层
  TH1 = (unsigned char)(256 - (FOSC / (BAUD * 12 * 16)));

这里计算 (BAUD * 12 * 16), BAUD是int型
9600*12*16=1843200溢出了吧?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:44
  • 最近打卡:2025-07-29 10:27:44

1

主题

19

回帖

251

积分

中级会员

积分
251
发表于 3 天前 来自手机 | 显示全部楼层
ercircle 发表于 2025-7-28 15:02
开EAXFR:

小工具计算波特率:

晚上我试试
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-8-1 01:56 , Processed in 0.146080 second(s), 70 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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