找回密码
 立即注册
查看: 58|回复: 1

VSCode SDCC 使用printf打印输出死机

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:1
  • 最近打卡:2025-11-20 10:14:29
已绑定手机

1

主题

0

回帖

25

积分

新手上路

积分
25
发表于 2025-11-20 10:14:29 | 显示全部楼层 |阅读模式
一、实现的功能:1、串口1自动收发;2、ADC采集后使用printf出处ADC的值

二、文件说明:
1、stc8hxxxx.h为使用ISP生成的SDCC格式头文件
2、使用的STC8H的函数库,用uint8_t替换STC8G_H_Delay、STC8G_H_Timer、STC8G_H_ADC、STC8G_H_UART的.c/.h中的u8
例如:
void TX1_write2buff(u8 dat)        //串口1发送函数
修改为:
void TX1_write2buff(uint8_t dat)        //串口1发送函数
3、xxx.h 头文件包含
#include "stdint.h"
#include "stdio.h"
4、重构STC8G_H_UART.c中的putchar
int putchar(int c)
{
    TX1_write2buff(c);
    return c;
}

修改为
int putchar(int c)
{
    TX1_write2buff(c);
    return c;
}
5、main.c

  1. #include    "config.h"
  2. #include    "stdint.h"
  3. #include    "stdio.h"
  4. #include    "string.h"
  5. #include    "STC8G_H_GPIO.h"
  6. #include    "STC8G_H_UART.h"
  7. #include    "STC8G_H_Delay.h"
  8. #include    "STC8G_H_NVIC.h"
  9. #include    "STC8G_H_Switch.h"
  10. #include    "STC8G_H_Timer.h"
  11. #include    "STC8G_H_ADC.h"
  12. /*************  本地变量声明    **************/
  13. char __xdata AdBuffer[7];
  14. /**********************************************************************************************/
  15. /*************  本地函数声明  *****************************************************************/
  16. void    GPIO_config(void)
  17. {
  18.     GPIO_InitTypeDef        GPIO_InitStructure;                //结构定义
  19.     GPIO_InitStructure.Pin  = GPIO_Pin_0 | GPIO_Pin_1;      //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
  20.     GPIO_InitStructure.Mode = GPIO_PullUp;                  //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
  21.     GPIO_Inilize(GPIO_P3, &GPIO_InitStructure);             //初始化
  22. }
  23. /***************  串口初始化函数 *****************/
  24. void    UART_config(void)
  25. {
  26.     COMx_InitDefine     COMx_InitStructure;                 //结构定义
  27.     COMx_InitStructure.UART_Mode      = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
  28.     COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;         //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
  29.     COMx_InitStructure.UART_BaudRate  = 115200ul;           //波特率, 一般 110 ~ 115200
  30.     COMx_InitStructure.UART_RxEnable  = ENABLE;             //接收允许,   ENABLE或DISABLE
  31.     COMx_InitStructure.BaudRateDouble = DISABLE;            //波特率加倍, ENABLE或DISABLE
  32.     UART_Configuration(UART1, &COMx_InitStructure);     //初始化串口1 UART1,UART2,UART3,UART4
  33.     NVIC_UART1_Init(ENABLE,Priority_2);     //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
  34.     UART1_SW(UART1_SW_P30_P31);     //UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
  35. }
  36. /************************ 定时器配置 ****************************/
  37. void    Timer_config(void)
  38. {
  39.     TIM_InitTypeDef     TIM_InitStructure;                      //结构定义
  40.     //定时器2做16位自动重装, 中断频率为1000HZ,中断函数从P6.5取反输出500HZ方波信号.
  41.     TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;         //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
  42.     TIM_InitStructure.TIM_ClkOut    = DISABLE;              //是否输出高速脉冲, ENABLE或DISABLE
  43.     TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000);             //初值,1000-1ms 1-1s
  44.     TIM_InitStructure.TIM_PS        = 0;                    //8位预分频器(n+1), 0~255, (注意:并非所有系列都有此寄存器,详情请查看数据手册)
  45.     TIM_InitStructure.TIM_Run       = ENABLE;               //是否初始化后启动定时器, ENABLE或DISABLE
  46.     Timer_Inilize(Timer0,&TIM_InitStructure);               //初始化Timer0    Timer0,Timer1,Timer2,Timer3,Timer4
  47.     NVIC_Timer0_Init(ENABLE,SDCC_NULL);                     //中断使能, ENABLE/DISABLE; 无优先级
  48. }
  49. /******************** ADC 配置 ********************/
  50. void    ADC_config(void)
  51. {
  52.     ADC_InitTypeDef     ADC_InitStructure;      //结构定义
  53.     ADC_InitStructure.ADC_SMPduty   = 31;                   //ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
  54.     ADC_InitStructure.ADC_CsSetup   = 0;                    //ADC 通道选择时间控制 0(默认),1
  55.     ADC_InitStructure.ADC_CsHold    = 1;                    //ADC 通道选择保持时间控制 0,1(默认),2,3
  56.     ADC_InitStructure.ADC_Speed     = ADC_SPEED_2X16T;      //设置 ADC 工作时钟频率 ADC_SPEED_2X1T~ADC_SPEED_2X16T
  57.     ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;  //ADC结果调整,  ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
  58.     ADC_Inilize(&ADC_InitStructure);                        //初始化
  59.     ADC_PowerControl(ENABLE);                               //ADC电源开关, ENABLE或DISABLE
  60.     NVIC_ADC_Init(DISABLE,Priority_0);                      //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
  61. }
  62. /*************  函数声明  *****************************************************************/
  63. void com1_rx_timeout_proc(void);    // 串口接收超时判断
  64. /**********************************************************************************************/
  65. /*************  中断响应函数需要在main.c重声明  ***********************************************/
  66. void UART1_ISR_Handler(void) __interrupt(UART1_VECTOR);
  67. void Timer0_ISR_Handler(void) __interrupt(TMR0_VECTOR); // 进中断时已经清除标志
  68. void ADC_ISR_Handler (void) __interrupt(ADC_VECTOR);
  69. /**********************************************************************************************/
  70. //========================================================================
  71. // 函数: void main(void)
  72. // 描述: 主程序。
  73. // 参数: none.
  74. // 返回: none.
  75. // 版本: VER1.0
  76. // 日期: 2025-10-29
  77. // 备注:
  78. //========================================================================
  79. void main(void)
  80. {
  81.     uint8_t i = 0;
  82.     g_sys_runtime = 0;
  83.     /* 扩展寄存器访问使能 */
  84.     EAXSFR();
  85.     // 系统配置初始化
  86.     GPIO_config();
  87.     UART_config();
  88.     Timer_config();
  89.     ADC_config();
  90.     // 开总中断
  91.     EA = 1;
  92.     PrintString1("Hello STC8H8K64U!\r\n");  //UART1发送一个字符串
  93.     while(1)
  94.     {
  95.                 delay_ms(1);                if(COM1.RX_TimeOut > 0)                //超时计数                {                        if(--COM1.RX_TimeOut == 0)                        {                                if(COM1.RX_Cnt > 0)                                {                                        for(i=0; i<COM1.RX_Cnt; i++)        TX1_write2buff(RX1_Buffer);        //收到的数据原样返回                                }                                COM1.RX_Cnt = 0;                        }                }
  96.         g_ch3_data.pv_value = Get_ADCResult(3);        
  97.         g_ch4_data.pv_value = Get_ADCResult(4);
  98.         printf("ADC ch3 pv:%d\r\n", g_ch3_data.pv_value);
  99.         printf("ADC ch3 pv:%d\r\n", g_ch3_data.pv_value);
  100.         }                       
  101.     }      
  102. }
