stm32单片机16路ad采集信号上位机查看全部波形(下位机部分)

有时候需要对单片机采集到多路信号进行一个直观的查看,这时候我们发现一般的串口助手都无法实现,这时候我在github上找了找,找到了一个开源工具,不过还是要在单片机下位机程序和和上位机上使用同一套通讯协议的,幸好源码也给出了stm32的一个源文件,这里我都放到我的空间里了,https://download.csdn.net/download/leva345/81848187,大家可以下载,上位机用管理员权限打开。
打开我们的文件夹,可以看到以下几个文件:
在这里插入图片描述
下位机里里有我们的stm32源文件,在这里插入图片描述

可以在这里照着我的步骤添加,也可以直接使用编辑好的,在我的空间也有https://download.csdn.net/download/leva345/81848500
以stm32单片机为例:
1、添头文件和c文件;在user文件夹添加我们的
在这里插入图片描述

结果图
在这里插入图片描述
要把头文件的路径添加进去。具体到文件夹中。
在这里插入图片描述

具体代码
main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"	 
#include "adc.h"
#include "DataScope_DP.h" 


 
 int main(void)
 {	 
  //u16 adcx;
	//int i = 0;
	//float temp;
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 	//串口初始化为115200
 	LED_Init();			     //LED端口初始化
	LCD_Init();			 	
 	Adc_Init();		  		//ADC初始化
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能
  DMA_Cmd(DMA1_Channel1,ENABLE);
	while(1)
	{
		
		ocs10_display(ADC_Value[0],ADC_Value[1],ADC_Value[2],ADC_Value[3],ADC_Value[4],ADC_Value[5],ADC_Value[6],ADC_Value[7],ADC_Value[8],ADC_Value[9]);
		
		
//		adcx=Get_Adc_Average(ADC_Channel_1,10);
//		temp=(float)adcx*(3.3/4096)*1000;
//    printf("%f\t",temp);
//		delay_ms(250);
    //ADC1->DR = 20; 
		
	//	temp = ADC_Value[13]*(3.3/4.096);
		
	//	printf("%d\r\n",(int)(ADC_Value[13]*(1000*3.3/4096)));// PA2
	//	printf("%d\r\n",(int)(ADC_Value[13]));// PA2
	//	printf("$%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d;",(int)(ADC_Value[0]),(int)(ADC_Value[1]),(int)(ADC_Value[2]),(int)(ADC_Value[3]),(int)(ADC_Value[4]),(int)(ADC_Value[5]),(int)(ADC_Value[6]),(int)(ADC_Value[7]),(int)(ADC_Value[8]),(int)(ADC_Value[9]),(int)(ADC_Value[10]),(int)(ADC_Value[11]),(int)(ADC_Value[12]),(int)(ADC_Value[13]),(int)(ADC_Value[14]),(int)(ADC_Value[15]));	
		
		
		
	//	printf("13: %f\t",temp);
		delay_ms(10);
	//	printf("\n");
		
//		for(i = 0;i<16;i++)
//		{
//			temp = ADC_Value[i]*(3.3/4.096);
//			printf("%d: %f\t",i,temp);
//			delay_ms(10);
//		}
    
	}
 }


#include "stm32f10x.h" 
#include "DataScope_DP.h"
#include "usart.h"
#include "stm32f10x_usart.h"
#include "delay.h"
 
unsigned char DataScope_OutPut_Buffer[42] = {0};	   //串口发送缓冲区


//函数说明:将单精度浮点数据转成4字节数据并存入指定地址 
//附加说明:用户无需直接操作此函数 
//target:目标单精度数据
//buf:待写入数组
//beg:指定从数组第几个元素开始写入
//函数无返回 
void Float2Byte(float *target,unsigned char *buf,unsigned char beg)
{
    unsigned char *point;
    point = (unsigned char*)target;	  //得到float的地址
    buf[beg]   = point[0];
    buf[beg+1] = point[1];
    buf[beg+2] = point[2];
    buf[beg+3] = point[3];
}
 
 
//函数说明:将待发送通道的单精度浮点数据写入发送缓冲区
//Data:通道数据
//Channel:选择通道(1-10)
//函数无返回 
void DataScope_Get_Channel_Data(float Data,unsigned char Channel)
{
//  if ( (Channel > 10) || (Channel == 0) ) return ;  //通道个数大于10或等于0,直接跳出,不执行函数
//  else
//  {
     switch (Channel)
		{
          case 1:  Float2Byte(&Data,DataScope_OutPut_Buffer,1); break;
          case 2:  Float2Byte(&Data,DataScope_OutPut_Buffer,5); break;
		  case 3:  Float2Byte(&Data,DataScope_OutPut_Buffer,9); break;
		  case 4:  Float2Byte(&Data,DataScope_OutPut_Buffer,13); break;
		  case 5:  Float2Byte(&Data,DataScope_OutPut_Buffer,17); break;
		  case 6:  Float2Byte(&Data,DataScope_OutPut_Buffer,21); break;
		  case 7:  Float2Byte(&Data,DataScope_OutPut_Buffer,25); break;
		  case 8:  Float2Byte(&Data,DataScope_OutPut_Buffer,29); break;
		  case 9:  Float2Byte(&Data,DataScope_OutPut_Buffer,33); break;
		  case 10: Float2Byte(&Data,DataScope_OutPut_Buffer,37); break;
			
		}
  //}	 
}
**DataScoDP.c**

