2回答

1收藏

【赚周年币】技术帖Week3-Day1——LPC824 Breakout之15、UART0、1、2

#线上活动 #线上活动 3874 人阅读 | 2 人回复 | 2017-01-15

本帖最后由 toofree 于 2017-1-19 03:22 编辑

        【赚周年币】技术帖Week3-Day1——LPC824 Breakout之15、UART0、1、2

        本贴测试程序,以上一贴最后上传压缩包做主工程模板。参见贴子最末尾的附件。
        【赚周年币】技术帖Week2-Day7——LPC824 Breakout之14、SPI NOKIA5110https://www.cirmall.com/bbs/forum ... 63170&fromuid=17147
        

        当然以其它之前的帖子为模板也可以,比如,【赚周年币】技术帖Week1-Day4——LPC824 Breakout之四,串口printfhttps://www.cirmall.com/bbs/forum ... 59498&fromuid=17147
        但是不能再早了,因为本帖会用到修改过的“user_bsp\src\Keil_Retarget1.c”文件。之所以要以上一贴压缩包为模板,只是因为不想重新解压压缩包,而只在本人电脑原有测试模板上修改增加。

        复制上一贴的“LPC824_Example_Code_Bundle_Keil_r1.0\Shared_Project_Source_Code\Example_USART1M_USART2S”工程,改名为“Example_USART1M_USART2S_TEST”,其它文件及文件夹,也相应改名。方法及注意事项,参考之前贴子。
        把原工程中的“Keil_Retarget.c”文件,替换为“Shared_Project_Source_Code\user_bsp\src\Keil_Retarget1.c”。把工程中程序文件中所有“\n\r”,全部改为“\r\n”,不要问为什么,地球人都知道。最后工程视图如下:
        


        首先我们来看两个时钟框图。UM10800.pdf第184页如下图:
        

        
        UM10800.pdf第30页如下图:
      


        其中由system clock来的时钟,作为UART模块内核逻辑工程时钟;从main clock来的U_PCLK用于波特率生成。
        同步模式和异步模式的波特率计算方式不同,同步模式波特是异步的16倍。异步模式是用16倍时钟来采样每一位数据的,而同步模式是在同步时钟的作用下同步采样,不需要采样误差调整。这在数据手册中有体现。
        

        在程序中注释部分也有说明。“Serial.c”中注释如下:
        


        “Example_USART1M_USART2S_TEST.c”中注释如下:
        
  1. // Configure the UARTCLKDIV, default for calculation below is same as AHBCLKDIV
  2.         LPC_SYSCON->UARTCLKDIV = LPC_SYSCON->SYSAHBCLKDIV;

  3.   // Configure the FRG (default for calculation below is divide-by-1)
  4.   LPC_SYSCON->UARTFRGMULT = 0;
  5.   LPC_SYSCON->UARTFRGDIV = 255;
复制代码
以上这三条语句,决定了,U_PCLK时钟与SystemCoreClock系统时钟频率相等,都是30MHz。
        串口0的BRG寄存器很容易算出,LPC_USART0->BRG = (SystemCoreClock / (16 * desired_baud)) - 1; BRG == (30000000 / (16*115200) - 1) == 15
        串口1、2的BRG寄存器值计算,LPC_USART1->BRG = (U_PCLK/desired_baud)-1 ; BRG == (30000000 / 115200) - 1 == 259
        串口0异步模式配置寄存器设置
  1. // Configure the USART0 CFG register:
  2.   // 8 data bits, no parity, one stop bit, no flow control, asynchronous mode
  3.   LPC_USART0->CFG = DATA_LENG_8|PARITY_NONE|STOP_BIT_1;
复制代码
串口1、2同步模式配置寄存器设置
  1.   // Configure the USART1 CFG register:
  2.   // 8 data bits, no parity, one stop bit, no flow control, synchronous mode, sample on falling edges, master mode, no loop-back
  3.   LPC_USART1->CFG = DATA_LENG_8|PARITY_NONE|STOP_BIT_1|SYNC_EN|SYNC_MS;
