久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > LPC1343串口學習

LPC1343串口學習

作者: 時間:2016-11-23 來源:網絡 收藏
本節我們來使用LPC1343的UART接口做一個簡單的收發實驗。

大家之前應該都有使用51或AVR一類單片機做過異步串行收發實驗,當然串口在電子開發中的應用地位就無需多言。我們直接進入主題。

本次試驗這樣設計,用PC作為上位機向UART發送一個(串)字節,然后LPC1343收到這個(串)字節后再發回UART,在PC上的串口觀察軟件顯示出來。

我們來看NXP帶給我們的UART例程來看看UART的設置以及工作過程。首先是主函數:
int main (void)
{
UARTInit(115200);//初始化UART接口并設置為波特率115200,NVIC也在內一并設置
while (1)
{
if ( UARTCount != 0 )
{
LPC_UART->IER = IER_THRE | IER_RLS;
UARTSend( (uint8_t *)UARTBuffer, UARTCount );//發送數據
UARTCount = 0;

LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;
}
}
}

從主函數就可以看到本次例程的目的了:初始化UART——一旦接收到數據之后立即停止接收——發送——開啟下一次接收。最重要的當然是初始化函數UARTInit():

void UARTInit(uint32_t baudrate)
{
uint32_t Fdiv;
uint32_t regVal;

UARTTxEmpty = 1;
UARTCount = 0;

NVIC_DisableIRQ(UART_IRQn); //關閉UART中斷,避免此后的初始化有中斷打斷
LPC_IOCON->PIO1_6 &= ~0x07;
LPC_IOCON->PIO1_6 |= 0x01;
LPC_IOCON->PIO1_7 &= ~0x07;
LPC_IOCON->PIO1_7 |= 0x01;

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
LPC_SYSCON->UARTCLKDIV = 0x1;

LPC_UART->LCR = 0x83;
regVal = LPC_SYSCON->UARTCLKDIV;
Fdiv=(((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)
//baudrate ;

LPC_UART->DLM = Fdiv / 256; //寫入波特率計算值高位
LPC_UART->DLL = Fdiv % 256; //寫入波特率計算值低位
LPC_UART->LCR = 0x03;
LPC_UART->FCR = 0x07;

regVal = LPC_UART->LSR;

while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) );
while ( LPC_UART->LSR & LSR_RDR )
{
regVal = LPC_UART->RBR;
}


NVIC_EnableIRQ(UART_IRQn);

#if TX_INTERRUPT //是否使用發送中斷,本次例程使用
LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS;
#else //所以執行此else
LPC_UART->IER = IER_RBR | IER_RLS;

#endif
return;
}