//函数说明:生成 DataScopeV1.0 能正确识别的帧格式
//Channel_Number,需要发送的通道个数
//返回发送缓冲区数据个数
//返回0表示帧格式生成失败 
u8 DataScope_Data_Generate(unsigned char Channel_Number)
{
	u8 ret_num;
	if ( (Channel_Number > 10) || (Channel_Number == 0) ) 
  { 
     return 0; 
  }  //通道个数大于10或等于0,直接跳出,不执行函数
  else
  {	
	 DataScope_OutPut_Buffer[0] = '$';  //帧头
		
	 switch(Channel_Number)   
     { 
		 case 1:   DataScope_OutPut_Buffer[5]  =  5;  ret_num=6;  break;  
		 case 2:   DataScope_OutPut_Buffer[9]  =  9;  ret_num=10;  break;
		 case 3:   DataScope_OutPut_Buffer[13] = 13;  ret_num=14;  break;
		 case 4:   DataScope_OutPut_Buffer[17] = 17;  ret_num=18;  break;
		 case 5:   DataScope_OutPut_Buffer[21] = 21;  ret_num=22;  break; 
		 case 6:   DataScope_OutPut_Buffer[25] = 25;  ret_num=26;  break;
		 case 7:   DataScope_OutPut_Buffer[29] = 29;  ret_num=30;  break;
		 case 8:   DataScope_OutPut_Buffer[33] = 33;  ret_num=34;  break;
		 case 9:   DataScope_OutPut_Buffer[37] = 37;  ret_num=38;  break;
         case 10:  DataScope_OutPut_Buffer[41] = 41;  ret_num=42;  break;
		 default: ret_num=0; break;
     }
	 return ret_num;	 
  }
//	return 0;
}


void ocs10_display(float CH1,float CH2,float CH3,float CH4,float CH5,float CH6,float CH7,float CH8,float CH9,float CH10)
{  
	   u8 i,Send_Count;

	   DataScope_Get_Channel_Data( CH1 , 1 ); //将数据 1.0  写入通道 1
       DataScope_Get_Channel_Data( CH2 , 2 ); //将数据 2.0  写入通道 2
       DataScope_Get_Channel_Data( CH3 , 3 ); //将数据 3.0  写入通道 3
       DataScope_Get_Channel_Data( CH4 , 4 ); //将数据 4.0  写入通道 4
 	   DataScope_Get_Channel_Data( CH5 , 5 ); //将数据 5.0  写入通道 5
       DataScope_Get_Channel_Data( CH6 , 6 ); //将数据 6.0  写入通道 6
 	   DataScope_Get_Channel_Data( CH7 , 7 ); //将数据 7.0  写入通道 7
       DataScope_Get_Channel_Data( CH8 , 8 ); //将数据 8.0  写入通道 8
 	   DataScope_Get_Channel_Data( CH9 , 9 ); //将数据 9.0  写入通道 9
       DataScope_Get_Channel_Data( CH10 , 10); //将数据 10.0 写入通道 10
	   Send_Count = DataScope_Data_Generate(10); //生成10个通道的 格式化帧数据,返回帧数据长度
	   
	   for( i = 0 ; i < Send_Count; i++)  //循环发送,直到发送完毕   
	 	  {
		      USART_SendData(USART1, DataScope_OutPut_Buffer[i]);

             /* Loop until the end of transmission */
          while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
          {}  
		  }
  
	   delay_ms(10);
}

接线方式:用的ADC1,通道0-15,一共16个通道。
在这里插入图片描述
adc代码

#include "adc.h"
 #include "delay.h"
 
/*
16路ADC采样DMA传输
调用Adc_Init()函数初始化设备,ADC循环采样 
数据被DMA搬运到ADC_Value[ADC_CH_NUM]数组中
滤波后的数据在ADC_AfterFilter[ADC_CH_NUM]中
*/
	   		   	

u16 ADC_Value[ADC_CH_NUM] = {0};					
u16 ADC_AfterFilter[ADC_CH_NUM] = {0};		


