查看: 4111|回复: 1

[原创] 【我要分享】Cortex-M3 (NXP LPC1788)之UART用法

[复制链接]

该用户从未签到

17

主题

32

帖子

0

注册会员

Rank: 2

积分
85
最后登录
2018-6-13
发表于 2017-2-27 08:50:41 | 显示全部楼层 |阅读模式
在工作中经常将平台的串口和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。计数公式如下图。

01.jpg

根据计算,当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.     {
  47.         unsigned int intId;
  48.         char tmp_char;
  49.          
  50.         intId = rU2IIR&0xf;
  51.         rU2THR = intId;
  52.          
  53.         if(intId == 0xc || intId == 0x4)    //RDA或者CTI中断
  54.         {
  55.             rU2LCR &= ~(0x1<<7);  //DLAB=0
  56.             tmp_char = rU2RBR&0xff;
  57.             rU2THR = tmp_char;
  58.         }
  59.         intId = rU2IIR&0xf;
  60.         rU2THR = intId;
  61.      
  62.             
  63.         if(tmp_char == 0xa5)
  64.             rFIO1PIN |= (1<<18);
  65.         elseif(tmp_char == 0x5a)
  66.             rFIO1PIN &= ~(1<<18);
  67.     }
  68.          
  69.     void SystemInit()   
  70.     {   
  71.         rSCS &= ~(0x1<<4);            //频率12M   
  72.         rSCS |= (0x1<<5);             //使能主振荡器   
  73.         while(0 == (rSCS & (0x1<<6)));//等待主振荡器稳定   
  74.            
  75.         rCLKSRCSEL = 0x1;   
  76.            
  77.         rPLL0CFG = 0x9;                 //配置CCLK = 120M   
  78.         rPLL0CON = 0x01;   
  79.         rPLL0FEED = 0xAA;   
  80.         rPLL0FEED =0x55;   
  81.         while(0 == (rPLL0STAT & (0x1<<10)));   
  82.            
  83.         rCCLKSEL = (0x1 | (0x1<<8));   
  84.         rPCLKSEL = 0x2;                 //配置PCLK = 60M   
  85.         rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);   
  86.     }
  87.      
  88.     void Init_Uart2()
  89.     {   
  90.         rPCONP |= 0x1<<24;    //使能UART2功率控制
  91.          
  92.         rIOCON_P0_10 = (rIOCON_P0_10 & (~0x7)) | 0x1;   //P0.10 P0.11做UART2的发送和接收管脚
  93.         rIOCON_P0_11 = (rIOCON_P0_11 & (~0x7)) | 0x1;
  94.      
  95.         rU2LCR |= 0x1<<7;     //DLAB=1
  96.         rU2FDR = 1 | 2<<4;    //波特率设置115200
  97.         rU2DLM = 0;
  98.         rU2DLL = 22;
  99.         rU2LCR &= ~(0x1<<7);  //DLAB=0
  100.         rU2LCR |= 0x3;          //8位数据位,无校验,1个停止位
  101.          
  102.         rU2TER |= 0x1<<7;     //使能串口2的发送
  103.          
  104.         rU2IER |= 0x1;          //使能串口2的接收中断
  105.         rU2FCR |= 0x1;          //复位FIFO,设置接收1个字符触发中断
  106.         rU2FCR |= 0x1<<1 | 0x1<<2;
  107.         rISER0 |= 0x1<<7;     //使能串口2中断
  108.          
  109.     }
  110.      
  111.     void Uart2SendC(char c)
  112.     {
  113.         rU2THR = c & 0xff;
  114.         while(!(rU2LSR&(0x1<<5)));    //等待rU2THR中的数据发送完成,防止数据溢出
  115.     }
  116.      
  117.     void Uart2SendS(char *s)
  118.     {
  119.         while(*s)
  120.         {
  121.             Uart2SendC(*s);
  122.             s++;
  123.         }
  124.     }
  125.      
  126.     int main(void)
  127.     {
  128.         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"};
  129.         rFIO1DIR |= (1<<18); //GPIO1.18 -> OUTPUT
  130.         Init_Uart2();
  131.         Uart2SendS(str);
  132.         while(1);
  133.     }
