• (转)CortexM3 (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

            串口调试软件下载点击我下载

  • 相关阅读:
    FineReport 子窗口刷新父页面
    Swagger rest API 描述
    maven properties 动态转换
    elasticsearch postman操作
    学习网站
    python | 干货:VSCode 13款插件和8个快捷键,工作效率提升10倍
    python | 5大SQL数据清洗方法
    python | 阿里云发短信教程详细(2) -Python3
    python | 阿里云短信发送服务
    python | Linux各目录及每个目录的详细介绍
  • 原文地址:https://www.cnblogs.com/tdyizhen1314/p/2704590.html
Copyright © 2020-2023  润新知