找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 352|回复: 7
打印 上一主题 下一主题
收起左侧

关于STC8H4K64TL/STC8G1K08A单片机的串口问题

[复制链接]
跳转到指定楼层
楼主
我使用STC官方(VSCode中EDIE插件下载的,有点区别)的串口写入函数TX1_write2buff,但是烧录到 STC8H4K64TL / STC8G1K08A 单片机,运行到TX1_write2buff后并没有输出(阻塞的方式是有输出的),球大佬。
改了一下帖子,代码精简了一点。

这是我的主函数


#include "GPIO.h"
#include "UART.h"
#include "config.h"
#include "delay.h"/
#include <compiler.h>

// 串口波特率设置
#define BAUD 115200 // 波特率

void UART_Init()
{
    /* ===========================
     * UART1 参数配置
     * =========================== */
    COMx_InitDefine uart;

    uart.UART_Mode = UART_8bit_BRTx; // 8 位 UART,波特率发生器
    uart.UART_BRT_Use = BRT_Timer1;  // 使用 Timer1
    uart.UART_BaudRate = BAUD;
    uart.Morecommunicate = DISABLE;    // 不启用多机通信
    uart.UART_RxEnable = ENABLE;       // 允许接收
    uart.BaudRateDouble = DISABLE;     // 不倍速,稳定优先
    uart.UART_Interrupt = ENABLE;      // 开 UART1 中断
    uart.UART_Priority = Priority_0;   // ★最低优先级★
    uart.UART_P_SW = UART1_SW_P30_P31; // P3.0 RX, P3.1 TX

    /* ===========================
     * 初始化 UART1
     * =========================== */
    int ret_code = UART_Configuration(UART1, &uart);

    /* ===========================
     * 初始化软件状态(很关键)
     * 防止上电或重入时脏数据
     * =========================== */
    ES = 0; // 关闭中断

    COM1.TX_read = 0;
    COM1.TX_write = 0;
    COM1.B_TX_busy = 0;

    COM1.RX_Cnt = 0;
    COM1.RX_TimeOut = 0;
    COM1.B_RX_OK = 0;

    ES = 1; // 开启中断
}

// 发送一个字节
void UART_SendByte(unsigned char c)
{
    SBUF = c;
    while (!TI)
        ; // 等待发送完成
    TI = 0;
    // TX1_write2buff(c); // 这里取消注释后,没有双倍的输出!!!!!!!!!!!!!!!
}

// 接收一个字节
unsigned char UART_ReceiveByte()
{
    while (!RI)
        ; // 等待接收完成
    RI = 0;
    return SBUF;
}

void main()
{
    unsigned char c;
    UART_Init();

    // ES = 1;
    EA = 1;

    while (1)
    {
        c = UART_ReceiveByte(); // 接收数据
        UART_SendByte(c);       // 原封不动发送回去
    }
}


"""

这是我使用的UART.c(部分)
"""
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/

#include "UART.h"


#ifdef UART1
COMx_Define COM1;
u8  __xdata TX1_Buffer[COM_TX1_Lenth];  //发送缓冲
u8  __xdata RX1_Buffer[COM_RX1_Lenth];  //接收缓冲
#endif
#ifdef UART2
COMx_Define COM2;
u8  __xdata TX2_Buffer[COM_TX2_Lenth];  //发送缓冲
u8  __xdata RX2_Buffer[COM_RX2_Lenth];  //接收缓冲
#endif
#ifdef UART3
COMx_Define COM3;
u8  __xdata TX3_Buffer[COM_TX3_Lenth];  //发送缓冲
u8  __xdata RX3_Buffer[COM_RX3_Lenth];  //接收缓冲
#endif
#ifdef UART4
COMx_Define COM4;
u8  __xdata TX4_Buffer[COM_TX4_Lenth];  //发送缓冲
u8  __xdata RX4_Buffer[COM_RX4_Lenth];  //接收缓冲
#endif