复制代码
  1. #define CCLK                120000000
  2. #define PCLK                 60000000

  3. #define rFIO1DIR        (*(volatile unsigned*)(0x20098020))
  4. #define rFIO1MASK         (*(volatile unsigned*)(0x20098030))
  5. #define rFIO1PIN        (*(volatile unsigned*)(0x20098034))
  6. #define rFIO1SET        (*(volatile unsigned*)(0x20098038))
  7. #define rFIO1CLR        (*(volatile unsigned*)(0x2009803c))

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

  9. #define rCLKSRCSEL  (*(volatile unsigned *)(0x400FC10C))     //时钟源选择寄存器  
  10. #define rPLL0CON    (*(volatile unsigned *)(0x400FC080))     //PLL0控制寄存器  
  11. #define rPLL0CFG    (*(volatile unsigned *)(0x400FC084))     //PLL0配置寄存器  
  12. #define rPLL0STAT   (*(volatile unsigned *)(0x400FC088))     //PLL0状态寄存器  
  13. #define rPLL0FEED   (*(volatile unsigned *)(0x400FC08C))     //PLL0馈送寄存器  
  14. #define rPLL1CON    (*(volatile unsigned *)(0x400FC0A0))      
  15. #define rPLL1CFG    (*(volatile unsigned *)(0x400FC0A4))  
  16. #define rPLL1STAT   (*(volatile unsigned *)(0x400FC0A8))  
  17. #define rPLL1FEED   (*(volatile unsigned *)(0x400FC0AC))  
  18. #define rCCLKSEL    (*(volatile unsigned *)(0x400FC104))     //CPU时钟选择寄存器  
  19. #define rUSBCLKSEL  (*(volatile unsigned *)(0x400FC108))     //USB时钟选择寄存器  
  20. #define rPCLKSEL    (*(volatile unsigned *)(0x400FC1A8))     //外设时钟寄存器  
  21. #define rPCON       (*(volatile unsigned *)(0x400FC0C0))  
  22. #define rPXCONP     (*(volatile unsigned *)(0x400FC0C4))  
  23. #define rSCS        (*(volatile unsigned *)(0x400FC1A0))     //系统控制和状态寄存器  
  24. #define rCLKOUTCFG  (*(volatile unsigned *)(0x400FC1C8))

  25. #define rIOCON_P0_10        (*(volatile unsigned *)(0x4002C028))
  26. #define rIOCON_P0_11        (*(volatile unsigned *)(0x4002C02C))
  27. #define rPCONP                (*(volatile unsigned *)(0x400FC0C4))
  28. #define rU2LCR          (*(volatile unsigned *)(0x4009800C))
  29. #define rU2FDR                (*(volatile unsigned *)(0x40098028))
  30. #define rU2DLL                (*(volatile unsigned *)(0x40098000))
  31. #define rU2DLM                (*(volatile unsigned *)(0x40098004))
  32. #define rU2TER                (*(volatile unsigned *)(0x40098030))
  33. #define rU2THR                (*(volatile unsigned *)(0x40098000))
  34. #define rU2RBR                (*(volatile unsigned *)(0x40098000))
  35. #define rU2FCR                (*(volatile unsigned *)(0x40098008))
  36. #define rU2IIR                (*(volatile unsigned *)(0x40098008))
  37. #define rU2LSR                (*(volatile unsigned *)(0x40098014))
  38. #define rU2IER                (*(volatile unsigned *)(0x40098004))
  39. #define rU2ACR                (*(volatile unsigned *)(0x40098020))

  40. void UART2_IRQHandler()
  41. {
  42.         unsigned int intId;
  43.         char tmp_char;
  44.        
  45.         intId = rU2IIR&0xf;
  46.         rU2THR = intId;
  47.        
  48.         if(intId == 0xc || intId == 0x4)        //RDA或者CTI中断
  49.         {
  50.                 rU2LCR &= ~(0x1<<7);        //DLAB=0
  51.                 tmp_char = rU2RBR&0xff;
  52.                 rU2THR = tmp_char;
  53.         }
  54.         intId = rU2IIR&0xf;
  55.         rU2THR = intId;

  56.                
  57.         if(tmp_char == 0xa5)
  58.                 rFIO1PIN |= (1<<18);
  59.         else if(tmp_char == 0x5a)
  60.                 rFIO1PIN &= ~(1<<18);
  61. }
  62.        
  63. void SystemInit()  
  64. {  
  65.     rSCS &= ~(0x1<<4);            //频率12M  
  66.     rSCS |= (0x1<<5);             //使能主振荡器  
  67.     while(0 == (rSCS & (0x1<<6)));//等待主振荡器稳定  
  68.       
  69.     rCLKSRCSEL = 0x1;  
  70.       
  71.     rPLL0CFG = 0x9;                 //配置CCLK = 120M  
  72.     rPLL0CON = 0x01;  
  73.     rPLL0FEED = 0xAA;  
  74.     rPLL0FEED =0x55;  
  75.     while(0 == (rPLL0STAT & (0x1<<10)));   
  76.       
  77.     rCCLKSEL = (0x1 | (0x1<<8));  
  78.     rPCLKSEL = 0x2;                 //配置PCLK = 60M   
  79.     rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);  
  80. }

  81. void Init_Uart2()
  82. {       
  83.         rPCONP |= 0x1<<24;          //使能UART2功率控制
  84.        
  85.         rIOCON_P0_10 = (rIOCON_P0_10 & (~0x7)) | 0x1;        //P0.10 P0.11做UART2的发送和接收管脚
  86.         rIOCON_P0_11 = (rIOCON_P0_11 & (~0x7)) | 0x1;

  87.         rU2LCR |= 0x1<<7;                //DLAB=1
  88.         rU2FDR = 1 | 2<<4;          //波特率设置115200
  89.         rU2DLM = 0;
  90.         rU2DLL = 22;
  91.         rU2LCR &= ~(0x1<<7);        //DLAB=0
  92.         rU2LCR |= 0x3;                  //8位数据位,无校验,1个停止位
  93.        
  94.         rU2TER |= 0x1<<7;                //使能串口2的发送
  95.        
  96.         rU2IER |= 0x1;                  //使能串口2的接收中断
  97.         rU2FCR |= 0x1;                  //复位FIFO,设置接收1个字符触发中断
  98.         rU2FCR |= 0x1<<1 | 0x1<<2;
  99.         rISER0 |= 0x1<<7;                //使能串口2中断
  100.        
  101. }

  102. void Uart2SendC(char c)
  103. {
  104.         rU2THR = c & 0xff;
  105.         while(!(rU2LSR&(0x1<<5)));          //等待rU2THR中的数据发送完成,防止数据溢出
  106. }

  107. void Uart2SendS(char *s)
  108. {
  109.         while(*s)
  110.         {
  111.                 Uart2SendC(*s);
  112.                 s++;
  113.         }
  114. }

  115. int main(void)
  116. {
  117.         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"};
  118.         rFIO1DIR |= (1<<18); //GPIO1.18 -> OUTPUT
  119.         Init_Uart2();
  120.         Uart2SendS(str);
  121.         while(1);
  122. }
复制代码


运行结果如下图所示
02.jpg

串口调试软件下载   地址


回复

使用道具 举报

该用户从未签到

1

主题

83

帖子

0

注册会员

Rank: 2

积分
179
最后登录
1970-1-1
发表于 2017-2-27 11:08:20 | 显示全部楼层
看看
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-7-18 09:26 , Processed in 0.090977 second(s), 23 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表