打星號的地方是筆者認為比較值得關注的地方:
1、UART的IO口設置,根據上述函數中的語句查找相關寄存器,可以發現它將P16、P17設置為:UART_RXD和UART_TXD功能;
2、選擇UART時鐘分頻數,此處1分頻,和波特率設置有直接關系;
3、選擇數據格式,此處選擇數據長度8位,無校驗,1位停止位,并開啟除數鎖存;
4、除數鎖存器:分為LSB(8位)和MSB(8位),用來填入對應某波特率的計數值,更改之前解除鎖定,更改完畢恢復鎖定,這樣就可以鎖定波特率了(可以這樣簡單的理解);
5、計算波特率,此處是重點了。首先我們肯定知道系統核心頻率為72MHz,即SystemCoreClock=72 000 000(參考本系列前幾章內容)。而UART作為AHB總線上的設備,自然要經過AHB分頻器,在此處,AHB分頻系數并未做過特別設置,所以為默認值1。時鐘經過AHB分頻之后要經過UART分頻器進行再分頻,分頻系數仍為1(第2點)。因此我們來計算這個公式:
Fdiv = (((SystemCoreClock*LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate
其中SystemCoreClock=72000000,LPC_SYSCON->SYSAHBCLKDI=1,regVal=1,baudrate=115200,所以可以計算出:
Fdiv=39.0625≈0x27
這個便是產生115200波特率所要填入除數鎖存器的值。逆過來就可以計算出計數值對應的波特率。
6、線狀態寄存器(下文稍加講述)是以讀操作來清空的;
其實這個函數,對于用戶來說,只需要填入想要產生的波特率作為函數參數就可以完成LPC1343的UART初始化以及波特率設定工作。
設定完成之后,UART就開始工作了,因為初始化函數里面開啟了“啟用緩存數據可用中斷、線狀態中斷”所以當有數據從上位機向UART發送數據時,進入中斷服務函數:
void UART_IRQHandler(void)
{
uint8_t IIRValue, LSRValue;
uint8_t Dummy = Dummy;
IIRValue = LPC_UART->IIR;
IIRValue >>= 1;
IIRValue &= 0x07;
if (IIRValue == IIR_RLS)
{
LSRValue = LPC_UART->LSR;

if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
{

UARTStatus = LSRValue;
Dummy = LPC_UART->RBR;

return;
}
if (LSRValue & LSR_RDR)
{

UARTBuffer[UARTCount++] = LPC_UART->RBR;
if (UARTCount == BUFSIZE)
{
UARTCount = 0;
}
}
}
else if (IIRValue == IIR_RDA)
{

UARTBuffer[UARTCount++] = LPC_UART->RBR;
if (UARTCount == BUFSIZE)
{
UARTCount = 0;
}
}
else if (IIRValue == IIR_CTI)
{

UARTStatus |= 0x100;
}
else if (IIRValue == IIR_THRE)
{

LSRValue = LPC_UART->LSR;
if (LSRValue & LSR_THRE)
{
UARTTxEmpty = 1;
}
else
{
UARTTxEmpty = 0;
}
}
return;
}
這個中斷服務函數是一個if…else if….else if結構。在進入此中斷服務函數后,讀取

中斷標識寄存器判斷中斷源,選擇進入相應的if環節執行相應語句。我們看看UART都有哪些中斷。第一個是RLS,Receive Line Status即接收線中斷:
可以在用戶手冊查看到接受線中斷分別有以下多種:
RDR :Receiver Data Ready,接受數據就緒中斷;
OE:Overrun Error,即溢出錯誤中斷;
PE:Parity Error,校驗錯誤中斷;
FE:Framing Error,幀錯誤中斷;
BI:Break Interrupt,間隔狀態中斷;
THRE:Transmitter Holding Register Empty,發送保持寄存器空中斷;
TEMP:Transmitter Empty,發送保持寄存器與臨時寄存器空中斷;
RXFE:Error in RX FIFO,RX錯誤中斷;
對照上述中斷服務函數第一個if部分,當判斷確定為線中斷之后,即判斷是否是OE——RXFE中的任何一個錯誤,如果有錯誤,則讀出數據有效保存,如果有錯誤,則讀出數據但丟棄。
所以,線中斷在進行數據校驗的場合才會使用。而本次實驗中并未用到數據校驗位。所以此中斷不會進入。
當不使用校驗功能之時,收到數據之后會進入第一個else if結構:
else if (IIRValue == IIR_RDA)
{}
在進入此部分之后將數據讀出。
當接受一個字符(5~8位不等)超時時,會進入“接受字符超時中斷”部分。
發送完成中斷在本次試驗中并未使能,略過。
如此我們應該可以預知本次試驗中當PC上位機發送一個(串)字符之后,會進入中斷服務函數并且進入else if (IIRValue == IIR_RDA{}環節,將收到的數據保存在UARTBuffer中,并使UARTCount++。然后退出中斷函數之后,回到主函數,執行發送部分:
if ( UARTCount != 0 )
{
LPC_UART->IER = IER_THRE | IER_RLS;
UARTSend( (uint8_t *)UARTBuffer, UARTCount );//發送數據
UARTCount = 0;

LPC_UART->IER = IER_THRE | IER_RLS | IER_RBR;
}
}
找到UARTSend():
void UARTSend(uint8_t *BufferPtr, uint32_t Length)
{
while ( Length != 0 )
{

#if !TX_INTERRUPT//未使用中斷發送方式,所以編譯此部分
while ( !(LPC_UART->LSR & LSR_THRE) );//等待發送保持寄存器空
LPC_UART->THR = *BufferPtr;//將待發數據寫入發送保持寄存器
#else

while ( !(UARTTxEmpty & 0x01) );
LPC_UART->THR = *BufferPtr;
UARTTxEmpty = 0;
#endif
BufferPtr++;
Length--;
}
return;
}
此UART數據發送函數,第一個參數要求填入存放待發送數據(注意為8位,即字符型數據)的數組名,第二個參數為待發數據長度。通過注釋可以看到發送的過程很簡單,等待發送保持寄存器為空后將數據寫入發送保持寄存器就完成了發送。
這樣我們就將本次的UART收發試驗的過程“初始化——等待接收——UART中斷——保存數據——發送數據”分析完畢。
NXP贈送的這個LPC1343并沒有掛載UART接口,而只留了P16、P17兩個IO給用戶拓展,所以筆者使用了其他開發板的串口連接,需要注意的是,我們手上的這塊開發板是3.3V供電,而市面上比較多采用的MAX232是5V供電。所以或者使用LPC1343評估板的5V給MAX232供電,或者使用3.3V供電的電平轉換芯片。筆者這里使用了3.3V供電的ST232芯片。
導入lpc1343.examples->uart,編譯鏈接。連好硬件,從串口調試終端發送一個(串)數據,可以看到串口調試終端的接收框里準確的顯示了我們所發送的數據,本次實驗完結。


關鍵詞: LPC1343串口學

評論


技術專區

關閉