STM32与匿名上位机通信——使用串口DMA实现

2023-02-18,,,,

背景:匿名上位机功能强大,这里想要采用匿名上位机输出一些调试信息,以波形的形式显示,方便观察和调试。

平台:

硬件:STM32F405RGT6

通信:2.4G zigbee无线串口收发模块 CC2530

软件:匿名上位机V6

数传模块操作简介:

配置 代码:(注意以下代码中不包含中断优先级的配置,个人习惯将所有nvic的配置写在一个单独的函数中)

这里采用UART2 DMA发送的方式 将数据通过数传发送给匿名上位机。采用DMA传输完成中断,可以实现不定长数据的传输。

/* usart2 for debug (Ano) */
void vUart2Config(void)
{
USART_InitTypeDef usart2;
GPIO_InitTypeDef gpio; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); gpio.GPIO_Pin = GPIO_Pin_2;
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Speed = GPIO_Speed_100MHz;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&gpio); gpio.GPIO_Pin = GPIO_Pin_3;
gpio.GPIO_Mode = GPIO_Mode_IN;
gpio.GPIO_Speed = GPIO_Speed_100MHz;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&gpio); USART_DeInit(USART2);
/* zigbee digital transmiter support up to 115200 */
usart2.USART_BaudRate = 115200;
usart2.USART_WordLength = USART_WordLength_8b;
usart2.USART_StopBits = USART_StopBits_1;
usart2.USART_Parity = USART_Parity_No;
usart2.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
usart2.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2,&usart2); USART_Cmd(USART2,ENABLE); USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE); /* send dma */
{
DMA_InitTypeDef dma; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
DMA_DeInit(DMA1_Stream6);
dma.DMA_Channel= DMA_Channel_4;
dma.DMA_PeripheralBaseAddr = (uint32_t)&(USART2->DR);
dma.DMA_Memory0BaseAddr = (uint32_t)SendToAno_Buff;
dma.DMA_DIR = DMA_DIR_MemoryToPeripheral;
dma.DMA_BufferSize = USART2_ANO_DMA_send_buffersize;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
dma.DMA_Priority = DMA_Priority_VeryHigh;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
dma.DMA_MemoryBurst = DMA_Mode_Normal;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream6,&dma); DMA_ITConfig(DMA1_Stream6,DMA_IT_TC,ENABLE);
/* enable dma when data preparing finish */
DMA_Cmd(DMA1_Stream6,DISABLE);
}
} /* uart2 DMA send finish interrupt : send debug date (Ano) */
void DMA1_Stream6_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA1_Stream6, DMA_IT_TCIF6) == SET)
{
DMA_Cmd(DMA1_Stream6, DISABLE);
DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6);
DMA_ClearITPendingBit(DMA1_Stream6, DMA_IT_TCIF6);
}
}

DMA发送函数:(初始化时不使能DMA,当数据准备好之后,根据待发送的数据长度,设定DMA发送的长度,同时使能DMA,启动一次发送,当每次DMA发送完成后,在传输完成中断中,关闭DMA,等待下一次数据准备好,循环以上过程)

/* start once usart2 dma send (for ANO) */
static void USART2_ANO_DMA_SEND(uint16_t sendsize)
{
DMA_Cmd(DMA1_Stream6, DISABLE);
/* set dma sendbuffer size */
DMA_SetCurrDataCounter(DMA1_Stream6, sendsize);
/* start usart dma send */
DMA_Cmd(DMA1_Stream6, ENABLE);
}

匿名上位机数据打包及循环发送:(使用的是匿名V6版本的上位机,具体协议请参考对应版本的上位机协议,这里使用匿名上位机提供的用户数据格式发送数据,ID分别为F1,F2,F3的三组不定长数据)