void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
  DMA_InitTypeDef  DMA_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB|
									RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE );	  //使能ADC1通道时钟
	
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

	//PA1-PA7 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|
					GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
		//PC4-C5 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|
																GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOC, &GPIO_InitStructure);	
	
			//PB0-B1 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOB, &GPIO_InitStructure);	

  /* DMA channel1 configuration */
 DMA_DeInit(DMA1_Channel1);
 /*定义DMA外设基地址,即为存放转换结果的寄存器*/
 DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&(ADC1->DR);
 /*定义内存基地址*/
 DMA_InitStructure.DMA_MemoryBaseAddr =(u32)ADC_Value;
 /*定义AD外设作为数据传输的来源*/
 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
 /*指定DMA通道的DMA缓存的大小,即需要开辟几个内存空间,由ADC_CH_NUM这个宏决定*/
 DMA_InitStructure.DMA_BufferSize = ADC_CH_NUM;
	/*设定寄存器地址固定*/
 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 /*设定内存地址递加,即每次DMA都是将该外设寄存器中的值传到开辟的内存空间中*/
 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*设定外设数据宽度 半字*/	
 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	/*设定内存的的宽度 半字*/
 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	/*设定DMA工作再循环缓存模式*/
 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
 /*设定DMA选定的通道软件优先级*/
 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
 DMA_Init(DMA1_Channel1, &DMA_InitStructure);
 /* Enable DMA channel1 */
 DMA_Cmd(DMA1_Channel1, ENABLE);

  
  
	ADC_DeInit(ADC1);  //复位ADC1 

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = ENABLE ;	//模数转换工作在扫描模式
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE ;	//模数转换工作在连续转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = ADC_CH_NUM;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
 
	/*ADC通道编号*/
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 9, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 10, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_10,11, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11,12, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_12,13, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_13,14, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_14,15, ADC_SampleTime_55Cycles5);
  ADC_RegularChannelConfig(ADC1, ADC_Channel_15,16, ADC_SampleTime_55Cycles5);
	
  ADC_DMACmd(ADC1, ENABLE);
  
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
 
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能

}				  

//ADC采样值滤波
u16 ADC_Filter(void)
{
	
}	
  • 6
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: STM32是一种基于ARM Cortex-M内核的微控制器系列,这个系列的芯片很适合用来开发各种嵌入式系统,包括那些需要使用USB HID协议的系统。通过使用STM32的开发板搭载hid下位机的C程序,用户可以轻松地实现让计算机与其他USB设备进行通信。 在使用STM32 HID下位机 C的过程,需要考虑如何设计USB HID协议,并使用C语言编写固件代码。其,USB HID协议设计包括多种事项,如定义HID报文格式、支持设备描述符、输入和输出报告描述符等。 使用STM32开发板进行嵌入式开发需要一定的硬件和软件支持。硬件方面需要选择合适的开发板、以及其他外设(如LED、显示屏、电机等),以实现对外友好的应用程序。软件方面,需要使用开发板上提供的IDE软件和相应的驱动程序,这些软件提供了丰富的API和函数库,能够使开发人员轻松地使用C语言进行编程。 总之,通过使用STM32 HID下位机 C,开发人员可以快速、高效地设计和实现USB HID应用程序,从而满足各种嵌入式系统的需求。无论是在智能家居、智能交通、智能医疗等领域,这种技术都发挥了广泛的作用。 ### 回答2: STM32是意法半导体(STMicroelectronics)推出的一种基于ARM Cortex-M架构的微处理器系列,其包括了丰富的外围设备,如模拟和数字IO、通信接口、USB和LCD控制器等。HID是Human Interface Device的缩写,即人机接口设备,在USB开发常用的一种设备类型。作为下位机STM32可以通过USB接口作为HID设备被主机识别,实现与计算机之间的通信。 在C语言,使用STM32开发HID下位机需要掌握相关的硬件驱动和USB协议。首先需要选择适合的STM32芯片,并配置其GPIO和时钟等硬件资源。同时,需要编写USB传输协议的代码,实现在上位机下位机之间的数据通信。具体来说,需要编写USB的描述符、配置文件、报文解析等程序,以及相应的数据交换机制。最后,需要开发上位机的应用程序,按照HID协议和下位机数据交换格式进行通信。 总之,STM32作为一种强大的处理器平台,结合USB技术和HID协议,可以实现丰富的人机交互和数据交换功能。掌握这种硬件和软件开发技术,能够对电子信息等行业的产品设计和开发提供很好的支持。 ### 回答3: STM32 是意法半导体公司(STMicroelectronics)推出的一款32位微控制器,具有高性能、低功耗、易开发等特点。而 HID (Human Interface Device)则是人机接口设备的缩写,是 USB 设备的一类,用于实现人机交互,例如键盘、鼠标、游戏手柄等。 在STM32,HID下位机是指通过USB接口与上位机通信,实现USB设备的数据传输和人机交互功能。而C语言则是常用的编程语言之一,用于编写STM32的底层驱动程序和应用程序。 在STM32 HID下位机 C开发,需要了解USB协议和USB HID协议,掌握底层驱动程序的开发和编写上位机通信协议的能力。一般来说,开发 HID 设备需要使用 USB HID类库和 USB驱动程序,其,USB HID类库是基于USB协议开发的,支持USB HID协议,可用于实现HID设备的功能,例如 USB键盘、鼠标、游戏手柄等。 在实际开发,开发人员需要根据具体需求选择合适的开发板和开发环境,例如Keil MDK、IAR Embedded Workbench等,同时需要掌握C语言编程和常见的通信协议(例如UART、SPI、I2C等),以便开发出高效稳定的STM32 HID下位机
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr Robot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值