匿名上位机数据波形显示以及下位机参数调试

本文介绍了博主如何使用匿名上位机v7与STM32F103C8T6单片机通过串口进行数据通信,包括数据帧结构、小端模式处理、校验算法以及如何利用上位机绘制波形并调试STM32特定参数。
摘要由CSDN通过智能技术生成

前言:

        博主所选用上位机为匿名上位机v7,下位机为stm32,所用MCU为f103c8t6,进行一个简单的上位机显示数据的波形和对单片机指定参数的调试。

        大概的思路为匿名上位机与stm32串口通信,在windows端匿名上位机绘制实时数据波形,并实现在遵循通信协议的前提下实现对下位机的某指定参数的修改,从而达到便捷调试的目的。

接线图:

7f8869b9e1554c59b0ec34040f2f1185.jpeg

匿名上位机接收stm32发送数据的通信帧格式:

b827d1cf579540d88d4becea51a9941c.png

DATA 数据内容中的数据,采用小端模式,低字节在前,高字节在后。
注意:不能发送小数,需要将小数乘以10的n次方再发送,之后在匿名上位机v7端设置接收数据的放大倍数为1/10^n即可接收到原始数据。
和校验 SUM CHECK 计算方法:
从帧头 0xAA 字节开始,一直到 DATA 区结束,对每一字节进行累加操作,只取低 8 位
附加校验 ADD CHECK 计算方法:
计算和校验时,每进行一字节的加法运算,同时进行一次 SUM CHECK 的累加操作,只取低 8 位。
校验计算示例:
假设数据帧缓存为 data_buf 数组,0xAA 存放于数组起始位置,那么 data_buf[3]存放的是数据长度,校验程序
如下:
uint8_t sumcheck = 0 ;
uint8_t addcheck = 0 ;
for (u8 i =0 ; I < (data_buf [3 ]+4 ); i ++)
{
sumcheck += data_buf [i ];
//从帧头开始,对每一字节进行求和,直到DATA区结束
addcheck += sumcheck ;
//每一字节的求和操作,进行一次sumcheck的累加
}
//如果计算出的sumcheck和addcheck和接收到的check数据相等,代表校验通过,反之数据有误
if (sumcheck == data_buf [data_buf [3 ]+4 ] && addcheck == data_buf [data_buf [3 ]+5 ])
        return true ;
//校验通过
else
        return false ; //校验失败
采取灵活格式帧
 

stm32接收匿名上位机发送的数据通信帧格式:

帧头1帧头2目标调参id参数改变量的绝对值正/负帧尾
0xAA0xAE00 00 00 009F 06 00 000xBF0xAC
固定值固定值01 00 00 00将十进制转换成16进制,补足8位,两个位为一组,高低位互换。0xCF固定值
02 00 00 000xBF为正增量
0,1,2分别表示第1/2/3个参数0xCF为负增量
10进制1695转成16进制为00 00 06 9F高低位互换后为9F 06 00 00 

帧头1: 0xAA

帧头2: 0xAE

指定参数id: 00 00 00 00 / 01 00 00 00 / 02 00 00 00  分别表示指参数variable_1,variable_2,variable_3

增量的绝对值: 9F 09 01 02 将十进制转换成16进制,补足8位,两个位为一组,高低位互换。

增量的正负: 0xBF / 0xCF     0xBF表示增量为正  0xCF表示增量为负

帧尾: 0xAC

Serial.h

#ifndef __SERIAL_H
#define __SERIAL_H
extern uint8_t Serial_RxPacket[];
void USART1_Init(void);
void UsartSendByte(uint8_t Byte);
void USART1_IRQHandler(void);
void sent_data(uint16_t A,uint16_t B,uint16_t C);
uint8_t Serial_GetRxFlag(void);
extern int variable_1,variable_2,variable_3;
#endif

Serial.c

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
//cup为小端模式存储,也就是在存储的时候,低位被存在0字节,高位在1字节
#define BYTE0(dwTemp)       (*(char *)(&dwTemp))	 //取出int型变量的低字节
#define BYTE1(dwTemp)       (*((char *)(&dwTemp) + 1))	 //	取存储在此变量下一内存字节的内容,高字节
#define BYTE2(dwTemp)       (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp)       (*((char *)(&dwTemp) + 3))
#define data_length 8
uint8_t receive_data[data_length+1];
uint8_t Serial_RxFlag;					//定义接收数据包标志位

int variable_id;						//指定需要改变的变量
int variation;  						//指定改变量大小
int variable_1,variable_2,variable_3;
uint8_t BUFF[30];
//windows端匿名上位机发送数据格式 AA AE 00 00 00 00 A6 09 00 00 BF/CF AC
//AA AE固定表示为两个帧头
//00 00 00 00表示指定改变variable_1
//01 00 00 00表示指定改变variable_2
//02 00 00 00表示指定改变variable_3
//A6 09 00 00表示改变量的绝对值variation 可以通过十进制转十六进制,两位一对,高低位互换获得
//exampe: 十进制2470   -->   十六进制  9a6 
//补零+大写后为   00 00 09 A6
//高低位互换为    A6 09 00 00
// BF表示变化量为正  CF表示变化量为负
// AC表示帧尾
void USART1_Init(void)
{
	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟

	//USART1_TX   GPIOA.9
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9

	//USART1_RX	  GPIOA.10初始化
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

	//USART 初始化设置

	USART_InitStructure.USART_BaudRate = 9600;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

	USART_Init(USART1, &USART_InitStructure); //初始化串口1
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
	USART_Cmd(USART1, ENABLE);                    //使能串口1 
}

