elec_bird 发表于 6 天前

AiCube生成代码使用printf_usb输出信息有阻塞现象,如何解决?

1.测试设备:STC8H8K64U实验箱V9.6。
2.代码生成:AiCube生成STC8H8K64U芯片代码。时钟24MHz
3.实现功能:使用printf_usb上传信息到串口助手,控制LED4进行状态翻转。
4.测试仪器:手持示波器FNIRSI-2C53T
5.测试代码如下:
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
                P40 = 0;
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
      //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
      // 在此添加主函数中用户主循环代码
                printf_usb("LED4 is Toggle!\r\n");
                P60 = ~P60;
      //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}6.测试步骤如下:
6.1 使用上面测试代码,编译并下载到STC8H8K64U实验箱,连接串口调试助手,但不打开串口,P60端口测试波形如下:


可以看到P60端口的翻转时间约73ms。(即printf_usb阻塞时间73ms)

6.2 使用上面测试代码,编译并下载到STC8H8K64U实验箱,连接串口调试助手,但打开串口,P60端口测试波形如下:


可以看到P60端口的翻转时间约204us。(即printf_usb运行时间204us)


6.3 使用上面测试代码,注释printf_usb(“LED4 is Toggle!\r\n”)代码,编译并下载到STC8H8K64U实验箱,P60端口测试波形如下:


可以看到P60端口的翻转时间约171ns。(正常)

使用printf_usb引起阻塞是什么原因?如何解决阻塞问题。请各位大神指导!{:baoquan:}

ercircle 发表于 5 天前


看下这个帖子,可以加个判断是否打开函数。
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=17406&pid=179406

elec_bird 发表于 5 天前

ercircle 发表于 2025-10-12 00:19
看下这个帖子,可以加个判断是否打开函数。
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findp ...

谢谢!参考帖子修改后测试如下:
1.增加函数声明及isCDCopen()函数。
函数声明如下:
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
extern void usb_write_reg(BYTE addr, BYTE dat);
extern BYTE usb_read_reg(BYTE addr);
u8 isCDCOpen();
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
isCDCopen()函数如下:
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
u8 isCDCOpen()
{
      u8 result = 0;   
      if (DeviceState != DEVSTATE_CONFIGURED){
                        return 0;
      }
      IE2 &= ~0x80;
      usb_write_reg(INDEX, 1);
      if (!(usb_read_reg(INCSR1) & INIPRDY)){
                result = 1;
      }      
      IE2 |= 0x80;
      return result ;
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
2.修改main()函数,增加条件判断后printf_usb输出信息。
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
                P40 = 0;
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
      //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
      // 在此添加主函数中用户主循环代码
                if(isCDCOpen())
                        printf_usb("LED4 is Toggle!\r\n");
                P60 = ~P60;
      //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}
3.测试结果:

3.1 使用上面测试代码,编译并下载到STC8H8K64U实验箱,连接串口调试助手,但不打开串口,P60端口测试波形如下:


可以看到P60端口的翻转时间约3us。(即isCDCopen()函数判断运行时间约3us)
3.2 使用上面测试代码,编译并下载到STC8H8K64U实验箱,连接串口调试助手,打开串口,P60端口测试波形如下:


可以看到P60端口的波形不再是标准方波,输出信号有些紊乱,具体原因还不清楚。


ercircle 发表于 5 天前

elec_bird 发表于 2025-10-12 14:11
谢谢!参考帖子修改后测试如下:
1.增加函数声明及isCDCopen()函数。
函数声明如下:

这是因为“isCDCOpen”其实判断的是“发送忙”,所以上面帖子里提到这个函数伴随发送行为才有效。

当printf发送最后一个字节是,printf函数已跳出,但是usb还在最后一个字节“发送忙”,所以后续几次主循环会跳过“isCDCOpen”快速翻转P60操作方波忽长忽短,

可以观察:

                        if(isCDCOpen())
                                        printf("LED4 is Toggle!\r\n");                        
                        while(!isCDCOpen()); //等待发送彻底结束,仅观察方波用,要是串口没打开就卡在这里了
                        P60 = !P60;

elec_bird 发表于 5 天前

ercircle 发表于 2025-10-12 14:38
这是因为“isCDCOpen”其实判断的是“发送忙”,所以上面帖子里提到这个函数伴随发送行为才有效。

当prin ...
按照上面代码测试,的确是解决了在打开串口助手后输出波形为方波。

尝试测试:将while(!isCDCOpen())语句放到if条件判断中:
if(isCDCOpen())
                {
                        printf_usb("LED4 is Toggle!\r\n");
                        while(!isCDCOpen());
                }                                       
                P60 = ~P60;
测试结果:

1. 串口助手不打开时,代码应该不会进入if语句,能正常输出方波,但实际却无输出(???)。

2.串口助手打开时,输出方波正常。

ercircle 发表于 5 天前

elec_bird 发表于 2025-10-12 15:20
按照上面代码测试,的确是解决了在打开串口助手后输出波形为方波。

尝试测试:将while(!isCDCOpen())语句 ...
哈哈细品:

上电默认空闲状态,第一次会进入if条件(没有发送行为就没有“发送忙”状态),没打开串口时printf有尝试发送行为,一直没发出去所以阻塞在while循环。

页: [1]
查看完整版本: AiCube生成代码使用printf_usb输出信息有阻塞现象,如何解决?