/* accroding to ANO earth station V6 protocol: userdata */
void ANOSend(void)
{
static uint8_t ANO_dataid = 1;
static uint16_t test_count = 0;
uint8_t senddata_cnt = 0;
uint8_t sumcheck = 0;
uint8_t errorcode_sum = 0;
int16_t yawAngle_100 = 0;
int16_t pitchAngle_100 = 0;
int16_t pctarget_yawAngle_100 = 0;
int16_t pctarget_pitchAngle_100 = 0;
int16_t sintest_data_100 = 0; switch(ANO_dataid)
{
/* id1 (F1) send gimbal angle */
case 1:
{
senddata_cnt = 0;
errorcode_sum = 0; SendToAno_Buff[senddata_cnt++] = 0xAA;
SendToAno_Buff[senddata_cnt++] = 0x05;
SendToAno_Buff[senddata_cnt++] = 0xAF;
SendToAno_Buff[senddata_cnt++] = (0xF0+ANO_dataid); /* jump over the data length byte */
senddata_cnt++; /* int16_t yawAngle */
yawAngle_100 = (int16_t)(imu.yawAngle*100);
SendToAno_Buff[senddata_cnt++] = BYTE1(yawAngle_100);
SendToAno_Buff[senddata_cnt++] = BYTE0(yawAngle_100); /* int16_t pitchAngle */
pitchAngle_100 = (int16_t)(imu.pitchAngle*100);
SendToAno_Buff[senddata_cnt++] = BYTE1(pitchAngle_100);
SendToAno_Buff[senddata_cnt++] = BYTE0(pitchAngle_100); SendToAno_Buff[4] = senddata_cnt-5; /* sum check calculate */
sumcheck = 0; for(uint8_t i=0; i < (SendToAno_Buff[4]+5); i++)
{
sumcheck += SendToAno_Buff[i];
} SendToAno_Buff[senddata_cnt++] = sumcheck; USART2_ANO_DMA_SEND(senddata_cnt); break;
} /* id2 (F2) send PC data */
case 2:
{
senddata_cnt = 0; SendToAno_Buff[senddata_cnt++] = 0xAA;
SendToAno_Buff[senddata_cnt++] = 0x05;
SendToAno_Buff[senddata_cnt++] = 0xAF;
SendToAno_Buff[senddata_cnt++] = (0xF0+ANO_dataid); /* jump over the data length byte */
senddata_cnt++; /* int16_t PCtarget_yawangle */
pctarget_yawAngle_100 = (int16_t)(PC_Recv.PCTargetYaw*100);
SendToAno_Buff[senddata_cnt++] = BYTE1(pctarget_yawAngle_100);
SendToAno_Buff[senddata_cnt++] = BYTE0(pctarget_yawAngle_100); /* int16_t PCtarget_pitchangle */
pctarget_pitchAngle_100 = (int16_t)(PC_Recv.PCTargetPitch*100);
SendToAno_Buff[senddata_cnt++] = BYTE1(pctarget_pitchAngle_100);
SendToAno_Buff[senddata_cnt++] = BYTE0(pctarget_pitchAngle_100); SendToAno_Buff[4] = senddata_cnt-5; /* sum check calculate */
sumcheck = 0; for(uint8_t i=0; i < (SendToAno_Buff[4]+5); i++)
{
sumcheck += SendToAno_Buff[i];
} SendToAno_Buff[senddata_cnt++] = sumcheck; USART2_ANO_DMA_SEND(senddata_cnt); break;
} /* id2 (F3) send test data */
case 3:
{
senddata_cnt = 0;
test_count++; SendToAno_Buff[senddata_cnt++] = 0xAA;
SendToAno_Buff[senddata_cnt++] = 0x05;
SendToAno_Buff[senddata_cnt++] = 0xAF;
SendToAno_Buff[senddata_cnt++] = (0xF0+ANO_dataid); /* jump over the data length byte */
senddata_cnt++; /* int16_t test_sindata 100times */
sintest_data_100 = (int16_t)(sin((float)test_count*3.14f/180.0f)*100);
SendToAno_Buff[senddata_cnt++] = BYTE1(sintest_data_100);
SendToAno_Buff[senddata_cnt++] = BYTE0(sintest_data_100); SendToAno_Buff[4] = senddata_cnt-5; /* sum check calculate */
sumcheck = 0; for(uint8_t i=0; i < (SendToAno_Buff[4]+5); i++)
{
sumcheck += SendToAno_Buff[i];
} SendToAno_Buff[senddata_cnt++] = sumcheck; USART2_ANO_DMA_SEND(senddata_cnt); break;
}
} ANO_dataid++; /* choose the return number */
if(ANO_TEST)
{
if(ANO_dataid >= 4)
{
ANO_dataid = 1;
}
}
else if(!ANO_TEST)
{
if(ANO_dataid >= 3)
{
ANO_dataid = 1;
}
}
}

——cloud over sky

——2020/3/7

STM32与匿名上位机通信——使用串口DMA实现的相关教程结束。

《STM32与匿名上位机通信——使用串口DMA实现.doc》

下载本文的Word格式文档,以方便收藏与打印。