u8 UART_Configuration(u8 UARTx, COMx_InitDefine *COMx)
{
    u8  i;
    u32 j;

#ifdef UART1
    if(UARTx == UART1)
    {
        COM1.id = 1;
        COM1.TX_read    = 0;
        COM1.TX_write   = 0;
        COM1.B_TX_busy  = 0;
        COM1.RX_Cnt     = 0;
        COM1.RX_TimeOut = 0;
        COM1.B_RX_OK    = 0;
        for(i=0; i<COM_TX1_Lenth; i++)  TX1_Buffer[ i] = 0;
        for(i=0; i<COM_RX1_Lenth; i++)  RX1_Buffer[ i] = 0;

        if(COMx->UART_Priority > Priority_3)    return 2;   //错误
        UART1_Priority(COMx->UART_Priority);    //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
        if(COMx->UART_Mode > UART_9bit_BRTx)    return 2;   //模式错误
        SCON = (SCON & 0x3f) | COMx->UART_Mode;
        if((COMx->UART_Mode == UART_9bit_BRTx) || (COMx->UART_Mode == UART_8bit_BRTx))  //可变波特率
        {
            j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;  //按1T计算
            if(j >= 65536UL)    return 2;   //错误
            j = 65536UL - j;
            if(COMx->UART_BRT_Use == BRT_Timer1)
            {
                TR1 = 0;
                AUXR &= ~0x01;      //S1 BRT Use Timer1;
                TMOD &= ~(1<<6);    //Timer1 set As Timer
                TMOD &= ~0x30;      //Timer1_16bitAutoReload;
                AUXR |=  (1<<6);    //Timer1 set as 1T mode
                TH1 = (u8)(j>>8);
                TL1 = (u8)j;
                ET1 = 0;    //禁止中断
                TMOD &= ~0x40;  //定时
                INT_CLKO &= ~0x02;  //不输出时钟
                TR1  = 1;
            }
            else if(COMx->UART_BRT_Use == BRT_Timer2)
            {
                AUXR &= ~(1<<4);    //Timer stop
                AUXR |= 0x01;       //S1 BRT Use Timer2;
                AUXR &= ~(1<<3);    //Timer2 set As Timer
                AUXR |=  (1<<2);    //Timer2 set as 1T mode
                TH2 = (u8)(j>>8);
                TL2 = (u8)j;
                IE2  &= ~(1<<2);    //禁止中断
                AUXR |=  (1<<4);    //Timer run enable
            }
            else return 2;  //错误
        }
        else if(COMx->UART_Mode == UART_ShiftRight)
        {
            if(COMx->BaudRateDouble == ENABLE)  AUXR |=  (1<<5);    //固定波特率SysClk/2
            else                                AUXR &= ~(1<<5);    //固定波特率SysClk/12
        }
        else if(COMx->UART_Mode == UART_9bit)   //固定波特率SysClk*2^SMOD/64
        {
            if(COMx->BaudRateDouble == ENABLE)  PCON |=  (1<<7);    //固定波特率SysClk/32
            else                                PCON &= ~(1<<7);    //固定波特率SysClk/64
        }
        if(COMx->UART_Interrupt == ENABLE)  ES = 1; //允许中断
        else                                ES = 0; //禁止中断
        if(COMx->UART_RxEnable == ENABLE)   REN = 1;    //允许接收
        else                                REN = 0;    //禁止接收
        P_SW1 = (P_SW1 & 0x3f) | (COMx->UART_P_SW & 0xc0);  //切换IO
        return  0;
    }
#endif
#ifdef UART2
    // 没用到就删了
#endif
#ifdef UART3
    // 没用到就删了
#endif
#ifdef UART4
    // 没用到就删了
#endif
    return  2;  //错误
}

/*********************************************************/

/********************* UART1 函数 ************************/
#ifdef UART1
void TX1_write2buff(u8 dat) //写入发送缓冲,指针+1
{
    TX1_Buffer[COM1.TX_write] = dat;    //装发送缓冲
    if(++COM1.TX_write >= COM_TX1_Lenth)    COM1.TX_write = 0;

    if(COM1.B_TX_busy == 0)     //空闲
    {  
        COM1.B_TX_busy = 1;     //标志忙
        TI = 1;                 //触发发送中断
    }
}

void PrintString1(u8 *puts)
{
    for (; *puts != 0;  puts++)  TX1_write2buff(*puts);     //遇到停止符0结束
}

