文章目录
- 运行环境:
- 1.1 DBUS协议解析
- 1)DT7遥控
- 2)配置串口引脚
- 3)配置串口接收DMA
- 2.1例程代码移植
- 1)例程移动到 Inc 和 Src
- 2)makefile添加.c文件
- 3.1核心代码解释
- 4.1代码修改
- 1)bsp_rc.c 和 remote_control.c
- 2)调用代码
- 5.1调试
- 1)硬件接线
- 2)串口工具监视拨杆数据
运行环境:
ubuntu18.04.melodic
宏基暗影骑士笔记本
stm32f427IIH6
stlink
9-24v可调电源
usb转串口
杜邦线转4pin
DBUS遥控
接收机
1.1 DBUS协议解析
1)DT7遥控
DT7遥控示意图:每个通道由11位数据控制
2)配置串口引脚
详情见:USART串口发送
UASRT6
发送TX_PG14
接收RX_PG9
3)配置串口接收DMA
串口接收DMA:接收由遥控发送过来的数据
DBUS 的传输速率为 100k bit/s,数据长度为 8 位,奇偶校验位为偶校验,结束位 1 位。
串口6接收DMA
环形储存器
打开串口全局中断
2.1例程代码移植
1)例程移动到 Inc 和 Src
2)makefile添加.c文件
3.1核心代码解释
每个通道由11位数据控制
rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff;
sbus_buf[1] << 8是将pData[1]左移8位到高8位,然后和sbus_buf[0]的pData[0]进行与运算, 拼接成左下图的16位
然后和0x07ff(0x07ff二进制是1111111111)进行或运算,取出后11位。
rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff
同理,sbus_buf[1] >> 3是将pData[1]右移3位,舍弃3位,保留低5位。
sbus_buf[2] << 5是将pData[2]左移5位,然后拼接如右下图,取后11位。
4.1代码修改
1)bsp_rc.c 和 remote_control.c
bsp_rc.c 文件是串口3的初始化, 我们用的是串口6,需要修改代码。
remote_control.c是对数据进行处理和解析,我们用的是串口6,需要修改代码。
void RC_init(uint8_t *rx1_buf, uint8_t *rx2_buf, uint16_t dma_buf_num)
{
//enable the DMA transfer for the receiver request
SET_BIT(huart6.Instance->CR3, USART_CR3_DMAR);
//enalbe idle interrupt
__HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
//disable DMA
__HAL_DMA_DISABLE(&hdma_usart6_rx);
while(hdma_usart6_rx.Instance->CR & DMA_SxCR_EN)
{
__HAL_DMA_DISABLE(&hdma_usart6_rx);
}
hdma_usart6_rx.Instance->PAR = (uint32_t) & (USART6->DR);
//memory buffer 1
hdma_usart6_rx.Instance->M0AR = (uint32_t)(rx1_buf);
//memory buffer 2
hdma_usart6_rx.Instance->M1AR = (uint32_t)(rx2_buf);
//data length
hdma_usart6_rx.Instance->NDTR = dma_buf_num;
//enable double memory buffer
SET_BIT(hdma_usart6_rx.Instance->CR, DMA_SxCR_DBM);
//enable DMA
__HAL_DMA_ENABLE(&hdma_usart6_rx);
}
extern UART_HandleTypeDef huart6;
extern DMA_HandleTypeDef hdma_USART6_rx;
/**
* @brief remote control protocol resolution
* @param[in] sbus_buf: raw data point
* @param[out] rc_ctrl: remote control data struct point
* @retval none
*/
/**
* @brief ң����Э�����
* @param[in] sbus_buf: ԭ������ָ��
* @param[out] rc_ctrl: ң��������ָ
* @retval none
*/
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl);
//remote control data
//ң�������Ʊ���
RC_ctrl_t rc_ctrl;
//receive data, 18 bytes one frame, but set 36 bytes
//����ԭʼ���ݣ�Ϊ18���ֽڣ�����36���ֽڳ��ȣ���ֹDMA����Խ��
static uint8_t sbus_rx_buf[2][SBUS_RX_BUF_NUM];
/**
* @brief remote control init
* @param[in] none
* @retval none
*/
/**
* @brief ң������ʼ��
* @param[in] none
* @retval none
*/
void remote_control_init(void)
{
RC_init(sbus_rx_buf[0], sbus_rx_buf[1], SBUS_RX_BUF_NUM);
}
/**
* @brief get remote control data point
* @param[in] none
* @retval remote control data point
*/
/**
* @brief ��ȡң��������ָ��
* @param[in] none
* @retval ң��������ָ��
*/
const RC_ctrl_t *get_remote_control_point(void)
{
return &rc_ctrl;
}
//�����ж�
void USART6_IRQHandler(void)
{
if(huart6.Instance->SR & UART_FLAG_RXNE)//���յ�����
{
__HAL_UART_CLEAR_PEFLAG(&huart6);
}
else if(USART6->SR & UART_FLAG_IDLE)
{
static uint16_t this_time_rx_len = 0;
__HAL_UART_CLEAR_PEFLAG(&huart6);
if ((hdma_USART6_rx.Instance->CR & DMA_SxCR_CT) == RESET)
{
/* Current memory buffer used is Memory 0 */
//disable DMA
//ʧЧDMA
__HAL_DMA_DISABLE(&hdma_USART6_rx);
//get receive data length, length = set_data_length - remain_length
//��ȡ�������ݳ���,���� = �趨���� - ʣ���
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_USART6_rx.Instance->NDTR;
//reset set_data_lenght
//�����趨���ݳ���
hdma_USART6_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
//set memory buffer 1
//�趨������1
hdma_USART6_rx.Instance->CR |= DMA_SxCR_CT;
//enable DMA
//ʹ��DMA
__HAL_DMA_ENABLE(&hdma_USART6_rx);
if(this_time_rx_len == RC_FRAME_LENGTH)
{
sbus_to_rc(sbus_rx_buf[0], &rc_ctrl);
}
}
else
{
/* Current memory buffer used is Memory 1 */
//disable DMA
//ʧЧDMA
__HAL_DMA_DISABLE(&hdma_USART6_rx);
//get receive data length, length = set_data_length - remain_length
//��ȡ�������ݳ���,���� = �趨���� - ʣ���
this_time_rx_len = SBUS_RX_BUF_NUM - hdma_USART6_rx.Instance->NDTR;
//reset set_data_lenght
//�����趨���ݳ���
hdma_USART6_rx.Instance->NDTR = SBUS_RX_BUF_NUM;
//set memory buffer 0
//�趨������0
DMA1_Stream1->CR &= ~(DMA_SxCR_CT);
//enable DMA
//ʹ��DMA
__HAL_DMA_ENABLE(&hdma_USART6_rx);
if(this_time_rx_len == RC_FRAME_LENGTH)
{
//����ң��������
sbus_to_rc(sbus_rx_buf[1], &rc_ctrl);
}
}
}
}
/**
* @brief remote control protocol resolution
* @param[in] sbus_buf: raw data point
* @param[out] rc_ctrl: remote control data struct point
* @retval none
*/
/**
* @brief ң����Э�����
* @param[in] sbus_buf: ԭ������ָ��
* @param[out] rc_ctrl: ң��������ָ
* @retval none
*/
static void sbus_to_rc(volatile const uint8_t *sbus_buf, RC_ctrl_t *rc_ctrl)
{
if (sbus_buf == NULL || rc_ctrl == NULL)
{
return;
}
rc_ctrl->rc.ch[0] = (sbus_buf[0] | (sbus_buf[1] << 8)) & 0x07ff; //!< Channel 0
rc_ctrl->rc.ch[1] = ((sbus_buf[1] >> 3) | (sbus_buf[2] << 5)) & 0x07ff; //!< Channel 1
rc_ctrl->rc.ch[2] = ((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) | //!< Channel 2
(sbus_buf[4] << 10)) &0x07ff;
rc_ctrl->rc.ch[3] = ((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff; //!< Channel 3
rc_ctrl->rc.s[0] = ((sbus_buf[5] >> 4) & 0x0003); //!< Switch left
rc_ctrl->rc.s[1] = ((sbus_buf[5] >> 4) & 0x000C) >> 2; //!< Switch right
rc_ctrl->mouse.x = sbus_buf[6] | (sbus_buf[7] << 8); //!< Mouse X axis
rc_ctrl->mouse.y = sbus_buf[8] | (sbus_buf[9] << 8); //!< Mouse Y axis
rc_ctrl->mouse.z = sbus_buf[10] | (sbus_buf[11] << 8); //!< Mouse Z axis
rc_ctrl->mouse.press_l = sbus_buf[12]; //!< Mouse Left Is Press ?
rc_ctrl->mouse.press_r = sbus_buf[13]; //!< Mouse Right Is Press ?
rc_ctrl->key.v = sbus_buf[14] | (sbus_buf[15] << 8); //!< KeyBoard value
rc_ctrl->rc.ch[4] = sbus_buf[16] | (sbus_buf[17] << 8); //NULL
rc_ctrl->rc.ch[0] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[1] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[2] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[3] -= RC_CH_VALUE_OFFSET;
rc_ctrl->rc.ch[4] -= RC_CH_VALUE_OFFSET;
}
2)调用代码
main.c中包含头文件
#include "bsp_rc.h"
#include "remote_control.h"
定义一个变量储存区(结构体指针)
const RC_ctrl_t *local_rc_ctrl;
初始化串口
初始化储存区
remote_control_init();
local_rc_ctrl = get_remote_control_point();
添加串口输出代码到while循环中
usart_printf(
"**********\r\n\
ch0:%d\r\n\
ch1:%d\r\n\
ch2:%d\r\n\
ch3:%d\r\n\
ch4:%d\r\n\
s1:%d\r\n\
s2:%d\r\n\
mouse_x:%d\r\n\
mouse_y:%d\r\n\
press_l:%d\r\n\
press_r:%d\r\n\
key:%d\r\n\
**********\r\n",
local_rc_ctrl->rc.ch[0], local_rc_ctrl->rc.ch[1], local_rc_ctrl->rc.ch[2], local_rc_ctrl->rc.ch[3], local_rc_ctrl->rc.ch[4],
local_rc_ctrl->rc.s[0], local_rc_ctrl->rc.s[1],
local_rc_ctrl->mouse.x, local_rc_ctrl->mouse.y,local_rc_ctrl->mouse.z, local_rc_ctrl->mouse.press_l, local_rc_ctrl->mouse.press_r,
local_rc_ctrl->key.v);
HAL_Delay(200);
添加void usart_printf()函数定义
void usart_printf(const char *fmt,...)
{
static uint8_t tx_buf[256] = {0};
static va_list ap;
static uint16_t len;
va_start(ap, fmt);
//return length of string
//�����ַ�������
len = vsprintf((char *)tx_buf, fmt, ap);
va_end(ap);
// usart1_tx_dma_enable(tx_buf, len);
}
修改bsp_rc.h和remote_control.h
注释stm32f4xx_it.c中重复定义的串口6中断服务函数(remote_control.c中已经定义过了)
5.1调试
1)硬件接线
接收机插A板的dbus接口
对频: 按住接收机的孔,然后打开遥控器
2)串口工具监视拨杆数据
sudo cutecom
make
F5调试运行