复制代码
其它设置串口0、1、2几乎相同。
       在主程序中,开启了UART2接收中断。主程序中,UART1给UART2发数,UART2中断接收,UART0作为标准打印串口。UART1与UART2之间,收发管脚P0_13、P0_14相当于已经内部连接,而仅仅需要把UART1的同步串行时钟输出管脚P0_24,与UART2的串行时钟输入管脚P0_25,外部短接,即可完成UART1到UART2的数据传送。

        编译、下载程序、复位全速运行,在串口终端收发数据,得到预期实验结果。
        


        测试还没有完噢,我们照猫画虎,把UART1、UART2改为异步模式,UART1、UART2分别互相收发试试。
        修改后的主程序“Example_USART1M_USART2S_TEST.c”文件
  1. /*
  2. ===============================================================================
  3. Name        : Example_USART1M_USART2S.c
  4. Author      : $(author)
  5. Version     :
  6. Copyright   : $(copyright)
  7. Description : main definition
  8. ===============================================================================
  9. */

  10. //#ifdef __USE_CMSIS
  11. #include "LPC8xx.h"
  12. //#endif

  13. //#include <cr_section_macros.h>

  14. #include <stdio.h>

  15. #include "lpc8xx_swm.h"
  16. #include "lpc8xx_syscon.h"
  17. #include "lpc8xx_uart.h"
  18. #include "utilities.h"

  19. extern void setup_debug_uart(void);

  20. volatile enum {false, true} handshake1,handshake2;
  21. volatile unsigned char RX1_Buffer[32],RX2_Buffer[32];
  22. char thestring[32];
  23. char * tx_ptr;

  24. int main(void) {
  25.   uint32_t temp;

  26.   // Configure the debug uart (see Serial.c)
  27.   setup_debug_uart();

  28. // Configure USART1 as master, USART2 as slave
  29. // Bit rate = 115,200 b.p.s
  30. // 8 data bits
  31. // No parity
  32. // 1 stop bit

  33. // UARTCLKDIV, FRG, and BRG calculation
  34. // For synchronous mode, the formula is
  35. // BRG + 1 = MainClk * (1/baud) * (1/(1+(frgmult/frgdiv))) * (1/UARTCLKDIV)
  36. // main clock = 60 MHz want baudrate = 115,200 Hz
  37. // Use UARTCLKDIV = divide-by-2, FRG = 1
  38. // Then the formula is (BRG + 1) = (main clock / 2*baudrate) = 260.4
  39. // So use BRG = 259


  40. // SWM settings for USART1 (master):
  41. // P0.12 = U1_SCLK
  42. // P0.13 = U1_TXD
  43. // P0.14 = U1_RXD
  44. //
  45. // SWM settings for USART2 (slave):
  46. // P0.15 = U2_SCLK (requires external connection from P0.12)
  47. // P0.13 = U2_RXD
  48. // P0.14 = U2_TXD

  49.   // Enable clocks to USARTs 1, 2, SWM
  50.   LPC_SYSCON->SYSAHBCLKCTRL |= (UART1 | UART2 | SWM);

  51.   // Configure the SWM (see utilities_lib and lpc8xx_swm.h)
  52.   //ConfigSWM(U1_SCLK, P0_24);
  53.   ConfigSWM(U1_TXD, P0_13);
  54.   ConfigSWM(U1_RXD, P0_14);

  55.   //ConfigSWM(U2_SCLK, P0_25);
  56.   ConfigSWM(U2_RXD, P0_13);
  57.   ConfigSWM(U2_TXD, P0_14);

  58.   // Configure the UARTCLKDIV
  59.   //LPC_SYSCON->UARTCLKDIV = 2;

  60.   // Configure the FRG
  61.   LPC_SYSCON->UARTFRGMULT = 0;
  62.   LPC_SYSCON->UARTFRGDIV = 255;

  63.   // Setup USART1 ...
  64.   // Give USART1 a reset
  65.   LPC_SYSCON->PRESETCTRL &= (UART1_RST_N);
  66.   LPC_SYSCON->PRESETCTRL |= ~(UART1_RST_N);

  67.   // Configure the USART1 baud rate generator (value written to BRG divides by value+1)
  68.   //LPC_USART1->BRG = 259;
  69.         LPC_USART1->BRG = 15;

  70.   // Configure the USART1 CFG register:
  71.   // 8 data bits, no parity, one stop bit, no flow control, synchronous mode, sample on falling edges, master mode, no loop-back
  72.   //LPC_USART1->CFG = DATA_LENG_8|PARITY_NONE|STOP_BIT_1|SYNC_EN|SYNC_MS;
  73.         // 8 data bits, no parity, one stop bit, no flow control, asynchronous mode
  74.   LPC_USART1->CFG = DATA_LENG_8|PARITY_NONE|STOP_BIT_1;

  75.   // Configure the USART1 CTL register (nothing to be done here)
  76.   // No continuous break, no address detect, no Tx disable, no CC, no CLRCC
  77.   LPC_USART1->CTL = 0;

  78.   // Clear any pending flags (Just to be safe, isn't necessary after the peripheral reset)
  79.   LPC_USART1->STAT = 0xFFFF;
  80.         
  81.         // Enable the UART2 RX Ready Interrupt
  82.   LPC_USART1->INTENSET = RXRDY;
  83.   NVIC_EnableIRQ(UART1_IRQn);


  84.   // Enable USART1
  85.   LPC_USART1->CFG |= UART_EN;



  86.   // Setup USART2 ...
  87.   // Give USART2 a reset
  88.   LPC_SYSCON->PRESETCTRL &= (UART2_RST_N);
  89.   LPC_SYSCON->PRESETCTRL |= ~(UART2_RST_N);

  90.   // Configure the baud rate generator (value written to BRG divides by value+1)
  91.   //LPC_USART2->BRG = 259;
  92.         LPC_USART2->BRG = 15;

  93.   // Configure the USART2 CFG register:
  94.   // 8 data bits, no parity, one stop bit, no flow control, synchronous mode, sample on falling edges, slave mode, no loop-back
  95.   //LPC_USART2->CFG = DATA_LENG_8|PARITY_NONE|STOP_BIT_1|SYNC_EN;
  96.         // 8 data bits, no parity, one stop bit, no flow control, asynchronous mode
  97.   LPC_USART2->CFG = DATA_LENG_8|PARITY_NONE|STOP_BIT_1;

  98.   // Configure the USART2 CTL register (nothing to be done here)
  99.   // No continuous break, no address detect, no Tx disable, no CC, no CLRCC
  100.   LPC_USART2->CTL = 0;

  101.   // Clear any pending flags (Just to be safe, isn't necessary after the peripheral reset)
  102.   LPC_USART2->STAT = 0xFFFF;

  103.   // Enable the UART2 RX Ready Interrupt
  104.   LPC_USART2->INTENSET = RXRDY;
  105.   NVIC_EnableIRQ(UART2_IRQn);

  106.   // Enable USART2
  107.   LPC_USART2->CFG |= UART_EN;


  108.   while (1) {

  109.     GetConsoleString(thestring);  // See utilities_lib
  110.     printf("Characters to be transmitted are: %s\r\n", thestring);

  111.     tx_ptr = &thestring[0];
  112.     handshake1 = false;
  113.                 handshake2 = false;

  114.     do {
  115.       temp = *tx_ptr++;
  116.       // Wait for TXRDY on USART1
  117.       while (((LPC_USART1->STAT) & (1<<2)) == 0);
  118.       // Write the current character to the USART1 TXDAT  register
  119.       LPC_USART1->TXDAT  = temp;
  120.     } while (temp != 0);


  121.     // Wait for handshake from ISR
  122.     while(handshake2 == false);

  123.     // Echo the string received by USART2 back to the console
  124.     printf("Characters received UART2 were: %s\r\n", RX2_Buffer);
  125.                
  126.                 tx_ptr = RX2_Buffer;
  127.                 do {
  128.       temp = *tx_ptr++;
  129.       // Wait for TXRDY on USART2
  130.       while (((LPC_USART2->STAT) & (1<<2)) == 0);
  131.       // Write the current character to the USART1 TXDAT  register
  132.       LPC_USART2->TXDAT  = temp;
  133.     } while (temp != 0);


  134.     // Wait for handshake from ISR
  135.     while(handshake1 == false);      //有错误,更正。之前为handshake2

  136.     // Echo the string received by USART1 back to the console
  137.     printf("Characters received UART1 were: %s\r\n", RX1_Buffer);

  138.   } // end of while 1

  139. } // end of main