void UART1_int (void) __interrupt(UART1_VECTOR)
{
    if(RI)
    {
        RI = 0;
        if(COM1.B_RX_OK == 0)
        {
            if(COM1.RX_Cnt >= COM_RX1_Lenth)    COM1.RX_Cnt = 0;
            RX1_Buffer[COM1.RX_Cnt++] = SBUF;
            COM1.RX_TimeOut = TimeOutSet1;
        }
    }

    if(TI)
    {
        TI = 0;
        if(COM1.TX_read != COM1.TX_write)
        {
            SBUF = TX1_Buffer[COM1.TX_read];
            if(++COM1.TX_read >= COM_TX1_Lenth)     COM1.TX_read = 0;
        }
        else    COM1.B_TX_busy = 0;
    }
}
#endif

/********************* UART2 函数 ************************/
// 没用到就删了


"""

这是我使用的UART.h
"""
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/

#ifndef __UART_H
#define __UART_H     

#include    "config.h"

#define UART1   1
//#define   UART2   2
//#define   UART3   3
//#define   UART4   4

#ifdef UART1
#define COM_TX1_Lenth   128
#define COM_RX1_Lenth   128
#endif
#ifdef UART2
#define COM_TX2_Lenth   128
#define COM_RX2_Lenth   128
#endif
#ifdef UART3
#define COM_TX3_Lenth   128
#define COM_RX3_Lenth   128
#endif
#ifdef UART4
#define COM_TX4_Lenth   128
#define COM_RX4_Lenth   128
#endif

#define UART_ShiftRight 0       //同步移位输出
#define UART_8bit_BRTx  (1<<6)  //8位数据,可变波特率
#define UART_9bit       (2<<6)  //9位数据,固定波特率
#define UART_9bit_BRTx  (3<<6)  //9位数据,可变波特率

#define UART1_SW_P30_P31    0
#define UART1_SW_P36_P37    (1<<6)
#define UART1_SW_P16_P17    (2<<6)
#define UART1_SW_P43_P44    (3<<6)
#define UART2_SW_P10_P11    0
#define UART2_SW_P46_P47    1
#define UART3_SW_P00_P01    0
#define UART3_SW_P50_P51    2
#define UART4_SW_P02_P03    0
#define UART4_SW_P52_P53    4


#define TimeOutSet1     5
#define TimeOutSet2     5
#define TimeOutSet3     5
#define TimeOutSet4     5

#define BRT_Timer1  1
#define BRT_Timer2  2
#define BRT_Timer3  3
#define BRT_Timer4  4

typedef struct
{
    u8  id;             //串口号

    u8  TX_read;        //发送读指针
    u8  TX_write;       //发送写指针
    u8  B_TX_busy;      //忙标志

    u8  RX_Cnt;         //接收字节计数
    u8  RX_TimeOut;     //接收超时
    u8  B_RX_OK;        //接收块完成
} COMx_Define;

typedef struct
{
    u8  UART_Mode;          //模式,         UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
    u8  UART_BRT_Use;       //使用波特率,   BRT_Timer1,BRT_Timer2
    u32 UART_BaudRate;      //波特率,       ENABLE,DISABLE
    u8  Morecommunicate;    //多机通讯允许, ENABLE,DISABLE
    u8  UART_RxEnable;      //允许接收,   ENABLE,DISABLE
    u8  BaudRateDouble;     //波特率加倍, ENABLE,DISABLE
    u8  UART_Interrupt;     //中断控制,   ENABLE,DISABLE
    u8  UART_Priority;      //优先级,     Priority_0,Priority_1,Priority_2,Priority_3
    u8  UART_P_SW;          //切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
} COMx_InitDefine;

#ifdef UART1
extern  COMx_Define COM1;
extern  u8  __xdata TX1_Buffer[COM_TX1_Lenth];  //发送缓冲
extern  u8  __xdata RX1_Buffer[COM_RX1_Lenth];  //接收缓冲
#endif
#ifdef UART2
extern  COMx_Define COM2;
extern  u8  __xdata TX2_Buffer[COM_TX2_Lenth];  //发送缓冲
extern  u8  __xdata RX2_Buffer[COM_RX2_Lenth];  //接收缓冲
#endif
#ifdef UART3
extern  COMx_Define COM3;
extern  u8  __xdata TX3_Buffer[COM_TX3_Lenth];  //发送缓冲
extern  u8  __xdata RX3_Buffer[COM_RX3_Lenth];  //接收缓冲
#endif
#ifdef UART4
extern  COMx_Define COM4;
extern  u8  __xdata TX4_Buffer[COM_TX4_Lenth];  //发送缓冲
extern  u8  __xdata RX4_Buffer[COM_RX4_Lenth];  //接收缓冲
#endif

