M0 M4之UART初始化


新唐的M0/M4 UART都有16級或者64級FIFO,用來緩存UART數據的收/發。例如:如果RX FIFO中斷觸發級別設為14,UART接收14個字節才會發生RDA(接收數據可得)中斷。這樣可以降低CPU的loading。上面的情況,如果RX只接收到10個字節怎么辦呢?這時候就要用到接收超時中斷。當RX FIFO中收到1個字節以后,定時器就開始計數,如果定時器超時都沒有再收到下一個字節就會發生接收超時中斷(RTO)。
每個IP的初始化都需要先初始化時鍾,然后才是IP功能初始化。初始化UART之前需要使能要用的晶振,然后選擇時鍾源並使能時鍾。最后將UART用到的引腳切換為UART功能。

void UART0_Init() {

/* UART選擇HIRC做時鍾源 */

CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk) | CLK_CLKSEL1_UART_S_HIRC;

/* 使能UART0 IP的時鍾 */

CLK->APBCLK |= CLK_APBCLK_UART0_EN;

/* PB13用作UART0 接收,PB14用作UART0發送 */

SYS->PB_H_MFP &= ~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);

SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB13_MFP_UART0_RX | SYS_PB_H_MFP_PB14_MFP_UART0_TX);

/* Init UART0 */ UART_Open(UART0, 115200);

/*默認數據長度為8bit,沒有奇偶校驗,1個停止位*/

/*初始化UART1,波特率9600,數據長度8bit,1個停止位,偶校驗*/

UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1);

}

UART_Open會根據UART選擇的時鍾源計算波特率。
上面的代碼執行之后,UART_WRITE(UART0, 0x31)就會從UART TX引腳發送0x31了。如果要使用printf打印信息,keil project中加入retarget.c就可以,然后由宏定義#define DEBUG_PORT UART0決定printf從哪個UART口打印。
如果想使用中斷接收數據,代碼如下:

void UART0_Init() {

/* 選擇UART時鍾源 */

CLK->CLKSEL1 = (CLK->CLKSEL1 & ~CLK_CLKSEL1_UART_S_Msk) | CLK_CLKSEL1_UART_S_HIRC;

/* 使能UART0 IP的時鍾 */

CLK->APBCLK |= CLK_APBCLK_UART0_EN;

/* PB13用作UART0 接收,PB14用作UART0發送 */

SYS->PB_H_MFP &= ~(SYS_PB_H_MFP_PB13_MFP_Msk | SYS_PB_H_MFP_PB14_MFP_Msk);

SYS->PB_H_MFP |= (SYS_PB_H_MFP_PB13_MFP_UART0_RX | SYS_PB_H_MFP_PB14_MFP_UART0_TX);

/* Init UART0 */ UART_Open(UART0, 115200);

/*默認數據長度為8bit,沒有奇偶校驗,1個停止位*/

/*初始化UART1,波特率9600,數據長度8bit,1個停止位,偶校驗*/

UART_SetLine_Config(UART1, 9600, UART_WORD_LEN_8, UART_PARITY_EVEN, UART_STOP_BIT_1); /*設置接收超時時間為40,單位波特率*/ UART_SetTimeoutCnt(UART0, 40); /*設置接收FIFO觸發級別為14B*/ UART_SET_RX_FIFO_INTTRGLV(UART0, UART_TLCTL_RFITL_14BYTES);

/*使能接收FIFO 閥值中斷,和接收超時中斷*/

UART_ENABLE_INT(UART0, (UART_IER_RDA_IE_Msk | UART_IER_RTO_IE_Msk)); NVIC_EnableIRQ(UART0_IRQn);

}

/*UART0中斷處理函數*/

void UART0_IRQHandler(void) {

uint8_t u8InChar=0xFF;

uint32_t u32IntSts= UART0->ISR;

/*發生接收閥值中斷或者接收超時中斷*/

if(u32IntSts & (UART_ISR_RDA_IS_Msk| UART_ISR_RTO_IS_Msk))

{ /* 讀走接收FIFO中所有的數據,直到接收FIFO為空 */

while(UART_GET_RX_EMPTY(UART0)==0) {

/* 從接收FIFO中讀一個數據 */

u8InChar = UART_READ(UART0);

}

}

}

UART IP有個復位函數:SYS_ResetModule(UART0_RST); 其實新唐的芯片每個IP都有單獨的復位控制。什么時候需要復位UART0呢?如果該代碼是通過CPU reset執行到的,那原本UART可能在工作,RX FIFO中可能有數據,可能會發生中斷等等一些無法預估的事情,這時候最好復位一下UART IP的邏輯。

 


免責聲明!

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



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