/**
  * 函    数:串口发送一个字节
  * 参    数:Byte 要发送的一个字节
  * 返 回 值:无
  */
void UsartSendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);		//将字节数据写入数据寄存器,写入后USART自动生成时序波形
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	//等待发送完成
	/*下次写入数据寄存器会自动清除发送完成标志位,故此循环后,无需清除标志位*/
}

void sent_data(uint16_t A,uint16_t B,uint16_t C)
{
	int i;
	uint8_t sumcheck = 0;
	uint8_t addcheck = 0;
	uint8_t _cnt=0;
	BUFF[_cnt++]=0xAA;			//帧头
	BUFF[_cnt++]=0xFF;			//目标地址
	BUFF[_cnt++]=0XF1;			//功能码
	BUFF[_cnt++]=0x06;			//数据长度
	BUFF[_cnt++]=BYTE0(A);		//数据内容,小段模式,低位在前
	BUFF[_cnt++]=BYTE1(A);		//需要将字节进行拆分,调用上面的宏定义即可。
	BUFF[_cnt++]=BYTE0(B);
	BUFF[_cnt++]=BYTE1(B);	
	BUFF[_cnt++]=BYTE0(C);
	BUFF[_cnt++]=BYTE1(C);
	//SC和AC的校验
	for(i=0;i<BUFF[3]+4;i++) 
	{
		sumcheck+=BUFF[i];
		addcheck+=sumcheck;
	}
	BUFF[_cnt++]=sumcheck;	
	BUFF[_cnt++]=addcheck;
	for(i=0;i<_cnt;i++) 
	{
		UsartSendByte(BUFF[i]);	     //串口逐个发送数据
	}
}

/**
  * 函    数:获取串口接收数据包标志位
  * 参    数:无
  * 返 回 值:串口接收数据包标志位,范围:0~1,接收到数据包后,标志位置1,读取后标志位自动清零
  */
uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)			//如果标志位为1
	{
		Serial_RxFlag = 0;
		return 1;					//则返回1,并自动清零标志位
	}
	return 0;						//如果标志位为0,则返回0
}

/**
  * 函    数:USART1中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void USART1_IRQHandler(void)
{
	static uint8_t RxState = 0;		//定义表示当前状态机状态的静态变量
	static uint8_t pRxPacket = 0;	//定义表示当前接收数据位置的静态变量
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		//判断是否是USART1的接收事件触发的中断
	{
		uint8_t RxData = USART_ReceiveData(USART1);				//读取数据寄存器,存放在接收的数据变量
		
		/*使用状态机的思路,依次处理数据包的不同部分*/

		/*当前状态为0,接收数据包包头*/
		if (RxState == 0)
		{
			if (RxData == 0xAA)			//如果数据确实是包头
			{
				RxState = 1;			//置下一个状态			//数据包的位置归零
			}
		}
		/*当前状态为1,接收数据包数据*/
		else if (RxState == 1)
		{
			if (RxData == 0xAE)
			{
				RxState = 2;
				pRxPacket = 0;
			}
		}
		/*当前状态为2,接收数据包包尾*/
		else if (RxState == 2)
		{
			receive_data[pRxPacket] = RxData;	//将数据存入数据包数组的指定位置
			pRxPacket ++;				//数据包的位置自增
			if (pRxPacket >= 9)			//如果收够9个数据
			{
				RxState = 3;			//置下一个状态
			}
		}
		else if(RxState == 3)
		{
			if (RxData == 0xAC)			//如果数据确实是包尾部
			{
				RxState = 0;			//状态归0
				Serial_RxFlag = 1;		//接收数据包标志位置1,成功接收一个数据包	
			}
		}
		variable_id = receive_data[3] << 24 | receive_data[2] << 16 | receive_data[1] << 8 | receive_data[0];//位移运算,将hex16进制转换成int整型
		if(receive_data[data_length] == 0xBF)
		{
			variation = (receive_data[7] << 24 | receive_data[6] << 16 | receive_data[5] << 8 | receive_data[4]);
		}
		else if(receive_data[data_length] == 0xCF)
		{
			variation = -(receive_data[7] << 24 | receive_data[6] << 16 | receive_data[5] << 8 | receive_data[4]);
		}
		if(variable_id == 0)
		{
			variable_1 = variation;//00 00 00 00 -> variable_1
		}
		else if(variable_id == 1)
		{
			variable_2 = variation;//01 00 00 00 -> variable_2
		}
		else if(variable_id == 2)
		{
			variable_3 = variation;//02 00 00 00 -> variable_3
		}
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);	//清除标志位
	}
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	USART1_Init();		//串口初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Var1:");
	OLED_ShowString(2, 1, "Var2:");
	uint16_t A=0, B=2;
	uint16_t C;
	
	while (1)
	{
	C = A + B;
	sent_data(A,B,C);
	Delay_ms(100);
	A = variable_1;
	B = variable_2;
	OLED_ShowSignedNum(1,5,variable_1,8);
	OLED_ShowSignedNum(2,5,variable_2,8);
	}
}

