[STM32L5] 【STM32L562E-DK试用】4.UART通讯与硬件CRC

[复制链接]
2604|0
 楼主| yuyy1989 发表于 2025-1-22 21:16 | 显示全部楼层 |阅读模式
UART在嵌入式领域应用的非常广泛,这块板子引出了一路串口接到了STLink的串口上,倒也省得再找USB转串口了,直接用这个测试一下串口功能
微信截图_20250122182154.png
在之前生成的工程中已经配置好了串口的IO
微信截图_20250122182256.png
默认的串口配置参数如图
微信截图_20250122182356.png
尝试直接通过串口发送数据到PC,看看通讯是否正常,串口的初始化代码STM32CubeMX已经帮我们写好了,直接调用发送方法就行了
  1. void AppUartSendStr(char *str)
  2. {
  3.     while(*str != '\0')
  4.     {
  5.         LL_USART_TransmitData8(USART1,(uint8_t)*str);
  6.         while(!LL_USART_IsActiveFlag_TXE(USART1));
  7.         str += 1;
  8.     }
  9. }
  10. void AppUserLoop(void)
  11. {
  12.     LL_mDelay(1000);
  13.     AppUartSendStr("STM32L562E-DK试用 code by yuyy1989");
  14. }
开发板连接到PC后会出现一个虚拟串口设备
微信截图_20250122183626.png
打开串口通讯软件,配置好串口参数,观察是否有数据发送过来,运行效果如图

微信截图_20250122183915.png
顺便完成一下重定向printf到串口,以方便后面调试,打开keil工程设置勾选use microlib
微信截图_20250122184134.png
在文件中包含stdio.h头文件,然后重写fputc
  1. int fputc(int ch, FILE *f)
  2. {
  3.     LL_USART_TransmitData8(USART1,(uint8_t)ch);
  4.     while(!LL_USART_IsActiveFlag_TXE(USART1));
  5.     return 0;
  6. }
  7. uint8_t count = 0;
  8. void AppUserLoop(void)
  9. {
  10.     LL_mDelay(1000);
  11.     printf("【STM32L562E-DK试用】printf测试%d code by yuyy1989",count++);
  12. }
写完代码后选择rebuld重新完整编译一次,不然可能会报错,运行效果
微信截图_20250122185448.png
接下来实现串口的中断接收功能,生成的工程默认是没有开启中断的,打开STM32CubeMX开启串口中断
微信截图_20250122192126.png
重新生成代码,和之前的定时器一样,需要手动使能串口中断,这里开启接收中断和空闲中断
  1. LL_USART_EnableIT_RXNE(USART1);
  2. LL_USART_EnableIT_IDLE(USART1);
触发空闲中断后将接收到的数据原样发送回去
  1. #define UART_BUFFER_LEN 100
  2. uint8_t uart_buffer[UART_BUFFER_LEN] = {0};
  3. uint8_t uart_rxlen = 0;
  4. uint8_t uart_rxfin_flag = 0;
  5. void USART1_IRQHandler(void)
  6. {
  7.     if(LL_USART_IsActiveFlag_RXNE(USART1))
  8.     {
  9.         uart_buffer[uart_rxlen] = LL_USART_ReceiveData8(USART1);
  10.         uart_rxlen += 1;
  11.         if(uart_rxlen == UART_BUFFER_LEN)
  12.         {
  13.             uart_rxfin_flag = 1;
  14.             LL_USART_DisableIT_RXNE(USART1);
  15.         }
  16.     }
  17.     if(LL_USART_IsActiveFlag_IDLE(USART1))
  18.     {
  19.         uart_rxfin_flag = 1;
  20.         LL_USART_DisableIT_RXNE(USART1);
  21.         LL_USART_ClearFlag_IDLE(USART1);
  22.     }
  23. }
  24. void AppUserLoop(void)
  25. {
  26.     uint8_t txindex = 0;
  27.     if(uart_rxfin_flag > 0)
  28.     {
  29.         while(txindex < uart_rxlen)
  30.         {
  31.             LL_USART_TransmitData8(USART1,uart_buffer[txindex]);
  32.             while(!LL_USART_IsActiveFlag_TXE(USART1));
  33.             txindex += 1;
  34.         }
  35.         uart_rxfin_flag = 0;
  36.         uart_rxlen = 0;
  37.         LL_USART_EnableIT_RXNE(USART1);
  38.     }
  39. }
运行效果如图
微信截图_20250122195036.png
STM32L562内置有CRC计算模块,可以快速产生CRC码,从而验证数据的完整性和正确性,这个功能在数据通信领域尤为重要,因为它可以确保数据在传输过程中的准确性,例如MODBUS就要用到CRC16,接下来配置CRC功能,将串口接收到的数据进行CRC16-MODBUS校验再通过串口输出结果
打开STM32CubeMX开启CRC,要关闭默认多项式和初始值才能自定义配置多项式和初始值,多项式要注意X16这位不用输入也输入不进去,输入数据按字节翻转,开启输出数据翻转
微信截图_20250122205059.png
代码实现计算串口接收到数据的CRC并用printf打印到串口,串口接收部分不用动,将前面的发送过程改一下加入CRC校验过程

  1. void AppUserLoop(void)
  2. {
  3.     uint16_t crc_result = 0;
  4.     if(uart_rxfin_flag > 0)
  5.     {
  6.         LL_CRC_ResetCRCCalculationUnit(CRC);
  7.         while(txindex < uart_rxlen)
  8.         {
  9.             LL_CRC_FeedData8(CRC,uart_buffer[txindex]);
  10.             txindex += 1;
  11.         }
  12.         crc_result = LL_CRC_ReadData16(CRC);
  13.         printf("【STM32L562E-DK试用】CRC计算结果:%04X code by yuyy1989",crc_result);
  14.         uart_rxfin_flag = 0;
  15.         uart_rxlen = 0;
  16.         LL_USART_EnableIT_RXNE(USART1);
  17.     }
  18. }
计算结果和网页工具比对,结果一致
微信截图_20250122204818.png

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

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部