目录
1. DW_apb_uart初始化流程
DW_apb_uart协议第七章有常规场景下的初始化流程介绍,发送数据配置流程如下图:
接收数据配置流程如下图:
简单整理初始化流程:
(1)配置MCR寄存器,配置红外sir模式、自动流控模式、loop back模式和modem控制输出值;
(2) 将 LCR.dlab写入1,允许配置波特率分频参数寄存器;
(3)根据需求,计算波特率整数和小数分频系数,分别配置DLL、DLH、DLF寄存器;
(4)将 LCR.dlab写入0,禁止配置波特率分频参数寄存器;
(5)配置LCR寄存器,配置数据长度、停止位长度、奇偶校验等参数;
(6)配置RCR寄存器,配置TX FIFO、RX FIFO水线阈值;
(7)配置IE寄存器,使能相关中断;
(8)如果要发送数据,则把要发送的数据写到THR寄存器中,然后读取IIR中断状态寄存器的值,当IIR中断状态寄存器的值为0x2时,说明TX FIFO为空,可以继续发送数据;如果要接收数据,则等待IIR中断状态寄存器为0x4,表明有数据进入RX FIFO,CPU可以读取RBR寄存器来获取接收的数据。
2. DW_apb_uart初始化编程
2.1 定义UART寄存器
/*定义联合体用于访问 RBR/DLL/THR 寄存器 */
typedef union
{
volatile const uart_rbr_reg_s rbr; /* Receive Buffer Register Address offset: 0x00 */
volatile uart_dll_reg_s dll; /* Divisor Latch (Low) Address offset: 0x00 */
volatile uart_thr_reg_s thr; /* Transmit Holding Register Address offset: 0x00 */
} uart_rdt_typedef_u;
/* 定义联合体用于访问 DLH/IER 寄存器 */
typedef union
{
volatile uart_dlh_reg_s dlh; /* Divisor Latch High Address offset: 0x04 */
volatile uart_ier_reg_s ier; /* Interrupt Enable Register Address offset: 0x04 */
} uart_dhie_typedef_u;
/* 定义联合体用于访问 FCR/IIR 寄存器 */
typedef union
{
volatile uart_fcr_reg_s fcr; /* FIFO Control Register Address offset: 0x08 */
volatile const uart_iir_reg_s iir; /* Interrupt Identification Register Address offset: 0x08 */
} uart_fcii_typedef_u;
上面这几个寄存器很特殊,使用的相同的偏移地址,读写的时候分别表示不同的含义,所以用联合体来定义。(吐槽一下,这个设计有点坑爹 =_=)
接下来是定义所有的寄存器。
typedef struct {
uart_rdt_typedef_u rdt; /* 0x00 Union type to access RBR,DLL,THR */
uart_dhie_typedef_u dhie; /* 0x04 Union type to access DLH,IER */
uart_fcii_typedef_u fcii; /* 0x08 Union type to access FCR,IIR */
volatile uart_lcr_reg_s lcr; /* 0x0c UART Line Control Register */
volatile uart_mcr_reg_s mcr; /* 0x10 UART Modem Control Register */
volatile const uart_lsr_reg_s lsr; /* 0x14 UART Line Status Register */
volatile const uart_msr_reg_s msr; /* 0x18 UART Modem Status Register */
volatile uart_scr_reg_s scr; /* 0x1c UART Scratchpad Register */
volatile uart_lpdll_reg_s lpdll; /* 0x20 UART Low Power Divisor Latch Low */
volatile uart_lpdlh_reg_s lpdlh; /* 0x24 UART Low Power Divisor Latch High */
volatile uart_misc_ctrl_reg_s misc_ctrl; /* 0x28 UART Functional control register */
unsigned char space0[68]; /* Reserved:0x2c~0x6c UART space0 */
volatile uart_far_reg_s fasr; /* 0x70 UART Fifo Access Register */
volatile uart_tfr_reg_s tfr; /* 0x74 UART Tx Fifo Read Register */
volatile uart_rfw_reg_s rfw; /* 0x78 UART Rx Fifo Write Register */
volatile uart_usr_reg_s usr; /* 0x7c UART Status Register */
volatile uart_tfl_reg_s tfl; /* 0x80 UART Transmit FIFO Level Register */
volatile uart_rfl_reg_s rfl; /* 0x84 UART Receive FIFO Level Register */
volatile uart_srr_reg_s srr; /* 0x88 UART Software Reset Register */
volatile uart_srts_reg_s srts; /* 0x8c UART Shadow Request to Send Register */
volatile uart_sbcr_reg_s sbcr; /* 0x90 UART Shadow Break Control Register */
volatile uart_sdmam_reg_s sdmam; /* 0x94 UART Shadow DMA Mode Register */
volatile uart_sfe_reg_s sfe; /* 0x98 UART Shadow FIFO Enable Register */
volatile uart_srt_reg_s srt; /* 0x9c UART Shadow RCVR Trigger Register */
volatile uart_stet_reg_s stet; /* 0xa0 UART Shadow TX Empty Trigger Register */
volatile uart_htx_reg_s htx; /* 0xa4 UART Halt tx */
unsigned char dmasa; /* 0xa8 UART Dma software Acknowledge Register */
volatile uart_tcr_reg_s tcr; /* 0xac UART Transceiver Control Register */
volatile uart_de_en_reg_s de_en; /* 0xb0 UART Driver Output Enable Register */
volatile uart_re_en_reg_s re_en; /* 0xb4 UART Receiver Output Enable Register */
volatile uart_det_reg_s det; /* 0xb8 UART Driver Output Enable Timing Register */
volatile uart_tat_reg_s tat; /* 0xbc UART TurnAround Timing Register */
volatile uart_dlf_reg_s dlf; /* 0xc0 UART Divisor Latch Fraction Register */
volatile uart_rar_reg_s rar; /* 0xc4 UART Receive Address Register */
volatile uart_tar_reg_s tar; /* 0xc8 UART Transmit Address Register */
volatile uart_lcr_ext_reg_s lcr_ext; /* 0xcc UART Line Extended Control Register */
unsigned int space1[9]; /* Reserved:0xd0 0xd4 0xd8 0xdc 0xe0 0xe4 0xe8 0xec 0xf0 */
volatile uart_cpr_reg_s cpr; /* 0xf4 UART Component Parameter Register */
volatile uart_ucv_reg_s ucv; /* 0xf8 UART Component Version Register */
volatile uart_ucv_reg_s ctr; /* 0xfc UART Component Type Register */
} uart_reg_s;
2.2 定义UART初始化结构体
该结构体包含UART初始化相关参数,用于配置UART的寄存器。
typedef struct {
uart_clk_sel_e clk_sel; /*!< 配置 uart 时钟源 */
uart_baudrate_e baudrate; /*!< 配置 uart 波特率 */
uart_data_length_e data_length; /*!< 配置 uart 数据位宽 */
uart_stop_bits_e stop_bits; /*!< 配置 uart 停止位宽 */
uart_parity_en_e parity; /*!< uart 校验使能控制 */
uart_parity_sel_e par_sel; /*!< uart 奇偶校验模式选择 */
uart_stick_parity_e stick_par; /*!< uart 固定校验模式控制.*/
uart_fifo_mode_e fifo_mode; /*!< uart FIFO 模式使能控制 */
uart_dma_mode_e dma_mode; /*!< uart DMA 模式使能控制 */
uart_sir_mode_e sir_mode; /*!< uart 红外模式使能控制 */
uart_loopback_mode_e loop_back; /*!< uart 环回模式使能控制 */
uart_hw_control_e hw_flow_ctrl; /*!< uart 硬件流控使能控制 */
uart_tx_rx_9bit_s tx_rx_9bit; /*!< uart 9bit 模式使能控制 */
uart_rs485_cfg_s rs485_cfg; /*!< uart RS485 模式使能控制 */
uart_rx_trig_e rcv_trig; /*!< uart 接收水线配置 */
uart_tx_trig_e tx_trig; /*!< uart 发送水线配置 */
} uart_init_s;
2.3 定义UART控制结构体
该结构体包含UART工作需要用到的相关控制参数,主要用于工作流程的控制。
typedef struct {
uart_reg_s *instance; /*!< 指向 uart 寄存器地址 */
unsigned int irq_control; /*!< uart 中断使能控制 */
unsigned int irq_num; /*!< uart 中断号配置 */
uart_init_s init; /*!< uart 初始化参数结构体 */
unsigned char *p_tx_buffer_ptr; /*!< uart 发送buf */
unsigned short tx_xfer_size; /*!< uart 发送数据量配置 */
volatile unsigned short tx_xfer_count; /*!< uart 已发送数据量统计 */
unsigned char *p_rx_buffer_ptr; /*!< uart 接收buf */
unsigned short rx_xfer_size; /*!< uart 接收数据量配置 */
volatile unsigned short rx_xfer_count; /*!< uart 已接收数据量统计 */
volatile unsigned int error_code; /*!< uart 错误码 */
volatile unsigned int interrupt_flags; /*!< uart 中断标记位 */
} uart_handle_s;
2.4 UART初始化
void uart_init(uart_handle_s *huart)
{
//1.开启时钟门控
uart_clk_enable(huart, 0x1);
//2.uart时钟源选择
uart_clk_sel(huart);
//3.CRG模块软复位
uart_crg_rst_en(huart);
//4.管脚复用设置
uart_io_config(huart);
//5.UART 软复位
uart_software_reset(huart);
//6.UART错误码清零
huart->error_code = UART_ERROR_NONE;
//7.硬件流控配置
if (huart->init.hw_flow_ctrl == UART_HWCONTROL_ENABLE){
uart_auto_flow_control(huart, ENABLE);
uart_rts_control(huart, ENABLE);
}else{
uart_auto_flow_control(huart, DISABLE);
}
//8.IRDA配置
if (huart->init.sir_enable == UART_SIR_ENABLE) {
uart_sir_mode_control(huart, ENABLE);
}else{
uart_sir_mode_control(huart, DISABLE);
}
/9. 配置波特率
uart_divisor_latch_access_control(huart, ENABLE);
uart_set_div_latch(huart);
uart_divisor_latch_access_control(huart, DISABLE);
//10.配置数据位长度,停止位宽,奇偶校验等
uart_data_length_select(huart, huart->init.word_length);
uart_stop_bits_select(huart, huart->init.stop_bits);
uart_parity_enable_control(huart,huart->init.parity);
uart_even_parity_control(huart,huart->init.par_sel);
uart_stick_parity_control(huart, huart->init.stick_par);
//11.配置FIFO mode,DMA水线设置
if(huart->init.fifo_mode == UART_FIFO_ENABLE){
uart_fifo_mode_enable_control(huart, UART_FIFO_ENABLE);
uart_tx_empty_trigger_level_set(huart, huart->init.tx_trig);
uart_rx_trigger_level_set(huart,huart->init.rcv_trig);
uart_txfifo_reset(huart);
uart_rxfifo_reset(huart);
}else{
uart_fifo_mode_enable_control(huart, UART_FIFO_DISABLE);
}
//12.配置DMA
uart_dma_mode_select(huart, huart->init.dma_mode);
//13.配置 THRE interrupt
uart_programmable_ther_interrupt_control(huart, DISABLE);
//14.配置9bit
if (huart->init.tx_rx_9bit.en == UART_TX_RX_9BIT_ENABLE) {
uart_9bit_enable_control(huart, UART_TX_RX_9BIT_ENABLE);
uart_receice_address_set(huart, huart->init.tx_rx_9bit.recv.addr);
uart_transmit_address_set(huart, huart->init.tx_rx_9bit.trans.addr);
uart_9bit_transmit_mode_set(huart, huart->init.tx_rx_9bit.trans.mode);
uart_9bit_address_match_mode_set(huart, huart->init.tx_rx_9bit.recv.mode);
uart_9bit_send_address_mode_set(huart, huart->init.tx_rx_9bit.trans.addr_en);
}else{
uart_9bit_enable_control(huart, UART_TX_RX_9BIT_DISABLE);
}
//15.配置RS485
if(huart->init.rs485_cfg.en == UART_RS485_MODE_ENABLE){
uart_rs485_enable_control(huart,UART_RS485_MODE_ENABLE);
uart_rs485_re_polarity_set(huart, huart->init.rs485_cfg.re_pol);
uart_rs485_de_polarity_set(huart,huart->init.rs485_cfg.de_pol );
uart_rs485_transfer_mode_set(huart, huart->init.rs485_cfg.duplex);
uart_rs485_de_assertion_time_set(huart, huart->init.rs485_cfg.det.de_assert_time);
uart_rs485_de_deassertion_time_set(huart, huart->init.rs485_cfg.det.de_deassert_time);
uart_rs485_de_to_re_turnaround_time_set(huart, huart->init.rs485_cfg.tat.de_to_re);
uart_rs485_re_to_de_turnaround_time_set(huart, huart->init.rs485_cfg.tat.re_to_de);
uart_rs485_de_enable_control(huart, huart->init.rs485_cfg.de_en);
uart_rs485_re_enable_control(huart, huart->init.rs485_cfg.re_en);
}else{
uart_rs485_enable_control(huart,UART_RS485_MODE_DISABLE);
}
//16.中断使能控制
if(huart->irq_control == UART_IRQ_ENABLE){
drv_irq_register(huart->irq_num, uart0_irq_handle, huart);
drv_irq_enable(huart->irq_num, IRQ_TYPE_VECTOR_HIGH_LEVEL, IRQ_PRIORITY_1);
}
}
3. DW_apb_uart 打印测试
void uart_default_cfg(uart_handle_s *huart)
{
memset(huart, 0, sizeof(uart_handle_s)); //对结构体清零
huart->init.clk_sel = CLK_LS; //选择100M低速时钟
huart->init.baudrate = UART_BAUDRATE_115200; //波特率115200
huart->init.word_length = UART_DATA_LEN_8; //数据位宽8bit
huart->init.stop_bits = UART_STOP_BITS_1; //停止位宽1bit
huart->init.parity = UART_PARITY_DISABLE; //禁止校验功能
huart->init.par_sel = UART_PARITY_ODD; //选择偶校验
huart->init.stick_par = UART_STICK_PARITY_DISABLE; //禁止固定校验模式
huart->init.fifo_mode = UART_FIFO_ENABLE; //使能FIFO
huart->init.dma_mode = UART_DMAM_0; //选择DMA0
huart->init.sir_enable = UART_SIR_DISABLE; //禁止红外模式
huart->init.loop_back = UART_LOOPBACK_DISABLE; //禁止环回模式
huart->init.hw_flow_ctrl = UART_HWCONTROL_DISABLE; //禁止硬件流控
huart->init.tx_rx_9bit.en = UART_TX_RX_9BIT_DISABLE; //禁止9bit功能
huart->init.rs485_cfg.en = UART_RS485_MODE_DISABLE; //禁止RS485
huart->init.rcv_trig = UART_RT_FIFO_CHAR_1; //接收水线配置为1byte
huart->init.tx_trig = UART_TX_FIFO_EMPTY; //发送水线配置为0
huart->irq_control = UART_IRQ_ENABLE; //使能中断
huart->irq_num = IRQ_NUM_UART0; //选择中断号
}
int main(void)
{
uart_handle_s uhandle;
sysctrl_init();
crg_init();
uart_default_cfg(&uhandle);
uart_init(&g_dbg_uart);
print("hello word 1\r\n");
print("hello word 2\r\n");
print("hello word 3\r\n");
}
测试结果: