CH579/CH573/CH583/CH57x/CH58x printf 串口打印相關


本文目的

本文將記錄如何在沁恆的ble芯片上修改printf的串口重定向,禁用,以及相關的注意事項

適用芯片

  • CH579/ch578/ch577
  • CH573/CH571
  • CH583/CH582/CH581
  • CH592/CH591

printf 中特性

  • 默認沖過UART1出輸出,即PA9,波特率115200
  • 半阻塞模式(沒有軟件緩沖實現,只有芯片UART帶的8字節硬件fifo),切記不要濫用,要考慮打印占用的時間
  • SDK中使用PRINT 宏來實現

一,SDK中 printf重定向實現原理

在KEIL中

串口輸出

keil 中主要是是需要實現fputc函數進行串口輸出,下面是CH579 SDK中的定義:
image

修改串口

初始化串口

#ifdef DEBUG
  GPIOA_SetBits(bTXD1);
  GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
  UART1_DefInit( );
#endif

修改宏:
image

在mounriver studio中

宏定義

官網的默認例程中,printf 通過PRINT宏來定義:
在CH573SFR.h文件中

#ifdef  DEBUG
#define PRINT(X...) printf(X)
#else
#define PRINT(X...)
#endif

其中這個DEBUG,官方的默認工程在IDE的全局定義中是:
image
這里還可以定義為其他值(CH57x_common.h)

#define Debug_UART0        0
#define Debug_UART1        1
#define Debug_UART2        2
#define Debug_UART3        3

初始化

在main函數中,上來進行串口初始化:

#ifdef DEBUG
  GPIOA_SetBits(bTXD1);
  GPIOA_ModeCfg(bTXD1, GPIO_ModeOut_PP_5mA);
  UART1_DefInit( );
#endif

串口輸出

以下定義在文件"CH57x_sys.c"中
其中這里的Debug_UART0-Debug_UART3 對應就是0-3,
實際上printf最終會調用下面的函數,並根據對應的宏對不同的串口寄存器阻塞方式寫數據.

#ifdef DEBUG
int _write(int fd, char *buf, int size)
{
    int i;
    for(i=0; i<size; i++)
    {
#if  DEBUG == Debug_UART0
        while( R8_UART0_TFC == UART_FIFO_SIZE );                        /* 等待數據發送 */
        R8_UART0_THR = *buf++;                                               /* 發送數據 */
#elif DEBUG == Debug_UART1
        while( R8_UART1_TFC == UART_FIFO_SIZE );                        /* 等待數據發送 */
        R8_UART1_THR = *buf++;                                               /* 發送數據 */
#elif DEBUG == Debug_UART2
        while( R8_UART2_TFC == UART_FIFO_SIZE );                        /* 等待數據發送 */
        R8_UART2_THR = *buf++;                                               /* 發送數據 */
#elif DEBUG == Debug_UART3
        while( R8_UART3_TFC == UART_FIFO_SIZE );                        /* 等待數據發送 */
        R8_UART3_THR = *buf++;                                               /* 發送數據 */
#endif
    }
    return size;
}

#endif

二,修改printf 的串口

在mounriver studio中

很明顯,PRINT 最終是調用
int _write(int fd, char *buf, int size) 函數實現的,
而這個函數里,根據不同的宏,寫不同串口的輸出寄存器,所以我們修改printf串口只需要兩步:

  • 1, main函數一開始的地方,初始化對應的要printf輸出串口
  • 2, 在全局宏里面修改 DEBUG的宏的值即可

三,低功耗下的串口打印的注意事項

由於WCH的串口是有8字節的硬件fifo的,由上面的代碼我們可以看出,其打印並不會等到硬件為空時候才退出,而在進入睡眠后串口是不能正常工作的,如果此時串口的TX fifo非空,我們就需要等待空了后再睡眠
在WCH 提供的代碼的sleep.c 函數中,我們可以看到大概下面的處理方式: (很明顯,wch的sdk中只實現了UAR1的的串口處理,其他的我們需要手動添加.)

u32 CH58X_LowPower( u32 time )
{
#if (defined (HAL_SLEEP)) && (HAL_SLEEP == TRUE)
    <...>
#if( DEBUG == Debug_UART1 )  // 使用其他串口輸出打印信息需要修改這行代碼
    while( ( R8_UART1_LSR & RB_LSR_TX_ALL_EMP ) == 0 )
    {
        __nop();
    }
#endif
    <...>
#endif
  return 0;
}

四,注意事項

  • wch 官網CH573/CH583 的例程中即使把DEBUG全局宏去了,仍然會存在定義為UART0,如果這時候沒有初始化UART0,會導致卡在printf 函數里, 解決方法是注釋掉"CH57x_common.h" 文件中的 #ifndef DEBUG 下面的 "#define DEBUG Debug_UART0 "
  • 如果是取消printf打印,一定是關閉宏,不可以直接注釋掉打印串口的初始化,否則會引起后面調用打印的時候,卡到具體的串口輸出函數里
  • wch 的print是阻塞的,純靠硬件8字節的fifo,打印過多時候,將等待fifo不滿時候才繼續寫入,所以要有節制的利用串口日志,而不是肆無忌憚的去使用,導致整個芯片都在打印,干不了其他事了
  • 提高串口的打印速度是一個很好的使用習慣, 建議大家使用wch的第三代USB轉串芯片,最高波特率支持到6Mbps.

其他事項

關於浮點打印

在mounriver studio中

下面圖的兩種顏色的框,任選其一打勾
image

mounriver studio中的printf實現差異

wch官方提供的SDK里面,printf的實現來自於toolchain內置的newlib-nano庫,這個庫的的printf會使用堆。
當工程的ram使用非常緊張的時候,堆和棧可能會沖突,從而導致代碼異常,為了避免這種情況,我們可以選擇wch提供的printf實現

關於一些標准函數諸如sprintf 之類的函數

關於串口打印占用的資源


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM