CH579/CH57x 串口收發,UART使用


CH57x 的串口跟沁恆其他的MCU串口外設使用基本一致, 收發分別有8個字節的FIFO,支持fifo閾值中斷,以及超時中斷,

支持的波特率

CH577/578/579 波特率計算與誤差

<待編輯>

CH571/573/581/582/583 波特率計算與誤差

<待編輯>

CH57X/58x 系列芯片串口波特率計算在線工具

<待編輯>

UART中斷接收處理:

uint16_t user_rx_buffer_length_mask = 1024-1;
uint16_t user_rx_buffer_write_index = 0;
uint8_t uart_rx_buffer[1024];
//Not every uart reception will end with a UART_II_RECV_TOUT
//UART_II_RECV_TOUT can only be triggered when R8_UARTx_RFC is not 0
//Here we cannot rely on UART_II_RECV_TOUT as the end of a uart reception

/*** Keep at least 1 byte in the RX fifo and UART_II_RECV_TOUT will be triggered at the end of every reception .***/
void UART3_IRQHandler(void){
    switch( UART3_GetITFlag() ){
        case UART_II_LINE_STAT:        // 線路狀態錯誤
            UART3_GetLinSTA();
            break;
        case UART_II_RECV_RDY:          // 數據達到設置觸發點 ,這里可以留一個在接收fifo里面,保證每次都能產生接收超時
            while( R8_UART3_RFC > 1) {  // 這個方式必須保證uart的接收觸發中斷是大於1字節的
                 uart_rx_buffer[user_rx_buffer_write_index & user_rx_buffer_length_mask] = R8_UART3_RBR;
          user_rx_buffer_write_index += 1;
            }
            break;
        case UART_II_RECV_TOUT:         // 接收超時,暫時一幀數據接收完成
            //for(uint8_t i=0;i < R8_UART3_RFC;i++) //There is an issue here
            while(0 != R8_UART3_RFC) {
                 uart_rx_buffer[user_rx_buffer_write_index & user_rx_buffer_length_mask] = R8_UART3_RBR;
          user_rx_buffer_write_index += 1;
            }
            break;
        case UART_II_THR_EMPTY: // 發送緩存區空,可繼續發送
            break;
        case UART_II_MODEM_CHG: // 只支持串口0
            break;
        default:
            break;
     }
}

UART 查詢發送

//tx process
//本查詢函數需要扔到主循環不斷調用
while(R8_UART1_TFC < UART_FIFO_SIZE){
    //判斷發送軟件緩沖區,是否空,如果不空,就一個一個讀出來,填到硬件fifo里
    if((user_tx_buffer_write_index - user_tx_buffer_read_index )& user_tx_buffer_length_mask) {
        //把軟件緩沖區的數據填到uart的硬件發送fifo里
        R8_UART1_THR = uart_tx_buffer[user_tx_buffer_read_index & user_tx_buffer_length_mask] ;  
        user_tx_buffer_read_index += 1;
    }else{
        break;
    }
}

UART 中斷發送

//開始發送,這里,我們需要先向串口的發送fifo里面寫入數據,然后串口的發送fifo空的時候才會報中斷上來,接下來我們在中斷服務程序里面處理就好了
void uart_start_send(void) {
    //這里涉及到中斷中修改標志位,我們關中斷后進行查標志位
    __disable_irq();
    if(false == uart1_tx_on_going) {
        __enable_irq();
        //由於寫fifo的操作非常快,我們這里直接while循環即可
        while(R8_UART1_TFC < UART_FIFO_SIZE){
            //發送緩沖區是否有數據,這里我們用軟件實現了一個緩沖區,如果有數據,就把數據取出來放到uart的fifo里
            if((user_rx_buffer_write_index - user_rx_buffer_read_index )& user_rx_buffer_length_mask) {
                R8_UART1_THR = uart_rx_buffer[user_rx_buffer_read_index & user_rx_buffer_length_mask] ;  
                user_rx_buffer_read_index += 1;
                uart1_tx_on_going = true;
            }else{
                break;
            }
        }
    }else{
        __enable_irq();
    }
}


//中斷服務程序中的處理,這里主要關注 UART_II_THR_EMPTY 里面的處理
void UART1_IRQHandler(void) {
    UINT8 i;
    //GPIOA_SetBits(GPIO_Pin_0);
    //GPIOA_ResetBits(GPIO_Pin_0);
    switch( UART1_GetITFlag() ) {
        case UART_II_LINE_STAT:        // 線路狀態錯誤
            UART1_GetLinSTA();
            break;
        case UART_II_RECV_RDY:          // 數據達到設置觸發點
        case UART_II_RECV_TOUT:         // 接收超時,暫時一幀數據接收完成
            while(0 != R8_UART1_RFC) {
                uart_rx_buffer[user_rx_buffer_write_index & user_rx_buffer_length_mask] = R8_UART1_RBR;
                user_rx_buffer_write_index += 1;
            }
            break;
        case UART_II_THR_EMPTY:         // 發送緩存區空,可繼續發送
            while(R8_UART1_TFC < UART_FIFO_SIZE){
                if((user_tx_buffer_write_index - user_tx_buffer_read_index )& user_tx_buffer_length_mask) {
                    R8_UART1_THR = uart_tx_buffer[user_tx_buffer_read_index & user_tx_buffer_length_mask] ;  
                    user_tx_buffer_read_index += 1;
                }else{
                    uart1_tx_on_going = false;
                    break;
                }
            }
            break;
        case UART_II_MODEM_CHG:         // 只支持串口0
            break;
        default:
            break;
    }
}

BLE工程中UART收發處理:

CH57x的ble協議棧是查詢方式實現的,實際應用中,中斷在微觀上會打斷BLE的運行,所以能少用中斷就少用中斷,在中斷張能少占用時間就少占用一些,
但是而ch57x的uart 又沒有dma,只有有8個直接的fifo,所以,
在沒有串口流控(CTS RTS)的情況下,建議uart的接收使用中斷方式,而uart發送使用查詢方式

Q&A

1.休眠情況下UART能收發數據嗎
UART依賴於高頻時鍾


免責聲明!

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



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