你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F427IIH6芯片通过DMA+USART与树莓派进行双工通信

[复制链接]
STMCU小助手 发布时间:2021-7-26 11:27
1. 树莓派

树莓派端我们需要找到USB端口设备,我的树莓派上是CHASSIS_SERIAL_PORT = '/dev/ttyUSB0',获得了端口设备之后就可以开始调库了,这也是python语言的拿手好戏。这次我们用的库是serial,我们需要这个库里的函数

串口初始化:self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)

发送数据:self.port_chassis.write((direction + str(distance)).encode())

读取数据:self.port_chassis.readline().decode()

流初始化:
self.port_chassis.flushInput();self.port_chassis.flushOutput()

有了上面几个函数之后,就可以开始写python脚本啦,结合代码来进行分析
首先是类的初始化函数,目的主要是初始化USART(UART)的波特率
  1. <font face="微软雅黑" size="3">def __init__(self):
  2.         print("move init finish")
  3.         self.time1 = time.time()
  4.         self.time2 = time.time()
  5.         self.flag = False
  6.         self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)
  7.         # print('port_chassis is :' + self.port_chassis.is_Open())
  8.         self.port_chassis.flushInput()
  9.         self.port_chassis.flushOutput()</font>
复制代码
接下来就是发送数据,我们的购物机器人是通过树莓派做为整个的 “大脑”,是由树莓派里的python脚本给底盘发送指令,所以这个函数就是python让底盘移动distance个格子的函数,这个函数里面也是通过USART(UART)给底盘发送指令的,所用函数就是self.port_chassis.write((direction + str(distance)).encode())
  1. <font face="微软雅黑" size="3"> def move_by_grid(self, direction, distance=''):
  2.         # print('move by grid')
  3.         self.port_chassis.write((direction + str(distance)).encode())
  4.         self.time1 = time.time()
  5.         print(direction + str(distance))
  6.         self.wait_for_act_end_signal_chassis(direction, distance)</font>
复制代码
最后是接收数据,既然树莓派要控制底盘,树莓派自然也要接收到底盘回传的数据,这里用到的USART(UART)接收数据函数是self.port_chassis.readline().decode(),sig就是树莓派接收到的USART(UART)数据,用户就可以对其做处理啦
  1. <font face="微软雅黑" size="3">def wait_for_act_end_signal_chassis(self, ret=None, distance=0):
  2.         print('waiting chassis...')
  3.         while True:
  4.             sig = self.port_chassis.readline().decode()

  5.             # print(self.time2 - self.time1)

  6.             sig = sig[0:2]
  7.             print(sig)
  8.             #
  9.             if sig == 'HI':
  10.                 self.time2 = time.time()
  11.                 print(self.time2 - self.time1)
  12.                 if self.time2 - self.time1 < 1.0 and self.flag == False and distance == 1:
  13.                     print('1 step deal error')
  14.                     self.flag = True
  15.                     if (ret == dir_up or ret == dir_back):
  16.                         self.move_by_grid(ret, 1)
  17.                     else:</font>
复制代码


2. STM32F427IIH6


在嵌入式芯片STM32F427IIH6里,我们首先要打开芯片的DMA功能,然后进行USART(UART)的初始化,最后设置USART(UART)的回调函数即可。


首先进行DMA的初始化,在这些初始化里面完成的就是DMA时钟的使能和DMA中断的使能。

  1. <font face="微软雅黑" size="3">void MX_DMA_Init(void)
  2. {

  3.   /* DMA controller clock enable */
  4.   __HAL_RCC_DMA1_CLK_ENABLE();
  5.   __HAL_RCC_DMA2_CLK_ENABLE();

  6.   /* DMA interrupt init */
  7.   /* DMA1_Stream0_IRQn interrupt configuration */
  8.   HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  9.   HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
  10.   /* DMA1_Stream1_IRQn interrupt configuration */
  11.   HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
  12.   HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  13.   /* DMA1_Stream3_IRQn interrupt configuration */
  14.   HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
  15.   HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
  16.   /* DMA1_Stream6_IRQn interrupt configuration */
  17.   HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
  18.   HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
  19.   /* DMA2_Stream1_IRQn interrupt configuration */
  20.   HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
  21.   HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
  22.   /* DMA2_Stream6_IRQn interrupt configuration */
  23.   HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);
  24.   HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);

  25. }
  26. </font>
