欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-09 10:58:10
...

 

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

平台:

硬件:STM32F405RGT6

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

软件:匿名上位机V6

数传模块操作简介:

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

配置 代码:(注意以下代码中不包含中断优先级的配置,个人习惯将所有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基础