当前位置:   article > 正文

树莓派与stm32通信超详细解答过程_树莓派和stm32通信

树莓派和stm32通信

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

笔者之前发过关于stm32与openmv通信的教程,在学习了几天opencv后,想实现树莓派4B与stm32进行通信。于是上网查询资料,最后实现了两者之间的通信,相信这对大多数电赛人都很有帮助,opencv的识别效果是远高于openmv以及K210的。在此我参考了以下资料辅助我学习,大家可以参考。

基于树莓派4B与STM32的UART串口通信实验(代码开源)_树莓派4b串口波特率-CSDN博客

这位大佬的接发方式我觉得可能对于新手朋友来说比较难懂,于是我换了一种收发方式,与我之前openmv与opencv通信的方式极为类似,如果那个可以搞懂,相信这个也不是问题,甚至超容易上手。

在此默认树莓派已经配置好环境烧录好系统。如果不会烧录系统以及配置opencv的可以私聊我获取镜像。

先上效果图以及视频

一、两者如何进行通信?

与我们之前openmv与stm32的通信方式类似,打开双方的串口然后互相连接,就可以进行通信,具体笔者不多描述,参考我给的链接就可以实现通信,笔者主要讲解我的数据传输方法。

具有以下两个特点:

1.以数据包格式打包发送,32端的代码不用过多改变,接收方式基本相同

  1. data = bytearray([0x2C, 0x12, temp_xh, temp_xl, temp_yh, temp_yl, temp_wh, temp_wl,temp_hh,temp_hl ,0x5B])
  2. ser.write(data)

2.可以发送16位数据,笔者起初一直发送8位数据,但是bytearray数据包只能发送8位的数据即最高只能发送小于256的数字。这对我们刚入手openmv和32通信的人极不友好。但是根据2023年e题有的坐标点大于256,我们将如何发送?我的解决方法我将数据拆分为高8位和低8位,发送到32后再让32进行解析。为此也是思考了一段时间,我认为还是很有帮助的也能很好的帮助大家。也自认为这个方法很不赖。在此我直接附上树莓派的代码。

  1. import serial
  2. import time
  3. import struct
  4. cx=300
  5. cy=400
  6. cw=500
  7. ch=600
  8. # 初始化串口,修改串口号和波特率
  9. ser = serial.Serial('/dev/ttyAMA0', 115200)
  10. def sending_data(cx, cy, cw, ch):
  11. # 取 cx 的高 8
  12. temp_xh = (cx & 0xff00) >> 8
  13. # 取 cx 的低 8
  14. temp_xl = cx & 0x00ff
  15. # 取 cy 的高 8
  16. temp_yh = (cy & 0xff00) >> 8
  17. # 取 cy 的低 8
  18. temp_yl = cy & 0x00ff
  19. # 取 cw 的高 8
  20. temp_wh = (cw & 0xff00) >> 8
  21. # 取 cw 的低 8
  22. temp_wl = cw & 0x00ff
  23. # 取 ch 的高 8
  24. temp_hh = (ch & 0xff00) >> 8
  25. # 取 ch 的低 8
  26. temp_hl = ch & 0x00ff
  27. data = bytearray([0x2C, 0x12, temp_xh, temp_xl, temp_yh, temp_yl, temp_wh, temp_wl,temp_hh,temp_hl ,0x5B])
  28. ser.write(data)
  29. print(data)
  30. while True:
  31. # 模拟获取数据
  32. cx += 100
  33. cy += 100
  34. cw += 100
  35. ch += 100
  36. sending_data(cx, cy, cw, ch)
  37. time.sleep(0.2)

可以发现这种数据传输方式与openmv与stm32通信的方式极为类似,如果理解了这种传输方式,那么我写的这个树莓派传输数据的方式就超容易上手以及理解。只不过openmv没有加16位数据发送的格式而已。

二、stm32如何解析树莓派发送的数据

1.解析8位数据(0-256)

代码如下(示例):

8位数据比较简单直接从python发送的数据解析低8位就可以

bytearray([0x2C, 0x12, temp_xh, temp_xl, temp_yh, temp_yl, temp_wh, temp_wl,temp_hh,temp_hl ,0x5B])

这里temp_xh为高8位数据,temp_xl为低8位数据,stm32对应数组的位置C1为高8位,Cx为低8位,我们只用处理Cx就可以了。

  1. Cx=RxBuffer1[RxCounter1-8];
  2. C1=RxBuffer1[RxCounter1-9];