复制代码
DMA使能完成之后就要进行USART(UART)的基本配置了,这里我设置的就是波特率9600(各个USART(UART)波特率初始化大同小异,因此在这里只放了usart6的初始化,其他类似,不做赘述)。
  1. <font face="微软雅黑" size="3">void MX_USART6_UART_Init(void)
  2. {

  3.   huart6.Instance = USART6;
  4.   huart6.Init.BaudRate = 9600;
  5.   huart6.Init.WordLength = UART_WORDLENGTH_8B;
  6.   huart6.Init.StopBits = UART_STOPBITS_1;
  7.   huart6.Init.Parity = UART_PARITY_NONE;
  8.   huart6.Init.Mode = UART_MODE_TX_RX;
  9.   huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  10.   huart6.Init.OverSampling = UART_OVERSAMPLING_16;
  11.   if (HAL_UART_Init(&huart6) != HAL_OK)
  12.   {
  13.     Error_Handler();
  14.   }

  15. }</font>
复制代码
完成了芯片级的配置之后,就要开始配置用户自己需求的USART(UART)功能了,简单点来说就是就是设置回调函数,并且编写回调函数内容。




在void USR_UartInit(void)中主要是打开USART(UART)的DMA接收功能,并且开启USART(UART)接收中断,HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)就是我们的回调函数,uart6Rx[1024],uart7Rx[1024],uart8Rx[1024]这3个数组就是STM32F427IIH6的3个(USART6,UART7,UART8)USART(UART)接收到的数组数据 啦,接下来用户就可以对其做处理啦。
  1. <font face="微软雅黑" size="3">
  2. void USR_UartInit(void)
  3. {
  4.     test1++;

  5.     uart8RxLength = 0;   
  6.     HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
  7.     uart7RxLength = 0;   
  8.     HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
  9.     uart6RxLength = 0;   
  10.     HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);   

  11.     __HAL_UART_ENABLE_IT(&huart8, UART_IT_IDLE);     
  12.     __HAL_UART_ENABLE_IT(&huart7, UART_IT_IDLE);   
  13.     __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);   
  14. }
  15. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  16. {

  17.     HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
  18.     HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
  19.     HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
  20.     __HAL_DMA_ENABLE(&hdma_uart8_rx);
  21.     __HAL_DMA_ENABLE(&hdma_uart7_rx);
  22.     __HAL_DMA_ENABLE(&hdma_usart6_rx);
  23.     test2++;
  24. }
  25. uint8_t RxLenHi, RxLenlo;  
  26. void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
  27. {
  28.     __HAL_UART_CLEAR_IDLEFLAG(huart);

  29.         if( huart == &huart8)
  30.         {
  31.             test3++;
  32.             HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);  

  33.             uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx);     
  34.             if(uart8Rx[0]=='@'
  35.             &&uart8Rx[1]=='c'
  36.             &&uart8Rx[2]=='m'
  37.             &&uart8Rx[3]=='d')
  38.             {
  39.                 if(!SERDEB_CmdValid())
  40.                     SERDEB_PushCmd(uart8Rx, uart8RxLength);
  41.             }
  42.             __HAL_DMA_DISABLE(&hdma_uart8_rx);
  43.             HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);   
  44.         }

  45.           if( huart == &huart7)
  46.         {        
  47.             __HAL_DMA_DISABLE(&hdma_uart7_rx);  
  48.             HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
  49.             __HAL_DMA_DISABLE(&hdma_uart7_rx);
  50.         }

  51.         if( huart == &huart6)
  52.         {
  53.             __HAL_DMA_DISABLE(&hdma_usart6_rx);
  54.             HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
  55.             __HAL_DMA_DISABLE(&hdma_usart6_rx);
  56.         }

  57. }</font>
复制代码
至此完成了双工通信的基本配置。




收藏 评论0 发布时间:2021-7-26 11:27

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版