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