2.16位数据(0-65536)

与8位数据类似,我们只需将Cx和C1都读出来,让C1*256加上Cx就是大于256即16位的数据。

我直接附上总处理代码。(stm32端)

  1. uint16_t Cx,Cy,Cw,Ch;
  2. uint16_t C1,C2,C3,C4;
  3. uint16_t X,Y,W,H;
  4. uint8_t display_buf[20];
  5. uint8_t Flag=0;
  6. void Receive_Data(int16_t Com_Data)
  7. {
  8. uint8_t i;
  9. static uint8_t RxCounter1=0;//
  10. static uint16_t RxBuffer1[20]={0};
  11. static uint8_t RxState = 0;
  12. static uint8_t RxFlag1 = 0;
  13. if(RxState==0&&Com_Data==0x2C) //0x2c
  14. {
  15. RxState=1;
  16. RxBuffer1[RxCounter1++]=Com_Data;
  17. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
  18. }
  19. else if(RxState==1&&Com_Data==0x12) //0x12
  20. {
  21. RxState=2;
  22. RxBuffer1[RxCounter1++]=Com_Data;
  23. }
  24. else if(RxState==2)
  25. {
  26. RxBuffer1[RxCounter1++]=Com_Data;
  27. if(RxCounter1>=20||Com_Data == 0x5B)
  28. {
  29. RxState=3;
  30. Cx=RxBuffer1[RxCounter1-8];
  31. C1=RxBuffer1[RxCounter1-9];
  32. Cy=RxBuffer1[RxCounter1-6];
  33. C2=RxBuffer1[RxCounter1-7];
  34. Cw=RxBuffer1[RxCounter1-4];
  35. C3=RxBuffer1[RxCounter1-5];
  36. Ch=RxBuffer1[RxCounter1-2];
  37. C4=RxBuffer1[RxCounter1-3];
  38. X=C1*256+Cx;
  39. Y=C2*256+Cy;
  40. W=C3*256+Cw;
  41. H=C4*256+Ch;
  42. }
  43. }
  44. else if(RxState==3)//
  45. {
  46. if(RxBuffer1[RxCounter1-1] == 0x5B)
  47. {
  48. if(RxFlag1==0)
  49. {
  50. OLED_Clear();
  51. }
  52. HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
  53. RxFlag1++;
  54. RxCounter1 = 0;
  55. RxState = 0;
  56. OLED_ShowNum(0,0,X,6,16);
  57. OLED_ShowNum(0,2,Y,6,16);
  58. OLED_ShowNum(0,4,W,6,16);
  59. OLED_ShowNum(0,6,H,6,16);
  60. }
  61. else
  62. {
  63. RxState = 0;
  64. RxCounter1=0;
  65. for(i=0;i<10;i++)
  66. {
  67. RxBuffer1[i]=0x00; //
  68. }
  69. }
  70. }
  71. else
  72. {
  73. RxState = 0;
  74. RxCounter1=0;
  75. for(i=0;i<10;i++)
  76. {
  77. RxBuffer1[i]=0x00; //
  78. }
  79. }
  80. }

XYWH分别对应处理过的cx,cy,cw,ch。我们直接用oled就可以显示我们从树莓派接收到的数据了。

3.stm32端开启中断

  1. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  2. {
  3. uint16_t tempt /*定义临时变量存放接受的数据*/;
  4. if(huart->Instance==USART1)
  5. {
  6. tempt=USART1_RXbuff;
  7. Receive_Data(tempt);
  8. HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET);
  9. }
  10. HAL_UART_Receive_IT(&huart1,(void *)&USART1_RXbuff,1);/*再次开启接收中断*/
  11. }


总结

具体的可以参考我openmv与stm32通信的文章,有详细的stm32端接收讲解。

https://blog.csdn.net/Halcyon0804/article/details/139890266?spm=1001.2014.3001.5502

到这里基本就实现两者的数据互传了。并且数据范围特别大,我相信已经很够用了,希望这篇文章可以帮到大家。

如果树莓派不会配置的可以私聊我获取树莓派配置好的镜像,已经配置好opencv以及2023年运动目标跟踪控制系统的图像处理代码。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/1018880
推荐阅读
相关标签
  

闽ICP备14008679号