复制代码


四、遇到的问题
1、关闭串口自动收发,单独使用printf格式化输出程序可以正常运行
        printf("ADC ch3 pv:%d\r\n", g_ch3_data.pv_value);        printf("ADC ch3 pv:%d\r\n", g_ch3_data.pv_value);
2、注释掉printf输出,电脑和串口1定时收发,运行正常
        //printf("ADC ch3 pv:%d\r\n", g_ch3_data.pv_value);
        //printf("ADC ch3 pv:%d\r\n", g_ch3_data.pv_value);

2、电脑和串口1定时定时收发,同时使用printf格式化输出,程序运行一段时间就会死机。
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:586
  • 最近打卡:2025-12-18 09:02:22
已绑定手机

49

主题

2369

回帖

8422

积分

论坛元老

积分
8422
发表于 2025-11-20 19:18:16 | 显示全部楼层
这个问题重点应该在 “TX1_write2buff” 函数的写法。
如果开启了串口中断,并且在中断里面有清除 TI 标志的话,要像下面这样写法,在发送完成中断里面清除 B_TX1_Busy 标志:
  1.     B_TX1_Busy = 1;
  2.     SBUF = dat;
  3.     while(B_TX1_Busy);
复制代码


如果没有开启串口中断,则可以像下面那样直接查询/清除 TI 标志:
  1.     SBUF = dat;
  2.     while(TI == 0);
  3.     TI = 0;
复制代码
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-12-18 18:59 , Processed in 0.111519 second(s), 49 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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