查看: 4984|回复: 3

[原创] 【正点原子_RT1052试用】2、自定义串口通信数据包

[复制链接]
  • TA的每日心情
    奋斗
    2017-12-1 19:29
  • 签到天数: 114 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2018-7-14 19:21:27 | 显示全部楼层 |阅读模式
    分享到:
    说明:本实验是通过串口调试助手模拟上位机或者其他MCU发送控制指令,使用RT1052作为从机,通过解析数据包,提取出所需数据。
    数据包格式为:(包头)(数据位数)(数据...)(数据位数反码)(包尾)
    对于包头和包尾可以自行修改,也可以使用2位数据作为包头,需要简单修改一下代码即可。
    2.1 串口设置步骤
    1、常规串口配置步骤
    开启串口时钟,并设置相应 IO 口的模式,然后配置波特率,数据位长度,奇偶校验位等。
    2、RT1052配置步骤
    1)开启串口时钟
    1. CLOCK_EnableClock(kCLOCK_Lpuart1);        //使能LPUART1时钟        
    2. CLOCK_SetMux(kCLOCK_UartMux,0); //设置UART时钟源为PLL3 80Mhz,PLL3/6=480/6=80MHz
    3. CLOCK_SetDiv(kCLOCK_UartDiv,0); //设置UART时钟1分频,即UART时钟为80Mhz
    复制代码

    2)配置IO为LPUART功能
    1. //LPUART1所使用的IO功能配置,即:从ALT0~ALT7选择合适的功能。
    2. IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0U);        //GPIO_AD_B0_12设置为LPUART1_TX
    3. IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0U);        //GPIO_AD_B0_13设置为LPUART1_RX

    4. //配置IO引脚GPIO_AD_B0_12和GPIO_AD_B0_13的功能
    5. //低转换速度,驱动能力为R0/6,速度为100Mhz,关闭开路功能,使能pull/keepr
    6. //选择keeper功能,下拉100K Ohm,关闭Hyst
    7. IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_12_LPUART1_TX,0x10B0u);
    8. IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,0x10B0u);
    复制代码
    3)配置串口
    1. lpuart1_config.baudRate_Bps=bound;        //波特率
    2. lpuart1_config.dataBitsCount=kLPUART_EightDataBits;        //8位
    3. lpuart1_config.stopBitCount=kLPUART_OneStopBit;        //1位停止位
    4. lpuart1_config.parityMode=kLPUART_ParityDisabled;        //无奇偶校验
    5. lpuart1_config.enableRx=true;        //使能接收
    6. lpuart1_config.enableTx=true;        //使能发送

    7. LPUART_Init(LPUART1,&lpuart1_config,freq);        //初始化LPUART1
    复制代码
    4)串口中断使能
    1. LPUART_EnableInterrupts(LPUART1,kLPUART_RxDataRegFullInterruptEnable); //使能接收中断
    2. RT1052_NVIC_SetPriority(LPUART1_IRQn,5,0);        //抢占优先级5,子优先级0
    3. EnableIRQ(LPUART1_IRQn);        //使能LPUART1中断
    复制代码
    2.2 自行添加串口中断函数代码
    1、LPUART.h的设置
    添加如下红色部分代码
    1. #ifndef _USART_H
    2. #define _USART_H
    3. #include "sys.h"
    4. #include "stdio.h"        
    5. #include "fsl_common.h"
    6. #include "fsl_iomuxc.h"
    7. //#include "pin_mux.h"
    8. #include "fsl_debug_console.h"
    9. //////////////////////////////////////////////////////////////////////////////////         
    10. //本程序只供学习使用,未经作者许可,不得用于其它任何用途
    11. //ALIENTEK I.MX RT1052开发板
    12. //串口1初始化        
    13. //正点原子@ALIENTEK
    14. //技术论坛:www.openedv.csom
    15. //修改日期:2017/12/10
    16. //版本:V1.0
    17. //版权所有,盗版必究。
    18. //Copyright(C) 正点原子 2009-2019
    19. //All rights reserved
    20. //********************************************************************************
    21. //V1.0修改说明
    22. //////////////////////////////////////////////////////////////////////////////////

    23. //跟NXP官方例程里提供的跟debug console有关的宏定义
    24. #define BOARD_DEBUG_UART_TYPE DEBUG_CONSOLE_DEVICE_TYPE_LPUART
    25. #define BOARD_DEBUG_UART_BASEADDR (uint32_t) LPUART1

    26. #define LPUART_REC_LEN 200 //定义最大接收字节数 200
    27. #define EN_LPUART1_RX 1        //使能(1)/禁止(0)串口1接收

    28. extern u8 LPUART_RX_BUF[LPUART_REC_LEN]; //接收缓冲,最大LPUART_REC_LEN个字节.末字节为换行符
    29. extern u16 LPUART_RX_STA; //接收状态标记        

    30. <font color="#ff0000">extern u8 usart_rx_buf[40];
    31. extern u8 usart_rd_len;
    32. extern u8 usart_rx_successflag;
    33. extern u8 len_store;</font>
    34. void LPUART1_Init(u32 bound);
    35. #endif
    复制代码
    2、更改串口中断函数
    本实验示例的数据包为:0xee 0x02 0x05/0x06 0x07/0x08 0xfd 0xef
    1)设置0x05数据为LED0亮,0x06数据为LED0灭
    2)设置0x07数据为LED1亮,0x08数据为LED1灭
    程序思路:
    1)当发生串口中断时,首先判断LPUART1->STAT和接收数据寄存器满标志是否置位,然后读取寄存器数据LPUART1->DATA
    2)判断第一帧数据是否为0xee,如果是,则usart_rx_enableflag=1,接收标志置1
    3)如果usart_rx_enableflag=1,那么再读下一帧数据作为数据长度
    4)继续读取数据,直到数据校验位和包尾验证正确,将usart_rx_successflag=1
    5)如果usart_rx_successflag=1,将存在数组usart_rx_temporary[]中的数据赋给usart_rx_buf[]
    1. uint8_t usart_rx_buf[40]; //接收缓冲,最大40个字节
    2. uint8_t usart_rx_temporary[40]; //数据保存暂存器,最多能够缓存40个字节
    3. uint8_t usart_rd_len=0; //有用信息的数据长度
    4. uint8_t usart_rd_lentemp=0;        //用来记录已读取的数据长度
    5. uint8_t usart_rx_enableflag=0; //接收状态标记         
    6. uint8_t usart_rx_lenrightflag=0;//数据长度校验位正确标志
    7. uint8_t usart_rx_successflag=0; //成功接收到数据信息
    8. uint8_t len_store=0;

    9. void LPUART1_IRQHandler(void) //串口1中断服务程序
    10. {
    11. u8 i,res,check_temp;

    12. if((LPUART1->STAT)&kLPUART_RxDataRegFullFlag) //接收中断
    13. {
    14. res=LPUART1->DATA;        //读取数据        //读取接收到的数据

    15. if(usart_rx_enableflag==1)        //到接受数据标志置位时,接受数据
    16. {        
    17. printf("\r\n 接收了数据\r\n\r\n");        
    18. if(usart_rd_lentemp==0)        //包头后第一个数据为需要传输的数据的长度
    19. {
    20. usart_rd_len=res;        //读取数据的长度
    21. if(usart_rd_len>=40)
    22. {
    23. usart_rx_lenrightflag=0;        //数据长度校验清零
    24. usart_rx_successflag=0;        //数据接收成功标志清零
    25. usart_rx_enableflag=0;        //数据接收完成,数据接收启动标志清零
    26. usart_rd_len=0;        //数据长度清零
    27. usart_rd_lentemp=0;        //数据长度暂存器清零        
    28. }
    29. }

    30. else if(usart_rd_lentemp==usart_rd_len+1)        //当读取到第usart_rd_lentemp+1个数据时,校验是否是长度信息的反码
    31. {
    32. check_temp=~usart_rd_len;        //取数据长度校验位的反码
    33. if(res==check_temp)        //当数据长度校验正确时
    34. usart_rx_lenrightflag=1;        //数据长度校验标志置一
    35. else
    36. {        //当数据长度校验错误时
    37. usart_rx_lenrightflag=0;        //数据长度校验清零
    38. usart_rx_successflag=0;        //数据接收成功标志清零
    39. usart_rx_enableflag=0;        //当数据长度校验错误时,数据接收启动标志清零
    40. usart_rd_len=0;        //数据长度清零
    41. usart_rd_lentemp=0; //数据长度暂存器清零
    42. }
    43. }

    44. else if(usart_rd_lentemp==usart_rd_len+2)        //当读取到第usart_rd_lentemp+2个数据时,校验包尾是否正确
    45. {
    46. if((res==0xef)&&(usart_rx_lenrightflag==1))        //如果包尾数据与长度校验都正确
    47. {
    48. usart_rx_lenrightflag=0;        //数据长度校验清零
    49. usart_rx_successflag=1;        //数据接收成功标志置一
    50. usart_rx_enableflag=0;        //数据接收完成,数据接收启动标志清零
    51. //usart_rd_len=0;        //数据长度清零
    52. usart_rd_lentemp=0; //数据长度暂存器清零        
    53. }
    54. else
    55. {        //当包尾数据校验错误时
    56. usart_rx_lenrightflag=0;        //数据长度校验清零
    57. usart_rx_successflag=0;        //数据接收成功标志清零
    58. usart_rx_enableflag=0;        //数据接收完成,数据接收启动标志清零
    59. usart_rd_len=0;        //数据长度清零
    60. usart_rd_lentemp=0;        //数据长度暂存器清零        
    61. }
    62. }
    63. else usart_rx_temporary[usart_rd_lentemp-1]=res;        //当usart_rd_lentemp为数据段时,将数据存到串口数据接收寄存器中        

    64. usart_rd_lentemp++;        //每次记录数据,数据长度暂存器自加        
    65. if(usart_rx_successflag==1)        //如果成功接收到信息数据,将缓存usart_rx_temporary[]内的数据传递给usart_rx_buf[][]
    66. {
    67. len_store=usart_rd_len;
    68. for(i=0;i<usart_rd_len;i++)
    69. usart_rx_buf[i]=usart_rx_temporary[i];
    70. usart_rx_lenrightflag=0;
    71. //数据长度校验清零
    72. //usart_rx_successflag=0;
    73. //数据接收成功标志清零
    74. usart_rx_enableflag=0;
    75. //数据接收完成,数据接收启动标志清零
    76. usart_rd_len=0; //数据长度清零
    77. usart_rd_lentemp=0;
    78. printf("\r\n 接收成功\r\n\r\n");//Usart_SendString( USART1,"successed rx!\r\n");
    79. }        
    80. }
    81. if((res==0xee)&&(usart_rx_enableflag==0))        //当接受到包头(0xee)数据并且还没有成功接收完数据信息
    82. usart_rx_enableflag=1;        //说明这是包头,启动接收数据标志,进入数据接收阶段
    83. }
    84. //        __DSB();        //数据同步屏蔽指令
    85. }
    复制代码
    3、在主函数加入以下代码
    1. if(usart_rx_successflag==1)
    2.                 {                        
    3.                         if(usart_rx_buf[0]==0x05)
    4.                         {
    5.                                 LED0(0);
    6.                         }
    7.                  if(usart_rx_buf[0]==0x06)
    8.                         {
    9.                                 LED0(1);
    10.                         }
    11.                         if(usart_rx_buf[1]==0x07)
    12.                         {
    13.                                 LED1(0);
    14.                         }
    15.                         if(usart_rx_buf[1]==0x08)
    16.                         {
    17.                                 LED1(1);
    18.                         }
    19.                         usart_rx_successflag=0;
    20.                         if(usart_rx_successflag==0)
    21.                         {
    22.                                 printf("\r\n 复位\r\n\r\n");
    23.                         }
    24.                         
    25.                 }
    复制代码


    2.3 下载程序,设置串口助手发送数据包
    从图中可以看出,我们发送数据包一共6位,通过我们添加的printf语句的位置,可以验证数据接收次数为5次,正确,因为不包含帧头。
    1.jpg
    2.4 实验结果





    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-12-1 19:29
  • 签到天数: 114 天

    连续签到: 1 天

    [LV.6]常住居民II

     楼主| 发表于 2018-7-14 19:25:47 | 显示全部楼层
    发的视频没有显示,管理员看一下哈
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2024-12-3 16:36
  • 签到天数: 49 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2018-7-16 09:54:56 | 显示全部楼层
    努力的人 发表于 2018-7-14 19:25
    发的视频没有显示,管理员看一下哈

    已经修改,具体插入视频方法可看https://www.cirmall.com/bbs/thread-99383-1-1.html
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-12-1 19:29
  • 签到天数: 114 天

    连续签到: 1 天

    [LV.6]常住居民II

     楼主| 发表于 2018-7-16 18:58:10 | 显示全部楼层
    satoll 发表于 2018-7-16 09:54
    已经修改,具体插入视频方法可看https://www.cirmall.com/bbs/thread-99383-1-1.html

    好的,谢啦
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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



    手机版|小黑屋|与非网

    GMT+8, 2025-1-12 21:01 , Processed in 0.141547 second(s), 22 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.