复制代码
修改后的中断处理函数“Example_USART1M_USART2S_TEST_ISR.c”文件。
  1. /*
  2. * Example_USART1M_USART2S_ISR.c
  3. */

  4. #include "LPC8xx.h"

  5. extern volatile unsigned char RX1_Buffer[32],RX2_Buffer[32];
  6. extern volatile enum {false, true} handshake1,handshake2;
  7. static uint32_t interrupt_counter2 = 0,interrupt_counter1 = 0;

  8. /*****************************************************************************
  9. ** Function name:                UART2_IRQHandler
  10. **
  11. ** Description:                    UART2 interrupt service routine
  12. **
  13. ** parameters:                        None
  14. ** Returned value:                None
  15. **
  16. *****************************************************************************/
  17. void UART2_IRQHandler() {
  18.   unsigned char temp;

  19.   temp = LPC_USART2->RXDAT ;
  20.   RX2_Buffer[interrupt_counter2] = temp;

  21.   if (temp == 0) { // NULL string terminator is current character
  22.     handshake2 = true;
  23.     interrupt_counter2 = 0;
  24.   }
  25.   else {
  26.     interrupt_counter2++;
  27.   }

  28.   return;
  29. }

  30. /*****************************************************************************
  31. ** Function name:                UART2_IRQHandler
  32. **
  33. ** Description:                    UART2 interrupt service routine
  34. **
  35. ** parameters:                        None
  36. ** Returned value:                None
  37. **
  38. *****************************************************************************/
  39. void UART1_IRQHandler() {
  40.   unsigned char temp;

  41.   temp = LPC_USART1->RXDAT ;
  42.   RX1_Buffer[interrupt_counter1] = temp;

  43.   if (temp == 0) { // NULL string terminator is current character
  44.     handshake1 = true;
  45.     interrupt_counter1 = 0;
  46.   }
  47.   else {
  48.     interrupt_counter1++;
  49.   }

  50.   return;
  51. }
