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)的波特率
- <font face="微软雅黑" size="3">def __init__(self):
- print("move init finish")
- self.time1 = time.time()
- self.time2 = time.time()
- self.flag = False
- self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)
- # print('port_chassis is :' + self.port_chassis.is_Open())
- self.port_chassis.flushInput()
- self.port_chassis.flushOutput()</font>
复制代码 接下来就是发送数据,我们的购物机器人是通过树莓派做为整个的 “大脑”,是由树莓派里的python脚本给底盘发送指令,所以这个函数就是python让底盘移动distance个格子的函数,这个函数里面也是通过USART(UART)给底盘发送指令的,所用函数就是self.port_chassis.write((direction + str(distance)).encode())
- <font face="微软雅黑" size="3"> def move_by_grid(self, direction, distance=''):
- # print('move by grid')
- self.port_chassis.write((direction + str(distance)).encode())
- self.time1 = time.time()
- print(direction + str(distance))
- self.wait_for_act_end_signal_chassis(direction, distance)</font>
复制代码 最后是接收数据,既然树莓派要控制底盘,树莓派自然也要接收到底盘回传的数据,这里用到的USART(UART)接收数据函数是self.port_chassis.readline().decode(),sig就是树莓派接收到的USART(UART)数据,用户就可以对其做处理啦。
- <font face="微软雅黑" size="3">def wait_for_act_end_signal_chassis(self, ret=None, distance=0):
- print('waiting chassis...')
- while True:
- sig = self.port_chassis.readline().decode()
-
- # print(self.time2 - self.time1)
-
- sig = sig[0:2]
- print(sig)
- #
- if sig == 'HI':
- self.time2 = time.time()
- print(self.time2 - self.time1)
- if self.time2 - self.time1 < 1.0 and self.flag == False and distance == 1:
- print('1 step deal error')
- self.flag = True
- if (ret == dir_up or ret == dir_back):
- self.move_by_grid(ret, 1)
- else:</font>
复制代码
2. STM32F427IIH6
在嵌入式芯片STM32F427IIH6里,我们首先要打开芯片的DMA功能,然后进行USART(UART)的初始化,最后设置USART(UART)的回调函数即可。
首先进行DMA的初始化,在这些初始化里面完成的就是DMA时钟的使能和DMA中断的使能。
- <font face="微软雅黑" size="3">void MX_DMA_Init(void)
- {
-
- /* DMA controller clock enable */
- __HAL_RCC_DMA1_CLK_ENABLE();
- __HAL_RCC_DMA2_CLK_ENABLE();
-
- /* DMA interrupt init */
- /* DMA1_Stream0_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
- /* DMA1_Stream1_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
- /* DMA1_Stream3_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
- /* DMA1_Stream6_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
- /* DMA2_Stream1_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
- /* DMA2_Stream6_IRQn interrupt configuration */
- HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);
- HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
-
- }
- </font>
复制代码 DMA使能完成之后就要进行USART(UART)的基本配置了,这里我设置的就是波特率9600(各个USART(UART)波特率初始化大同小异,因此在这里只放了usart6的初始化,其他类似,不做赘述)。
- <font face="微软雅黑" size="3">void MX_USART6_UART_Init(void)
- {
-
- huart6.Instance = USART6;
- huart6.Init.BaudRate = 9600;
- huart6.Init.WordLength = UART_WORDLENGTH_8B;
- huart6.Init.StopBits = UART_STOPBITS_1;
- huart6.Init.Parity = UART_PARITY_NONE;
- huart6.Init.Mode = UART_MODE_TX_RX;
- huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart6.Init.OverSampling = UART_OVERSAMPLING_16;
- if (HAL_UART_Init(&huart6) != HAL_OK)
- {
- Error_Handler();
- }
-
- }</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)接收到的数组数据 啦,接下来用户就可以对其做处理啦。
- <font face="微软雅黑" size="3">
- void USR_UartInit(void)
- {
- test1++;
-
- uart8RxLength = 0;
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
- uart7RxLength = 0;
- HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
- uart6RxLength = 0;
- HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
-
- __HAL_UART_ENABLE_IT(&huart8, UART_IT_IDLE);
- __HAL_UART_ENABLE_IT(&huart7, UART_IT_IDLE);
- __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
- }
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
-
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
- HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
- HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
- __HAL_DMA_ENABLE(&hdma_uart8_rx);
- __HAL_DMA_ENABLE(&hdma_uart7_rx);
- __HAL_DMA_ENABLE(&hdma_usart6_rx);
- test2++;
- }
- uint8_t RxLenHi, RxLenlo;
- void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
- {
- __HAL_UART_CLEAR_IDLEFLAG(huart);
-
- if( huart == &huart8)
- {
- test3++;
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
-
- uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx);
- if(uart8Rx[0]=='@'
- &&uart8Rx[1]=='c'
- &&uart8Rx[2]=='m'
- &&uart8Rx[3]=='d')
- {
- if(!SERDEB_CmdValid())
- SERDEB_PushCmd(uart8Rx, uart8RxLength);
- }
- __HAL_DMA_DISABLE(&hdma_uart8_rx);
- HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);
- }
-
- if( huart == &huart7)
- {
- __HAL_DMA_DISABLE(&hdma_uart7_rx);
- HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
- __HAL_DMA_DISABLE(&hdma_uart7_rx);
- }
-
- if( huart == &huart6)
- {
- __HAL_DMA_DISABLE(&hdma_usart6_rx);
- HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
- __HAL_DMA_DISABLE(&hdma_usart6_rx);
- }
-
- }</font>
复制代码 至此完成了双工通信的基本配置。
|