有时候需要对单片机采集到多路信号进行一个直观的查看,这时候我们发现一般的串口助手都无法实现,这时候我在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)
{
}