复制代码
重新编译、下载程序、复位全速运行,在串口终端收发数据,得到预期实验结果。
        


        依照惯例, 修改后工程文件打包附上。
        
LPC824_Example_Code_Bundle_Keil_r1.0(201701160146).rar (3.36 MB, 下载次数: 38)
关注下面的标签,发现更多相似文章

评分

参与人数 2 +35 收起 理由
EEboard爱板网 + 5 3周发帖养成记 奖励
loveeeboard + 30

查看全部评分

分享到:
回复

使用道具 举报

回答|共 2 个

倒序浏览

沙发

海迹天涯

发表于 2017-1-16 10:54:55 | 只看该作者

学习学习
板凳

toofree

发表于 2017-1-16 23:25:27 | 只看该作者

        主程序“Example_USART1M_USART2S_TEST.c”文件,178行代码有问题。
        

        应该改为,while(handshake1 == false);
        SWM配置串口管脚部分,作修改,改为如下代码:
  1.   ConfigSWM(U1_TXD, P0_25);
  2.   ConfigSWM(U1_RXD, P0_26);

  3.   ConfigSWM(U2_TXD, P0_27);
  4.   ConfigSWM(U2_RXD, P0_28);  
复制代码
然后在外部将P0_25、P026分别与P0_28、P0_27连接,那么就在外部构成了UART1、UART2互相收发。经验证,一切正常。
   
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

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