查看: 3576|回复: 1

[原创] 【IRD-LPC1768-DEV】UART_RS232

[复制链接]
  • TA的每日心情
    无聊
    2021-12-29 19:06
  • 签到天数: 47 天

    连续签到: 1 天

    [LV.5]常住居民I

    49

    主题

    188

    帖子

    21

    金牌会员

    Rank: 6Rank: 6

    积分
    1392
    最后登录
    2025-3-4
    发表于 2019-2-26 11:27:28 | 显示全部楼层 |阅读模式
    本帖最后由 day_day 于 2019-2-26 11:29 编辑

    (一)
    这个板子做RS232,实际上说到底就是一个UART而已,RS232是硬件已经实现好TTL转RS232了,不需要软件端操心。


    (二)接口定义
    11.png



    (三)端口初始化
    首先设置复用:
    31.png


    都是第二个映射

    1. void UartGPIOInit(void)
    2. {
    3.         //LPC_PINCON->PINSEL0 |= 0x00000050;
    4.         PIN_Configure(0, 2, PIN_FUNC_1, PIN_PINMODE_PULLUP, PIN_PINMODE_PULLUP);
    5.         PIN_Configure(0, 3, PIN_FUNC_1, PIN_PINMODE_PULLUP, PIN_PINMODE_PULLUP);
    6. }
    复制代码


    我是用PIN_Configure设置,一开始打算直接操作寄存器,但想了想还是不怎么明了


    (四)UART设置
    UART相关寄存器:
    41.png


    主要是波特率设置的两个寄存器:DLL、DLM
    此外还有一个配置寄存器,用于配置奇偶校核位之类的东西,还有锁住波特率设置的两个寄存器的标志位:LCR
    波特率设置实际上困扰了我一阵子
    1. uint16_t usFdiv = ((SystemCoreClock/4)/16)/bps;
    复制代码


    SystemCoreClock/4是uart0总线时钟,在时钟树上面有相关的位配置。 22.png
    21.png
    但为何要/16让我有些疑惑,后来才发现发送一个字节需要16个位,前8个是一个字节里面的八个位,后面是一些奇偶校核之类的,详见:
    串口、波特率等概念


    1. LPC_UART0->LCR = 0x83;                                        //使能访问除数锁存器,8 bits, no Parity, 1 Stop bit     */
    2.   LPC_UART0->DLM = usFdiv / 256;        //初始化波特率                   */
    3.   LPC_UART0->DLL = usFdiv % 256;
    4.   LPC_UART0->LCR = 0x03;                                        //禁止访问除数锁存器,锁定波特率
    5.         
    复制代码


    这样就基本可以正常通讯了,使用函数:
    1. int sendchar (int ch)  {                 /* Write character to Serial Port    */

    2.   while (!(LPC_UART0->LSR & 0x20));

    3.   return (LPC_UART0->THR = ch);
    4. }
    复制代码


    (四)重定向

    加入头文件stdio.h

    1. #pragma import(__use_no_semihosting)            
    2. //标准库需要的支持函数                 
    3. struct __FILE { int handle; };        /* Add whatever you need here */
    4. FILE __stdout;

    5. FILE __stdout;      

    6. //定义_sys_exit()以避免使用半主机模式   
    7. void _sys_exit(int return_code) {
    8. label:  goto label;  /* endless loop */
    9. }

    10. //重定义fputc函数
    11. int fputc(int ch, FILE *f) {
    12.   return (sendchar(ch));
    13. }
    复制代码






    (五)UART设置
    以上是非常基本的UART配置,只能用于基本的阻塞通讯,要想启动中断,还需要配置IER寄存器和使能NVIC

    1. LPC_UART0->FCR  = 0x00;                 //禁止FIFO
    2.         NVIC_ClearPendingIRQ(UART0_IRQn);
    3.         NVIC_SetPriority(UART0_IRQn, 0);
    4.         NVIC_EnableIRQ(UART0_IRQn);              /* enable irq in nvic              */
    5.         LPC_UART0->IER = 0x01;                  //使能接收中断
    复制代码


    中断相关配置:
    1. void UartInit(uint32_t bps)
    2. {
    3.         uint16_t usFdiv = ((SystemCoreClock/4)/16)/bps;
    4.         
    5.         UartGPIOInit();
    6. //        LPC_UART0->RBR;        //缓冲接收寄存器
    7. //        LPC_UART0->THR;        //发送寄存器
    8. //        LPC_UART0->DLL;        //波特率低位
    9. //        LPC_UART0->DLM;        //波特率高位
    10.         
    11.   LPC_UART0->LCR = 0x83;                                        //使能访问除数锁存器,8 bits, no Parity, 1 Stop bit     */
    12.   LPC_UART0->DLM = usFdiv / 256;        //初始化波特率                   */
    13.   LPC_UART0->DLL = usFdiv % 256;
    14.   LPC_UART0->LCR = 0x03;                                        //禁止访问除数锁存器,锁定波特率
    15.         
    16.         LPC_UART0->FCR  = 0x00;                 //禁止FIFO
    17.         NVIC_ClearPendingIRQ(UART0_IRQn);
    18. //        NVIC_SetPriority(UART0_IRQn,NVIC_EncodePriority(SYS_NVIC_GROUP,UART0_PreemptPriority,UART0_SubPriority));
    19.         NVIC_SetPriority(UART0_IRQn, 0);
    20.         NVIC_EnableIRQ(UART0_IRQn);              /* enable irq in nvic              */
    21.         LPC_UART0->IER = 0x01;                  //使能接收中断
    22. }

    23. char RxBuf[50]="";
    24. struct _usart_flag usart0_flag={0,0,0};

    25. void UartRxInBuf(uint8_t str)
    26. {
    27.         if(usart0_flag.rec_end_flag==0)//接收未完成
    28.     {
    29.         if(usart0_flag.rec_middle_flag)//接收到了0x0d
    30.         {
    31.             if(str!=0x0a)
    32.                                                         usart0_flag.rec_middle_flag = 0;//接收错误,重新开始
    33.             else
    34.                                                         usart0_flag.rec_end_flag = 1;        //接收完成了
    35.         }
    36.         else //还没收到0X0D
    37.         {
    38.             if(str==0x0d)
    39.                                                         usart0_flag.rec_middle_flag = 1;
    40.             else
    41.             {
    42.                 RxBuf[usart0_flag.size]=str ;
    43.                 usart0_flag.size++;
    44.                 if(usart0_flag.size>(50-1))
    45.                                                                         memset(&usart0_flag, 0, sizeof(usart0_flag));        //接收数据错误,重新开始接收
    46.             }
    47.         }
    48.     }
    49. }

    50. #define UART_IIR_RLS 3
    51. #define UART_IIR_CTI 6
    52. #define UART_IIR_RDA 2

    53. #define UART_LSR_RDR 0x01
    54. #define UART_LSR_OE 0x02
    55. #define UART_LSR_PE 0x04
    56. #define UART_LSR_FE 0x08
    57. #define UART_LSR_THRE 0x20
    58. #define UART_LSR_TEMT 0x40
    59. #define UART_LSR_RXFE 0x80

    60. void UART0_IRQHandler(void)
    61. {
    62.                 uint8_t IIRValue;
    63.     uint8_t     LSRValue;
    64.     uint8_t     Dummy = 0;
    65. //    Uart_Buf *p = NULL;
    66.     bool bFlag = true;


    67.     while ( bFlag ) {                                 // 等待产生的所有中断处理完?
    68.         IIRValue   = LPC_UART0->IIR;                      // 读取中断状态寄存器
    69.         IIRValue >>= 1;                               // 屏蔽IIR中不需要的信息
    70.         IIRValue  &= 0x07;                            // 效验1~3BIT 对中断状态识别

    71.         switch (IIRValue) {                           //
    72.         case UART_IIR_RLS :                           // --接收线状态
    73.             LSRValue = LPC_UART0->LSR;                    // 读取线状态信息
    74.             Dummy = UART_LSR_OE | UART_LSR_PE | UART_LSR_FE | UART_LSR_RXFE;
    75.             if ( LSRValue & Dummy) {                  // -- 线状态 接收有关中断 只丢弃错误的成对接收RSR中字符
    76.                 Dummy = LPC_UART0->RBR;                   // 读出成对字符 丢弃
    77.                 break;                                // 下一个中断标志处理
    78.             }

    79.             if ( LSRValue & UART_LSR_RDR ) {          // -- 线状态 接收数据就绪
    80.                 Dummy = LPC_UART0->RBR;                   // 读数据 时会清除中断
    81.                 UartRxInBuf(Dummy);                // 进缓存
    82.             }

    83.             if ( ( LSRValue & UART_LSR_THRE) ||       // -- 线状态 发送保持寄存器空
    84.                  ( LSRValue & UART_LSR_TEMT) ) {      // -- 线状态 发送器空
    85. //                p = &UartTx[0];                       // 取对应串口发送缓存信息
    86. //                if (p->Cnt > 0) {                     // 检查发送消息缓存区是否为空 不为空则继续发数据
    87. //                    LPC_UART0->THR = UartTxOutBuf(0);  // 读走一个数据到发送寄存器
    88. //                } else {
    89. //                    UartTxFlag[0] = FALSE;            // 发送标志为0表示 可以直接发送信息
    90. //                }
    91.             }
    92.             break;

    93.         case UART_IIR_CTI :                           // -- 字符超时
    94.             Dummy = LPC_UART0->RBR;                       // 读数据
    95.             UartRxInBuf(Dummy);                    // 进接受缓存
    96.             break;

    97.         case UART_IIR_RDA :                           // -- 数据接收
    98.             Dummy = LPC_UART0->RBR;                       // 读数据
    99.             UartRxInBuf(Dummy);                    // 进接受缓存
    100.             break;

    101. //        case UART_IIR_THRE :                          // -- 发送空
    102. //            p = &UartTx[0];                           // 取对应串口发送缓存信息
    103. //            if (p->Cnt > 0) {                         // 检查发送消息缓存区是否为空 不为空则继续发数据
    104. //                LPC_UART0->THR    = UartTxOutBuf(0);      // 读走一个数据到发送寄存器
    105. //            } else {
    106. //                UartTxFlag[0] = FALSE;                // 发送标志为0表示 可以直接发送信息
    107. //            }
    108. //            break;

    109.         default :                                     // -- 默认处理 空
    110.             bFlag = false;                            // 没有中断需要处理了
    111.             break;
    112.         }
    113.     }
    114. }
    复制代码








    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2025-7-11 08:53
  • 签到天数: 301 天

    连续签到: 2 天

    [LV.8]以坛为家I

    3868

    主题

    7472

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    39232
    最后登录
    2025-7-18
    发表于 2019-3-5 13:43:04 | 显示全部楼层
    支持下!
    qiandao qiandao
    回复

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2025-7-20 23:23 , Processed in 0.090534 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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