匿名上位机:

1.连接设置

选择所用到的串口号,波特率设置为9600

42e362ec1e5141009cdce089119ad1ee.png

 2.使能F1用户帧,传输缩放设置为1,数据类型和stm32发送的数据类型保持一致uint16

18973227c64b4796a3991e9a156c86e4.png

3.打开数据波形显示

f007c552dcd14ab28004ea2fd7ab1fef.png

总结

以上就是全部内容,包括四轴匿名上位机的使用、通信协议和一些接收发送代码。

若有不当之处,欢迎指出。

 

stm32发送数据匿名上位机接收参考:匿名上位机V7波形显示教程-简单能用-CSDN博客

上位机发送数据stm32接收参考视频:【STM32入门教程-2023版 细致讲解 中文字幕】 https://www.bilibili.com/video/BV1th411z7sn/?p=29&share_source=copy_web&vd_source=9ec6c39a21d0abd9b95bab21aa05a11d

 

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的示例代码,可以使用STM32匿名上位机通过串口通信并实时显示波形。 首先,需要在STM32上设置串口通信。在示例代码中,我们使用USART2和PA2 / PA3引脚进行串口通信。使用CubeMX可以轻松配置串口。 ```c /* Includes */ #include "main.h" #include "stdio.h" /* Private variables */ UART_HandleTypeDef huart2; /* Private function prototypes */ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); int main(void) { /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART2_UART_Init(); /* Infinite loop */ while (1) { /* Send data through UART */ char buffer[50]; sprintf(buffer, "Hello World!\r\n"); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); /* Delay for 1 second */ HAL_Delay(1000); } } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /** * @brief USART2 Initialization Function * @param None * @retval None */ static void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } ``` 接下来,我们需要在STM32上实现波形显示。这可以通过使用ADC和DMA来实现。示例代码中,我们将PA0连接到STM32的ADC1通道,并使用DMA将ADC值传输到内存中。然后,我们可以使用这些值来绘制波形。 ```c /* Includes */ #include "main.h" #include "stdio.h" #include "math.h" /* Private variables */ UART_HandleTypeDef huart2; ADC_HandleTypeDef hadc1; DMA_HandleTypeDef hdma_adc1; /* Private function prototypes */ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_ADC1_Init(void); static void MX_USART2_UART_Init(void); /* Private variables */ volatile uint16_t adc_values[100]; volatile uint8_t adc_ready = 0; /* Private functions */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { adc_ready = 1; } int main(void) { /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_ADC1_Init(); MX_USART2_UART_Init(); /* Start ADC conversion */ HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_values, 100); /* Infinite loop */ while (1) { /* Check if ADC values are ready */ if (adc_ready) { /* Clear flag */ adc_ready = 0; /* Calculate average value */ uint32_t sum = 0; for (int i = 0; i < 100; i++) { sum += adc_values[i]; } float avg = (float)sum / 100.0f; /* Calculate standard deviation */ float s = 0; for (int i = 0; i < 100; i++) { s += powf((float)adc_values[i] - avg, 2.0f); } s = sqrtf(s / 99.0f); /* Print values */ char buffer[50]; sprintf(buffer, "Avg = %f, StdDev = %f\r\n", avg, s); HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); } } } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } /** * @brief ADC1 Initialization Function * @param None * @retval None */ static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } /** * @brief DMA Initialization Function * @param None * @retval None */ static void MX_DMA_Init(void) { /* USER CODE BEGIN DMA_Init 0 */ /* USER CODE END DMA_Init 0 */ /* DMA1_Stream1_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); } /** * @brief USART2 Initialization Function * @param None * @retval None */ static void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ while(1) { } /* USER CODE END Error_Handler_Debug */ } /** * @brief This function is executed in case of error occurrence. * @retval None */ void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */ } /** * @brief This function is executed in case of error occurrence. * @retval None */ void DMA1_Stream1_IRQHandler(void) { /* USER CODE BEGIN DMA1_Stream1_IRQn 0 */ /* USER CODE END DMA1_Stream1_IRQn 0 */ HAL_DMA_IRQHandler(&hdma_adc1); /* USER CODE BEGIN DMA1_Stream1_IRQn 1 */ /* USER CODE END DMA1_Stream1_IRQn 1 */ } ``` 在代码中,我们使用DMA将ADC值传输到内存中,然后在main函数中计算平均值和标准差,并将它们通过USART2发送到匿名上位机。你可以根据需要修改代码以适应你的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值