u8  UART_Configuration(u8 UARTx, COMx_InitDefine *COMx);
#ifdef UART1
void TX1_write2buff(u8 dat);    //写入发送缓冲,指针+1
void PrintString1(u8 *puts);
#endif
#ifdef UART2
void TX2_write2buff(u8 dat);    //写入发送缓冲,指针+1
void PrintString2(u8 *puts);
#endif
#ifdef UART3
void TX3_write2buff(u8 dat);    //写入发送缓冲,指针+1
void PrintString3(u8 *puts);
#endif
#ifdef UART4
void TX4_write2buff(u8 dat);    //写入发送缓冲,指针+1
void PrintString4(u8 *puts);
#endif

//void COMx_write2buff(COMx_Define *COMx, u8 dat);  //写入发送缓冲,指针+1
//void PrintString(COMx_Define *COMx, u8 *puts);

#endif
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1167358 发表于 2026-2-9 08:24 | 只看该作者
试了一下阻塞发送就没问题。阻塞和非阻塞接收都没问题。
回复

使用道具 举报

板凳
ID:959346 发表于 2026-2-9 11:12 | 只看该作者
对这颗芯片不熟,看情况是不是一直进中断了?看看中断触发方式对不,中断内是否没有清除好中断标志?
回复

使用道具 举报

地板
ID:1167358 发表于 2026-2-9 12:06 | 只看该作者
中断内部清除标志了
  1. void UART1_int (void) __interrupt(UART1_VECTOR)
  2. {
  3.         if(RI)
  4.         {
  5.                 RI = 0;
  6.                 if(COM1.B_RX_OK == 0)
  7.                 {
  8.                         if(COM1.RX_Cnt >= COM_RX1_Lenth)        COM1.RX_Cnt = 0;
  9.                         RX1_Buffer[COM1.RX_Cnt++] = SBUF;
  10.                         COM1.RX_TimeOut = TimeOutSet1;
  11.                 }
  12.         }

  13.         if(TI)
  14.         {
  15.                 TI = 0;
  16.                 if(COM1.TX_read != COM1.TX_write)
  17.                 {
  18.                          SBUF = TX1_Buffer[COM1.TX_read];
  19.                         if(++COM1.TX_read >= COM_TX1_Lenth)                COM1.TX_read = 0;
  20.                 }
  21.                 else        COM1.B_TX_busy = 0;
  22.         }
  23. }
复制代码
回复

使用道具 举报

5#
ID:1133081 发表于 2026-2-9 16:58 | 只看该作者
STC官方示例就几十条代码,你洋洋洒洒几百条代码,把简单问题复杂化。出了问题不好找。
回复

使用道具 举报

6#
ID:1167358 发表于 2026-2-9 17:39 | 只看该作者
我那几百行有stc官方库啊。

我在stc8g1k08a上实验也不行:

  1. #include "GPIO.h"
  2. #include "UART.h"
  3. #include "config.h"
  4. #include "delay.h"
  5. #include <compiler.h>

  6. // 串口波特率设置
  7. #define BAUD 115200 // 波特率

  8. void UART_Init()
  9. {
  10.     /* ===========================
  11.      * UART1 参数配置
  12.      * =========================== */
  13.     COMx_InitDefine uart;

  14.     uart.UART_Mode = UART_8bit_BRTx; // 8 位 UART,波特率发生器
  15.     uart.UART_BRT_Use = BRT_Timer1;  // 使用 Timer1
  16.     uart.UART_BaudRate = BAUD;
  17.     uart.Morecommunicate = DISABLE;    // 不启用多机通信
  18.     uart.UART_RxEnable = ENABLE;       // 允许接收
  19.     uart.BaudRateDouble = DISABLE;     // 不倍速,稳定优先
  20.     uart.UART_Interrupt = ENABLE;      // 开 UART1 中断
  21.     uart.UART_Priority = Priority_0;   // ★最低优先级★
  22.     uart.UART_P_SW = UART1_SW_P30_P31; // P3.0 RX, P3.1 TX

  23.     /* ===========================
  24.      * 初始化 UART1
  25.      * =========================== */
  26.     int ret_code = UART_Configuration(UART1, &uart);

  27.     /* ===========================
  28.      * 初始化软件状态(很关键)
  29.      * 防止上电或重入时脏数据
  30.      * =========================== */
  31.     ES = 0; // 关闭中断

  32.     COM1.TX_read = 0;
  33.     COM1.TX_write = 0;
  34.     COM1.B_TX_busy = 0;

  35.     COM1.RX_Cnt = 0;
  36.     COM1.RX_TimeOut = 0;
  37.     COM1.B_RX_OK = 0;

  38.     ES = 1; // 开启中断
  39. }

  40. // 发送一个字节
  41. void UART_SendByte(unsigned char c)
  42. {
  43.     SBUF = c;
  44.     while (!TI)
  45.         ; // 等待发送完成
  46.     TI = 0;
  47.     // TX1_write2buff(c);
  48. }

  49. // 接收一个字节
  50. unsigned char UART_ReceiveByte()
  51. {
  52.     while (!RI)
  53.         ; // 等待接收完成
  54.     RI = 0;
  55.     return SBUF;
  56. }

  57. void main()
  58. {
  59.     unsigned char c;
  60.     UART_Init();

  61.     // ES = 1;
  62.     EA = 1;

  63.     while (1)
  64.     {
  65.         c = UART_ReceiveByte(); // 接收数据
  66.         UART_SendByte(c);       // 原封不动发送回去
  67.     }
  68. }
