(轉)Cortex-M3 (NXP LPC1788)之UART用法


 在工作中經常將平台的串口和PC機連接,通過串口打印信息進行程序調試。LPC1788共有5個串口Uart0~Uart4,跟具開發板的資源,將使用Uart2進行簡單的串口輸出和輸入中斷的操作。開發板上使用74HC4052多路開關對UART2的RXD和TXD進行選擇,使用SP3243E進行3.0V到5.5V的RS-232電平轉換。查看手冊配置好相關的跳線帽,保證DB口上的串口輸出采用的是Uart2。

       下面介紹Uart相關系統配置和Uart模塊的配置。Uart的時鍾采用PCLK,我們配置系統的CCLK為120M,PCLK為60M,后面設置串口的波特率就采用PLCK進行計算。要使用串口2的功能需要使能系統時鍾控制PCONP,以及配置GPIO管腳為Uart2的RXD和TXD功能。要實現通信,我們需要設置數據的格式,包括傳輸的波特率,數據長度,停止位,以及校驗等,這些數據在線性控制寄存器UnLCR中控制。波特率的產生需要經過分數波特率分頻器UnFDR和主分頻器DLL,DLM。計數公式如下圖。

baudrate

根據計算,當PLCK=60M,波特率為115200,數據位為8,停止位為1,無校驗,則DLL = 22, DLM =0, DivAddVal =1, MulVal = 2 ,線性控制寄存器中的值為0x3。

        要通過串口發送數據時,只需要把要發送的數據寫入發送保持寄存器UnTHR,系統就會通過移位寄存器將數據通過串口發送。為了了解系統的發送狀態,還需要線性狀態寄存器UnLSR,例如程序中使用該該寄存器的第5位判斷發慫保持寄存器是否為空,防止數據溢出。

        如果需要進行串口的中斷操作,還需要對串口中斷進行配置,如串口中斷使能寄存器UnIER和串口中斷標識寄存器UnIIR。程序中使用到了串口2的接收中斷,為此在中斷使能設置寄存器ISER中使能UART2中斷,在串口中斷使能寄存器UnIER中使能串口的接收中斷,該中斷同時使能了字符接收超時中斷。UART2的RXD管腳接收到數據將存放在FIFO中,程序中配置接收FIFO的觸發條件為1個字節,即有接收到數據就觸發。中斷觸發后,我們可以根據中斷標識寄存器UnIIR判斷到底是串口的接收中斷,超時中斷,發送中斷等。進入中斷以后,接收中斷和超時中斷,都可以通過讀取接收緩存寄存器UnRBR進行中斷復位,使下次中斷可以發生。

       下面的程序例子,程序開始打印菜單,PC串口軟件發送一個字節數據給開發板,開發板接收到數據后將讀取UnRBR前后的中斷標識寄存器IIR的值,以及接收到的值發送回給PC。如果是0x5a或者0xa5還可以打開或者關閉LED指示燈。

 

  1. #define CCLK        120000000 
  2. #define PCLK         60000000 
  3.  
  4. #define rFIO1DIR    (*(volatile unsigned*)(0x20098020)) 
  5. #define rFIO1MASK   (*(volatile unsigned*)(0x20098030)) 
  6. #define rFIO1PIN    (*(volatile unsigned*)(0x20098034)) 
  7. #define rFIO1SET    (*(volatile unsigned*)(0x20098038)) 
  8. #define rFIO1CLR    (*(volatile unsigned*)(0x2009803c)) 
  9.  
  10. #define rISER0      (*(volatile unsigned*)(0xE000E100)) 
  11.  
  12. #define rCLKSRCSEL  (*(volatile unsigned *)(0x400FC10C))     //時鍾源選擇寄存器   
  13. #define rPLL0CON    (*(volatile unsigned *)(0x400FC080))     //PLL0控制寄存器   
  14. #define rPLL0CFG    (*(volatile unsigned *)(0x400FC084))     //PLL0配置寄存器   
  15. #define rPLL0STAT   (*(volatile unsigned *)(0x400FC088))     //PLL0狀態寄存器   
  16. #define rPLL0FEED   (*(volatile unsigned *)(0x400FC08C))     //PLL0饋送寄存器   
  17. #define rPLL1CON    (*(volatile unsigned *)(0x400FC0A0))        
  18. #define rPLL1CFG    (*(volatile unsigned *)(0x400FC0A4))   
  19. #define rPLL1STAT   (*(volatile unsigned *)(0x400FC0A8))   
  20. #define rPLL1FEED   (*(volatile unsigned *)(0x400FC0AC))   
  21. #define rCCLKSEL    (*(volatile unsigned *)(0x400FC104))     //CPU時鍾選擇寄存器   
  22. #define rUSBCLKSEL  (*(volatile unsigned *)(0x400FC108))     //USB時鍾選擇寄存器   
  23. #define rPCLKSEL    (*(volatile unsigned *)(0x400FC1A8))     //外設時鍾寄存器   
  24. #define rPCON       (*(volatile unsigned *)(0x400FC0C0))   
  25. #define rPXCONP     (*(volatile unsigned *)(0x400FC0C4))   
  26. #define rSCS        (*(volatile unsigned *)(0x400FC1A0))     //系統控制和狀態寄存器   
  27. #define rCLKOUTCFG  (*(volatile unsigned *)(0x400FC1C8)) 
  28.  
  29. #define rIOCON_P0_10    (*(volatile unsigned *)(0x4002C028)) 
  30. #define rIOCON_P0_11    (*(volatile unsigned *)(0x4002C02C)) 
  31. #define rPCONP      (*(volatile unsigned *)(0x400FC0C4)) 
  32. #define rU2LCR      (*(volatile unsigned *)(0x4009800C)) 
  33. #define rU2FDR      (*(volatile unsigned *)(0x40098028)) 
  34. #define rU2DLL      (*(volatile unsigned *)(0x40098000)) 
  35. #define rU2DLM      (*(volatile unsigned *)(0x40098004)) 
  36. #define rU2TER      (*(volatile unsigned *)(0x40098030)) 
  37. #define rU2THR      (*(volatile unsigned *)(0x40098000)) 
  38. #define rU2RBR      (*(volatile unsigned *)(0x40098000)) 
  39. #define rU2FCR      (*(volatile unsigned *)(0x40098008)) 
  40. #define rU2IIR      (*(volatile unsigned *)(0x40098008)) 
  41. #define rU2LSR      (*(volatile unsigned *)(0x40098014)) 
  42. #define rU2IER      (*(volatile unsigned *)(0x40098004)) 
  43. #define rU2ACR      (*(volatile unsigned *)(0x40098020)) 
  44.  
  45. void UART2_IRQHandler() 
  46.     unsigned int intId; 
  47.     char tmp_char; 
  48.      
  49.     intId = rU2IIR&0xf; 
  50.     rU2THR = intId; 
  51.      
  52.     if(intId == 0xc || intId == 0x4)    //RDA或者CTI中斷 
  53.     { 
  54.         rU2LCR &= ~(0x1<<7);  //DLAB=0 
  55.         tmp_char = rU2RBR&0xff; 
  56.         rU2THR = tmp_char; 
  57.     } 
  58.     intId = rU2IIR&0xf; 
  59.     rU2THR = intId; 
  60.  
  61.          
  62.     if(tmp_char == 0xa5) 
  63.         rFIO1PIN |= (1<<18); 
  64.     elseif(tmp_char == 0x5a) 
  65.         rFIO1PIN &= ~(1<<18); 
  66.      
  67. void SystemInit()   
  68. {   
  69.     rSCS &= ~(0x1<<4);            //頻率12M   
  70.     rSCS |= (0x1<<5);             //使能主振盪器   
  71.     while(0 == (rSCS & (0x1<<6)));//等待主振盪器穩定   
  72.        
  73.     rCLKSRCSEL = 0x1;   
  74.        
  75.     rPLL0CFG = 0x9;                 //配置CCLK = 120M   
  76.     rPLL0CON = 0x01;   
  77.     rPLL0FEED = 0xAA;   
  78.     rPLL0FEED =0x55;   
  79.     while(0 == (rPLL0STAT & (0x1<<10)));    
  80.        
  81.     rCCLKSEL = (0x1 | (0x1<<8));   
  82.     rPCLKSEL = 0x2;                 //配置PCLK = 60M    
  83.     rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);   
  84.  
  85. void Init_Uart2() 
  86. {    
  87.     rPCONP |= 0x1<<24;    //使能UART2功率控制 
  88.      
  89.     rIOCON_P0_10 = (rIOCON_P0_10 & (~0x7)) | 0x1;   //P0.10 P0.11做UART2的發送和接收管腳 
  90.     rIOCON_P0_11 = (rIOCON_P0_11 & (~0x7)) | 0x1; 
  91.  
  92.     rU2LCR |= 0x1<<7;     //DLAB=1 
  93.     rU2FDR = 1 | 2<<4;    //波特率設置115200 
  94.     rU2DLM = 0; 
  95.     rU2DLL = 22; 
  96.     rU2LCR &= ~(0x1<<7);  //DLAB=0 
  97.     rU2LCR |= 0x3;          //8位數據位,無校驗,1個停止位 
  98.      
  99.     rU2TER |= 0x1<<7;     //使能串口2的發送 
  100.      
  101.     rU2IER |= 0x1;          //使能串口2的接收中斷 
  102.     rU2FCR |= 0x1;          //復位FIFO,設置接收1個字符觸發中斷 
  103.     rU2FCR |= 0x1<<1 | 0x1<<2; 
  104.     rISER0 |= 0x1<<7;     //使能串口2中斷 
  105.      
  106.  
  107. void Uart2SendC(char c) 
  108.     rU2THR = c & 0xff; 
  109.     while(!(rU2LSR&(0x1<<5)));    //等待rU2THR中的數據發送完成,防止數據溢出 
  110.  
  111. void Uart2SendS(char *s) 
  112.     while(*s) 
  113.     { 
  114.         Uart2SendC(*s); 
  115.         s++; 
  116.     } 
  117.  
  118. int main(void
  119.     char str[] = {"\n\r1, Display the U2IIR[3:0] + Data + U2IIR[3:0]\n\r2, Send 0x5a ---> Turn on the LED\n\r3, Send 0xa5 --->Turn off the LED\n\r"}; 
  120.     rFIO1DIR |= (1<<18); //GPIO1.18 -> OUTPUT 
  121.     Init_Uart2(); 
  122.     Uart2SendS(str); 
  123.     while(1); 
#define CCLK		120000000
#define PCLK		 60000000

#define rFIO1DIR	(*(volatile unsigned*)(0x20098020))
#define rFIO1MASK 	(*(volatile unsigned*)(0x20098030))
#define rFIO1PIN	(*(volatile unsigned*)(0x20098034))
#define rFIO1SET	(*(volatile unsigned*)(0x20098038))
#define rFIO1CLR	(*(volatile unsigned*)(0x2009803c))

#define rISER0  	(*(volatile unsigned*)(0xE000E100))

#define rCLKSRCSEL  (*(volatile unsigned *)(0x400FC10C))     //時鍾源選擇寄存器  
#define rPLL0CON    (*(volatile unsigned *)(0x400FC080))     //PLL0控制寄存器  
#define rPLL0CFG    (*(volatile unsigned *)(0x400FC084))     //PLL0配置寄存器  
#define rPLL0STAT   (*(volatile unsigned *)(0x400FC088))     //PLL0狀態寄存器  
#define rPLL0FEED   (*(volatile unsigned *)(0x400FC08C))     //PLL0饋送寄存器  
#define rPLL1CON    (*(volatile unsigned *)(0x400FC0A0))       
#define rPLL1CFG    (*(volatile unsigned *)(0x400FC0A4))  
#define rPLL1STAT   (*(volatile unsigned *)(0x400FC0A8))  
#define rPLL1FEED   (*(volatile unsigned *)(0x400FC0AC))  
#define rCCLKSEL    (*(volatile unsigned *)(0x400FC104))     //CPU時鍾選擇寄存器  
#define rUSBCLKSEL  (*(volatile unsigned *)(0x400FC108))     //USB時鍾選擇寄存器  
#define rPCLKSEL    (*(volatile unsigned *)(0x400FC1A8))     //外設時鍾寄存器  
#define rPCON       (*(volatile unsigned *)(0x400FC0C0))  
#define rPXCONP     (*(volatile unsigned *)(0x400FC0C4))  
#define rSCS        (*(volatile unsigned *)(0x400FC1A0))     //系統控制和狀態寄存器  
#define rCLKOUTCFG  (*(volatile unsigned *)(0x400FC1C8))

#define rIOCON_P0_10	(*(volatile unsigned *)(0x4002C028))
#define rIOCON_P0_11	(*(volatile unsigned *)(0x4002C02C))
#define rPCONP		(*(volatile unsigned *)(0x400FC0C4))
#define rU2LCR  	(*(volatile unsigned *)(0x4009800C))
#define rU2FDR		(*(volatile unsigned *)(0x40098028))
#define rU2DLL		(*(volatile unsigned *)(0x40098000))
#define rU2DLM		(*(volatile unsigned *)(0x40098004))
#define rU2TER		(*(volatile unsigned *)(0x40098030))
#define rU2THR		(*(volatile unsigned *)(0x40098000))
#define rU2RBR		(*(volatile unsigned *)(0x40098000))
#define rU2FCR		(*(volatile unsigned *)(0x40098008))
#define rU2IIR		(*(volatile unsigned *)(0x40098008))
#define rU2LSR		(*(volatile unsigned *)(0x40098014))
#define rU2IER		(*(volatile unsigned *)(0x40098004))
#define rU2ACR		(*(volatile unsigned *)(0x40098020))

void UART2_IRQHandler()
{
	unsigned int intId;
	char tmp_char;
	
	intId = rU2IIR&0xf;
	rU2THR = intId;
	
	if(intId == 0xc || intId == 0x4)	//RDA或者CTI中斷
	{
		rU2LCR &= ~(0x1<<7);	//DLAB=0
		tmp_char = rU2RBR&0xff;
		rU2THR = tmp_char;
	}
	intId = rU2IIR&0xf;
	rU2THR = intId;

		
	if(tmp_char == 0xa5)
		rFIO1PIN |= (1<<18);
	else if(tmp_char == 0x5a)
		rFIO1PIN &= ~(1<<18);
}
	
void SystemInit()  
{  
    rSCS &= ~(0x1<<4);            //頻率12M  
    rSCS |= (0x1<<5);             //使能主振盪器  
    while(0 == (rSCS & (0x1<<6)));//等待主振盪器穩定  
      
    rCLKSRCSEL = 0x1;  
      
    rPLL0CFG = 0x9;                 //配置CCLK = 120M  
    rPLL0CON = 0x01;  
    rPLL0FEED = 0xAA;  
    rPLL0FEED =0x55;  
    while(0 == (rPLL0STAT & (0x1<<10)));   
      
    rCCLKSEL = (0x1 | (0x1<<8));  
    rPCLKSEL = 0x2;                 //配置PCLK = 60M   
    rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);  
}

void Init_Uart2()
{	
	rPCONP |= 0x1<<24;  	//使能UART2功率控制
	
	rIOCON_P0_10 = (rIOCON_P0_10 & (~0x7)) | 0x1;	//P0.10 P0.11做UART2的發送和接收管腳
	rIOCON_P0_11 = (rIOCON_P0_11 & (~0x7)) | 0x1;

	rU2LCR |= 0x1<<7;		//DLAB=1
	rU2FDR = 1 | 2<<4;  	//波特率設置115200
	rU2DLM = 0;
	rU2DLL = 22;
	rU2LCR &= ~(0x1<<7);	//DLAB=0
	rU2LCR |= 0x3;  		//8位數據位,無校驗,1個停止位
	
	rU2TER |= 0x1<<7;		//使能串口2的發送
	
	rU2IER |= 0x1;  		//使能串口2的接收中斷
	rU2FCR |= 0x1;  		//復位FIFO,設置接收1個字符觸發中斷
	rU2FCR |= 0x1<<1 | 0x1<<2;
	rISER0 |= 0x1<<7;		//使能串口2中斷
	
}

void Uart2SendC(char c)
{
	rU2THR = c & 0xff;
	while(!(rU2LSR&(0x1<<5)));  	//等待rU2THR中的數據發送完成,防止數據溢出
}

void Uart2SendS(char *s)
{
	while(*s)
	{
		Uart2SendC(*s);
		s++;
	}
}

int main(void)
{
	char str[] = {"\n\r1, Display the U2IIR[3:0] + Data + U2IIR[3:0]\n\r2, Send 0x5a ---> Turn on the LED\n\r3, Send 0xa5 --->Turn off the LED\n\r"};
	rFIO1DIR |= (1<<18); //GPIO1.18 -> OUTPUT
	Init_Uart2();
	Uart2SendS(str);
	while(1);
}

        運行結果如下圖所示

uart

        串口調試軟件下載點擊我下載


免責聲明!

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



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