复制代码
回复

使用道具 举报

7#
ID:1167358 发表于 2026-2-10 14:13 | 只看该作者
已经解决了!
结论是SDCC有点坑人,中断函数不声明在头文件(UART.h)就直接优化了,导致中断函数没有定义!
回复

使用道具 举报

8#
ID:1133081 发表于 2026-2-10 14:53 | 只看该作者
fly-cloud 发表于 2026-2-9 17:39
我那几百行有stc官方库啊。

我在stc8g1k08a上实验也不行:

这是用STC官方示例在STC8G1K08上测试的结果


  1. #include "stc8g.h"
  2. #include "intrins.h"

  3. #define FOSC        11059200UL
  4. #define BRT         (256 - FOSC / 115200 / 32)


  5. bit busy;
  6. char wptr;
  7. char rptr;
  8. char buffer[16];

  9. void UartIsr() interrupt 4
  10. {
  11.     if (TI)
  12.     {
  13.         TI = 0;
  14.         busy = 0;
  15.     }
  16.     if (RI)
  17.     {
  18.         RI = 0;
  19.         buffer[wptr++] = SBUF;
  20.         wptr &= 0x0f;
  21.     }
  22. }

  23. void UartInit()
  24. {
  25.     SCON = 0x50;
  26.     TMOD = 0x20;
  27.     TL1 = BRT;
  28.     TH1 = BRT;
  29.     TR1 = 1;
  30.     AUXR = 0x40;
  31.     wptr = 0x00;
  32.     rptr = 0x00;
  33.     busy = 0;
  34. }

  35. void UartSend(char dat)
  36. {
  37.     while (busy);
  38.     busy = 1;
  39.     SBUF = dat;
  40. }

  41. void UartSendStr(char *p)
  42. {
  43.     while (*p)
  44.     {
  45.         UartSend(*p++);
  46.     }
  47. }

  48. void main()
  49. {
  50.     P0M0 = 0x00;
  51.     P0M1 = 0x00;
  52.     P1M0 = 0x00;
  53.     P1M1 = 0x00;
  54.     P2M0 = 0x00;
  55.     P2M1 = 0x00;
  56.     P3M0 = 0x00;
  57.     P3M1 = 0x00;
  58.     P4M0 = 0x00;
  59.     P4M1 = 0x00;
  60.     P5M0 = 0x00;
  61.     P5M1 = 0x00;

  62.     UartInit();
  63.     ES = 1;
  64.     EA = 1;
  65.     UartSendStr("Uart Test !\r\n");

  66.     while (1)
  67.     {
  68.         if (rptr != wptr)
  69.         {
  70.             UartSend(buffer[rptr++]);
  71.             rptr &= 0x0f;
  72.         }
  73.     }
  74. }

复制代码



回复

使用道具 举报

9#
ID:1167358 发表于 2026-2-10 16:46 | 只看该作者
WL0123 发表于 2026-2-10 14:53
这是用STC官方示例在STC8G1K08上测试的结果

已经解决了!
结论是SDCC有点坑人,中断函数不声明在头文件(UART.h)就直接优化了,导致中断函数没有定义!
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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