【单片机开发】STM32简易示波器开发

文章目录

  • (一)前言
  • (二)硬件介绍
    • (1)MCU
    • (2)TFT显示屏
    • (3)按键接口
  • (三)驱动编程
    • (1)ADC驱动
    • (2)LCD驱动
    • (3)一路测试PWM
  • (四)FFT原理
  • (四)操作逻辑
  • (五)操作效果
    • 0.1KHz
    • 0.2KHz
    • 0.4KHZ
    • 0.8KHz
    • 1.6KHz
    • 3.2K
    • 6.4KHz
    • 双通道
  • (六)下载地址

(一)前言

还记得之前因为个人需要,又不太想花钱买示波器,实现了一个简易的示波器。
【单片机开发】STM32简易示波器开发_第1张图片
这个示波器非常明显存在以下几个非常尴尬的问题:
1.对于ADC数据的处理方式还是基于查询模式
2.最高采样率无法控制,而且最高采样率可能都不会超过10K
3.供电方式有点尴尬,非常不方便
4.无法提供基本信息,包括峰峰值,以及信号频率

【单片机开发】STM32简易示波器开发_第2张图片

基于这些问题我想到了以下的改进方案
1.ADC采集基于定时器触发模式,可以实现采样频率的设置
2.ADC数据传输模式改成DMA模式,可以进一步提高采样率
3.改成小电池供电
4加入DSP库实现 256点的DSP运算,计算出信号频率

(二)硬件介绍

(1)MCU

因为需要实现DSP,需要大量的数据空间,所以我将之前的C8T6改成了RCT6,两者在封装以及部件上没有什么明显的区别,只是FLASH从64K升级成256K,RAM从20K变成了48K,这样就有了更多的操作空间。

【单片机开发】STM32简易示波器开发_第3张图片

(2)TFT显示屏

再网上买的核心板存在一个直插的OLED接口,也可以作为TFT接口。

【单片机开发】STM32简易示波器开发_第4张图片

(3)按键接口

【单片机开发】STM32简易示波器开发_第5张图片

(三)驱动编程

(1)ADC驱动

【单片机开发】STM32简易示波器开发_第6张图片

因为只有ADC1可以使用DMA所以我们将PA0,PA1映射到ADC1 CH0和ADC CH1

为了将ADC的采样率我们需要将ADC设置为TIM溢出触发,我们将TIM3作为触发。同时将PCLK2 6分频,可以得到12M的ADCCLK。

转换时间计算,我们设置转换周期ADC_SampleTime_1Cycles5
可以计算最短转换时间为(1.5+12.5)/12M=1.17us
0.85M采样率左右
当然实际肯定是达不到的。

ADC.h

#ifndef ADC_H
#define ADC_H

#include "sys.h"
#define ADC_CHANNEL_NUMS 		2
#define SAMPLS_NUM        	1024

#define TIM3_DEFAULT 9
#define TIM2_PERIOD  999

extern u16 ADC_SourceData[SAMPLS_NUM][ADC_CHANNEL_NUMS];

//ADCCLK=12M
void Adc_Init(void);
void ADC_SetFreq(u32 FREQ);
u32 ADC_GetFREQ(void);
#endif

ADC.c


#include "sys.h"
#include "usart.h"
#include "ADC.h"

u16 ADC_SourceData[SAMPLS_NUM][ADC_CHANNEL_NUMS] = {0};
u32 ADC_FREQ=100000;

void ADC_GPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void ADC_TIM2_GPIO_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void ADC_TIM2_Configuration(void)
{ 
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	ADC_TIM2_GPIO_Configuration();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	TIM_DeInit(TIM2);
	TIM_TimeBaseStructure.TIM_Period = TIM2_PERIOD - 1;
	TIM_TimeBaseStructure.TIM_Prescaler = 71;		
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	
	TIM_OCInitStructure.TIM_Pulse = (TIM2_PERIOD - 1) / 2;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;		
	TIM_OC3Init(TIM2, & TIM_OCInitStructure);
}

void ADC_TIM3_Configuration(u16 TIM3_PERIOD)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	TIM_TimeBaseInitStructure.TIM_Period = TIM3_PERIOD - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;			
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;		
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);			
	TIM_Cmd(TIM3,ENABLE);									
}

void ADC_DMA_NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel	= DMA1_Channel1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority		 = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	DMA_ClearITPendingBit(DMA1_IT_TC1);
	DMA_ITConfig(DMA1_Channel1,DMA1_IT_TC1,ENABLE);
}

void ADC_DMA_Configuration(void)
{
	DMA_InitTypeDef  DMA_InitStructure;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	DMA_DeInit(DMA1_Channel1);
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;
	DMA_InitStructure.DMA_MemoryBaseAddr     = (u32)ADC_SourceData;
	DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;
	DMA_InitStructure.DMA_BufferSize         = ADC_CHANNEL_NUMS*SAMPLS_NUM;
	DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;
	DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
	DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);
	DMA_Cmd(DMA1_Channel1, ENABLE);	
	ADC_DMA_NVIC_Configuration();
}
//ADCCLK=12M
//ADC_SampleTime_28Cycles5 ת»»ÖÜÆÚ28.5+12.5=41¸öÖÜÆÚ
//ADC_SampleTime_1Cycles5  ת»»ÖÜÆÚ1 .5+12.5=14¸öÖÜÆÚ
//×î¶Ìת»»Ê±¼ä£º 14/12=1.17us
//²ÉÑùÂÊ×î¸ß0.85M
void ADC_Init_Configuration(void)
{
	ADC_InitTypeDef  ADC_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//AFCCLK:72/6=12MHz
	ADC_DeInit(ADC1);
	ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;
	ADC_InitStructure.ADC_ScanConvMode       = ENABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
	ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_T3_TRGO;
	ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel       = ADC_CHANNEL_NUMS;
	ADC_Init(ADC1, &ADC_InitStructure);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0,  1, ADC_SampleTime_1Cycles5);	//AI_VS_A1
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1,  2, ADC_SampleTime_1Cycles5);	//AI_VS_B1

	ADC_DMACmd(ADC1, ENABLE);
	ADC_Cmd(ADC1, ENABLE);
	
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	ADC_ExternalTrigConvCmd(ADC1, ENABLE);
}




void Adc_Init(void)
{
	ADC_GPIO_Configuration();
	ADC_TIM3_Configuration(TIM3_DEFAULT);
	ADC_DMA_Configuration();
	ADC_Init_Configuration();
}
u32 ADC_GetFREQ(void)
{
	return ADC_FREQ;
}
//TIM3¶¨Ê±Æ÷1M
//×î¸ß´¥·¢ PERIOD=0 				²ÉÑùÂÊ=1M
//				 PERIOD=1 				²ÉÑùÂÊ=0.5M
//				 PERIOD=3 				²ÉÑùÂÊ=0.25M		250K
//				 PERIOD=3 				²ÉÑùÂÊ=0.1M			100K
//				 PERIOD=999 		  ²ÉÑùÂÊ=1K
//				 PERIOD=60000    	²ÉÑùÂÊ=16
void ADC_SetFreq(u32 FREQ)
{
	u16 PERIOD=((float)1000000/FREQ)-1;
	TIM3->ARR=PERIOD;
	ADC_FREQ=FREQ;
}

void DMA1_Channel1_IRQHandler(void)
{
	if(DMA_GetITStatus(DMA1_IT_TC1) != RESET)
	{
		DMA_ClearITPendingBit(DMA1_IT_TC1);
	}
}


我设置将 ADC数据的目标地址设置为 ADC_SourceData。

(2)LCD驱动

(3)一路测试PWM

#include "SERVO.h"
#include "delay.h"
void TIM4_PWM_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR|=1<<2;       
	GPIOB->CRH&=0XFFFFFF00;
	GPIOB->CRH|=0X000000BB;  
	GPIOB->ODR|=3<<8;
	TIM4->ARR=arr;
	TIM4->PSC=psc;
	TIM4->CCMR2|=6<<4; 
	TIM4->CCMR2|=1<<3; 
	TIM4->CCMR2|=6<<12;  
	TIM4->CCMR2|=1<<11;  
	TIM4->CCER|=1<<8;  
	TIM4->CCER|=1<<12;  
	TIM4->CR1=0x0080;  
	TIM4->CR1|=0x01;   
}

void Servo_Init(void)
{
	TIM4_PWM_Init(20000,71);//50HZ
	TIM4->CCR3 =10000;
	TIM4->CCR4 =15000;
}
void SERVO1(u8 degree)
{
	u16 k;
	k = 500 + degree * 11;
	TIM4->CCR3 = k;
}
void SERVO2(u8 degree)
{
	u16 k;
	k = 500 + degree * 11;
	TIM4->CCR4 = k;
}


(四)FFT原理

采集出信号频率以后我们需要在短时间内计算出信号的频率。

通过一组离散信号计算信号频率的方法通常叫做离散傅里叶变换。

我们首先来看一下DFT的原理:

学过信号的都知道,信号从时域来看是不断变换的,同时也可以从一个完全不同的角度来看信号。
DFT(FFT)的作用:可以将信号从时域变换到频域,而且时域和频域都是离散的,通俗的说,可以求出一个信号由哪些正弦波叠加而成,求出的结果就是这些正弦波的幅度和相位,我们音乐播放器上面显示的就是音乐fft之后不同频率正弦波的幅度,就像下面这张图片:
在这里插入图片描述

DFT公式:
在这里插入图片描述拆分以后可以得到

【单片机开发】STM32简易示波器开发_第7张图片

我们可以通过一组信号来测试:

DFT之后的数据是对称的,,在FFT的章节。比如做8点DFT,采样信号为x(n),DFT之后的数据为X(k),那么X(0)为直流信号,X(1), X(2), X(3), X(5), X(6), X(7),关于X(4)对称,即X(1)=X(7), X(2)=X(6),X(3)=X(5),如下图,是对1+sin(2PIt)进行DFT变换,具体的幅值先不关心,只要知道它是对称的就行了

【单片机开发】STM32简易示波器开发_第8张图片
我们可以看到得到的离散幅值序列,就是采样点数。这个时候点数的含义就从时间序列变成了频率序列。那么怎么从这个序列转换为我们需要的频率呢。

以上面的例子为例:

我们得到 0-7的离散序列可以对应到0-FS(采样频率)

具体公式为

我们在这个计算过程中可以看到采样频率一定要大于信号频率的两倍以上,否则幅值最高的频点就无法在你的采样范围内了。
我对DFT的理解其实就是将你的采样离散信号与采样信号进行卷积,这样以来,信号在频率中幅值最高的部分就会被突出出来。
FFT(Fast Fourier Transformation),中文名快速傅里叶变换,是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
而在信奥中,一般用来加速多项式乘法。
朴素高精度乘法的时间为 O ( n 2 ) O(n^2) O(n2),但FFT能将时间复杂度降到 O ( n l o g 2 n ) O(nlog_2n) O(nlog2​n)

一下是我用C语言实现的简单FFT

/*
 * @Descripttion: 
 * @version: 
 * @Author: Yueyang
 * @email: [email protected]
 * @Date: 2021-04-06 08:17:24
 * @LastEditors: Yueyang
 * @LastEditTime: 2021-04-06 11:02:16
 */
#include "stdio.h"
#include "math.h"
#include 
void kfft(double pr[],double pi[],int n,int k,double fr[],double fi[],int l,int il)
{ 
	int it,m,is,i,j,nv,l0;
    double p,q,s,vr,vi,poddr,poddi;
    for (it=0; it<=n-1; it++)
      { m=it; is=0;
        for (i=0; i<=k-1; i++)
          { j=m/2; is=2*is+(m-2*j); m=j;}
        fr[it]=pr[is]; fi[it]=pi[is];
      }
    pr[0]=1.0; pi[0]=0.0;
    p=6.283185306/(1.0*n);
    pr[1]=cos(p); pi[1]=-sin(p);
    if (l!=0) pi[1]=-pi[1];
    for (i=2; i<=n-1; i++)
      { p=pr[i-1]*pr[1]; q=pi[i-1]*pi[1];
        s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);
        pr[i]=p-q; pi[i]=s-p-q;
      }
    for (it=0; it<=n-2; it=it+2)
      { vr=fr[it]; vi=fi[it];
        fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];
        fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1];
      }
    m=n/2; nv=2;
    for (l0=k-2; l0>=0; l0--)
      { m=m/2; nv=2*nv;
        for (it=0; it<=(m-1)*nv; it=it+nv)
          for (j=0; j<=(nv/2)-1; j++)
            { p=pr[m*j]*fr[it+j+nv/2];
              q=pi[m*j]*fi[it+j+nv/2];
              s=pr[m*j]+pi[m*j];
              s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]);
              poddr=p-q; poddi=s-p-q;
              fr[it+j+nv/2]=fr[it+j]-poddr;
              fi[it+j+nv/2]=fi[it+j]-poddi;
              fr[it+j]=fr[it+j]+poddr;
              fi[it+j]=fi[it+j]+poddi;
            }
      }
    if (l!=0)
      for (i=0; i<=n-1; i++)
        { fr[i]=fr[i]/(1.0*n);
          fi[i]=fi[i]/(1.0*n);
        }
    if (il!=0)
      for (i=0; i<=n-1; i++)
        { pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);
          if (fabs(fr[i])<0.000001*fabs(fi[i]))
            { if ((fi[i]*fr[i])>0) pi[i]=90.0;
              else pi[i]=-90.0;
            }
          else
            pi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;
        }
    return;
}



#define PI 3.1415926535
#define FS 128
#define N (512)
#define M (int)log2(N)
 int main()
  { 
	  int i;
	  double t;
	  double pr[N],pi[N],fr[N],fi[N];
    clock_t start,end;
      //产生抽样序列
	  for (i=0; i<N; i++)
      { 
		 t=(double)i/FS;
		 pr[i]=sin(2*PI*33*t);
		 pi[i]=0.0;
	  }
    start=clock();
	  kfft(pr,pi,N,M,fr,fi,0,1);  //调用fft函数
    end=clock();
      for (i=0; i<N; i++)
      {
		  printf("%.6f %.6f\n",FS*(i+1)/(double)N,pr[i]); //输出数据
	    }
      printf("time:%d\n",(end-start));

      return 0;
  }

下面是输出序列
0.250000 0.000000
0.500000 0.000000
0.750000 0.000000
1.000000 0.000000
1.250000 0.000000
1.500000 0.000000
1.750000 0.000000
2.000000 0.000000
2.250000 0.000000
2.500000 0.000000
2.750000 0.000000
3.000000 0.000000
3.250000 0.000000
3.500000 0.000000
3.750000 0.000000
4.000000 0.000000
4.250000 0.000000
4.500000 0.000000
4.750000 0.000000
5.000000 0.000000
5.250000 0.000000
5.500000 0.000000
5.750000 0.000000
6.000000 0.000000
6.250000 0.000000
6.500000 0.000000
6.750000 0.000000
7.000000 0.000000
7.250000 0.000000
7.500000 0.000000
7.750000 0.000000
8.000000 0.000000
8.250000 0.000000
8.500000 0.000000
8.750000 0.000000
9.000000 0.000000
9.250000 0.000000
9.500000 0.000000
9.750000 0.000000
10.000000 0.000000
10.250000 0.000000
10.500000 0.000000
10.750000 0.000000
11.000000 0.000000
11.250000 0.000000
11.500000 0.000000
11.750000 0.000000
12.000000 0.000000
12.250000 0.000000
12.500000 0.000000
12.750000 0.000000
13.000000 0.000000
13.250000 0.000000
13.500000 0.000000
13.750000 0.000000
14.000000 0.000000
14.250000 0.000000
14.500000 0.000000
14.750000 0.000000
15.000000 0.000000
15.250000 0.000000
15.500000 0.000000
15.750000 0.000000
16.000000 0.000000
16.250000 0.000000
16.500000 0.000000
16.750000 0.000000
17.000000 0.000000
17.250000 0.000000
17.500000 0.000000
17.750000 0.000000
18.000000 0.000000
18.250000 0.000000
18.500000 0.000000
18.750000 0.000000
19.000000 0.000000
19.250000 0.000000
19.500000 0.000000
19.750000 0.000000
20.000000 0.000000
20.250000 0.000000
20.500000 0.000000
20.750000 0.000000
21.000000 0.000000
21.250000 0.000000
21.500000 0.000000
21.750000 0.000000
22.000000 0.000000
22.250000 0.000000
22.500000 0.000000
22.750000 0.000000
23.000000 0.000000
23.250000 0.000000
23.500000 0.000000
23.750000 0.000000
24.000000 0.000000
24.250000 0.000000
24.500000 0.000000
24.750000 0.000000
25.000000 0.000000
25.250000 0.000000
25.500000 0.000000
25.750000 0.000000
26.000000 0.000000
26.250000 0.000000
26.500000 0.000000
26.750000 0.000000
27.000000 0.000000
27.250000 0.000000
27.500000 0.000000
27.750000 0.000000
28.000000 0.000000
28.250000 0.000000
28.500000 0.000000
28.750000 0.000000
29.000000 0.000000
29.250000 0.000000
29.500000 0.000000
29.750000 0.000000
30.000000 0.000000
30.250000 0.000000
30.500000 0.000000
30.750000 0.000000
31.000000 0.000000
31.250000 0.000000
31.500000 0.000000
31.750000 0.000000
32.000000 0.000000
32.250000 0.000000
32.500000 0.000000
32.750000 0.000000
33.000000 0.000001
33.250000 256.000000
33.500000 0.000001
33.750000 0.000000
34.000000 0.000000
34.250000 0.000000
34.500000 0.000000
34.750000 0.000000
35.000000 0.000000
35.250000 0.000000
35.500000 0.000000
35.750000 0.000000
36.000000 0.000000
36.250000 0.000000
36.500000 0.000000
36.750000 0.000000
37.000000 0.000000
37.250000 0.000000
37.500000 0.000000
37.750000 0.000000
38.000000 0.000000
38.250000 0.000000
38.500000 0.000000
38.750000 0.000000
39.000000 0.000000
39.250000 0.000000
39.500000 0.000000
39.750000 0.000000
40.000000 0.000000
40.250000 0.000000
40.500000 0.000000
40.750000 0.000000
41.000000 0.000000
41.250000 0.000000
41.500000 0.000000
41.750000 0.000000
42.000000 0.000000
42.250000 0.000000
42.500000 0.000000
42.750000 0.000000
43.000000 0.000000
43.250000 0.000000
43.500000 0.000000
43.750000 0.000000
44.000000 0.000000
44.250000 0.000000
44.500000 0.000000
44.750000 0.000000
45.000000 0.000000
45.250000 0.000000
45.500000 0.000000
45.750000 0.000000
46.000000 0.000000
46.250000 0.000000
46.500000 0.000000
46.750000 0.000000
47.000000 0.000000
47.250000 0.000000
47.500000 0.000000
47.750000 0.000000
48.000000 0.000000
48.250000 0.000000
48.500000 0.000000
48.750000 0.000000
49.000000 0.000000
49.250000 0.000000
49.500000 0.000000
49.750000 0.000000
50.000000 0.000000
50.250000 0.000000
50.500000 0.000000
50.750000 0.000000
51.000000 0.000000
51.250000 0.000000
51.500000 0.000000
51.750000 0.000000
52.000000 0.000000
52.250000 0.000000
52.500000 0.000000
52.750000 0.000000
53.000000 0.000000
53.250000 0.000000
53.500000 0.000000
53.750000 0.000000
54.000000 0.000000
54.250000 0.000000
54.500000 0.000000
54.750000 0.000000
55.000000 0.000000
55.250000 0.000000
55.500000 0.000000
55.750000 0.000000
56.000000 0.000000
56.250000 0.000000
56.500000 0.000000
56.750000 0.000000
57.000000 0.000000
57.250000 0.000000
57.500000 0.000000
57.750000 0.000000
58.000000 0.000000
58.250000 0.000000
58.500000 0.000000
58.750000 0.000000
59.000000 0.000000
59.250000 0.000000
59.500000 0.000000
59.750000 0.000000
60.000000 0.000000
60.250000 0.000000
60.500000 0.000000
60.750000 0.000000
61.000000 0.000000
61.250000 0.000000
61.500000 0.000000
61.750000 0.000000
62.000000 0.000000
62.250000 0.000000
62.500000 0.000000
62.750000 0.000000
63.000000 0.000000
63.250000 0.000000
63.500000 0.000000
63.750000 0.000000
64.000000 0.000000
64.250000 0.000000
64.500000 0.000000
64.750000 0.000000
65.000000 0.000000
65.250000 0.000000
65.500000 0.000000
65.750000 0.000000
66.000000 0.000000
66.250000 0.000000
66.500000 0.000000
66.750000 0.000000
67.000000 0.000000
67.250000 0.000000
67.500000 0.000000
67.750000 0.000000
68.000000 0.000000
68.250000 0.000000
68.500000 0.000000
68.750000 0.000000
69.000000 0.000000
69.250000 0.000000
69.500000 0.000000
69.750000 0.000000
70.000000 0.000000
70.250000 0.000000
70.500000 0.000000
70.750000 0.000000
71.000000 0.000000
71.250000 0.000000
71.500000 0.000000
71.750000 0.000000
72.000000 0.000000
72.250000 0.000000
72.500000 0.000000
72.750000 0.000000
73.000000 0.000000
73.250000 0.000000
73.500000 0.000000
73.750000 0.000000
74.000000 0.000000
74.250000 0.000000
74.500000 0.000000
74.750000 0.000000
75.000000 0.000000
75.250000 0.000000
75.500000 0.000000
75.750000 0.000000
76.000000 0.000000
76.250000 0.000000
76.500000 0.000000
76.750000 0.000000
77.000000 0.000000
77.250000 0.000000
77.500000 0.000000
77.750000 0.000000
78.000000 0.000000
78.250000 0.000000
78.500000 0.000000
78.750000 0.000000
79.000000 0.000000
79.250000 0.000000
79.500000 0.000000
79.750000 0.000000
80.000000 0.000000
80.250000 0.000000
80.500000 0.000000
80.750000 0.000000
81.000000 0.000000
81.250000 0.000000
81.500000 0.000000
81.750000 0.000000
82.000000 0.000000
82.250000 0.000000
82.500000 0.000000
82.750000 0.000000
83.000000 0.000000
83.250000 0.000000
83.500000 0.000000
83.750000 0.000000
84.000000 0.000000
84.250000 0.000000
84.500000 0.000000
84.750000 0.000000
85.000000 0.000000
85.250000 0.000000
85.500000 0.000000
85.750000 0.000000
86.000000 0.000000
86.250000 0.000000
86.500000 0.000000
86.750000 0.000000
87.000000 0.000000
87.250000 0.000000
87.500000 0.000000
87.750000 0.000000
88.000000 0.000000
88.250000 0.000000
88.500000 0.000000
88.750000 0.000000
89.000000 0.000000
89.250000 0.000000
89.500000 0.000000
89.750000 0.000000
90.000000 0.000000
90.250000 0.000000
90.500000 0.000000
90.750000 0.000000
91.000000 0.000000
91.250000 0.000000
91.500000 0.000000
91.750000 0.000000
92.000000 0.000000
92.250000 0.000000
92.500000 0.000000
92.750000 0.000000
93.000000 0.000000
93.250000 0.000000
93.500000 0.000000
93.750000 0.000000
94.000000 0.000000
94.250000 0.000000
94.500000 0.000000
94.750000 0.000000
95.000000 0.000001
95.250000 256.000000
95.500000 0.000001
95.750000 0.000000
96.000000 0.000000
96.250000 0.000000
96.500000 0.000000
96.750000 0.000000
97.000000 0.000000
97.250000 0.000000
97.500000 0.000000
97.750000 0.000000
98.000000 0.000000
98.250000 0.000000
98.500000 0.000000
98.750000 0.000000
99.000000 0.000000
99.250000 0.000000
99.500000 0.000000
99.750000 0.000000
100.000000 0.000000
100.250000 0.000000
100.500000 0.000000
100.750000 0.000000
101.000000 0.000000
101.250000 0.000000
101.500000 0.000000
101.750000 0.000000
102.000000 0.000000
102.250000 0.000000
102.500000 0.000000
102.750000 0.000000
103.000000 0.000000
103.250000 0.000000
103.500000 0.000000
103.750000 0.000000
104.000000 0.000000
104.250000 0.000000
104.500000 0.000000
104.750000 0.000000
105.000000 0.000000
105.250000 0.000000
105.500000 0.000000
105.750000 0.000000
106.000000 0.000000
106.250000 0.000000
106.500000 0.000000
106.750000 0.000000
107.000000 0.000000
107.250000 0.000000
107.500000 0.000000
107.750000 0.000000
108.000000 0.000000
108.250000 0.000000
108.500000 0.000000
108.750000 0.000000
109.000000 0.000000
109.250000 0.000000
109.500000 0.000000
109.750000 0.000000
110.000000 0.000000
110.250000 0.000000
110.500000 0.000000
110.750000 0.000000
111.000000 0.000000
111.250000 0.000000
111.500000 0.000000
111.750000 0.000000
112.000000 0.000000
112.250000 0.000000
112.500000 0.000000
112.750000 0.000000
113.000000 0.000000
113.250000 0.000000
113.500000 0.000000
113.750000 0.000000
114.000000 0.000000
114.250000 0.000000
114.500000 0.000000
114.750000 0.000000
115.000000 0.000000
115.250000 0.000000
115.500000 0.000000
115.750000 0.000000
116.000000 0.000000
116.250000 0.000000
116.500000 0.000000
116.750000 0.000000
117.000000 0.000000
117.250000 0.000000
117.500000 0.000000
117.750000 0.000000
118.000000 0.000000
118.250000 0.000000
118.500000 0.000000
118.750000 0.000000
119.000000 0.000000
119.250000 0.000000
119.500000 0.000000
119.750000 0.000000
120.000000 0.000000
120.250000 0.000000
120.500000 0.000000
120.750000 0.000000
121.000000 0.000000
121.250000 0.000000
121.500000 0.000000
121.750000 0.000000
122.000000 0.000000
122.250000 0.000000
122.500000 0.000000
122.750000 0.000000
123.000000 0.000000
123.250000 0.000000
123.500000 0.000000
123.750000 0.000000
124.000000 0.000000
124.250000 0.000000
124.500000 0.000000
124.750000 0.000000
125.000000 0.000000
125.250000 0.000000
125.500000 0.000000
125.750000 0.000000
126.000000 0.000000
126.250000 0.000000
126.500000 0.000000
126.750000 0.000000
127.000000 0.000000
127.250000 0.000000
127.500000 0.000000
127.750000 0.000000
128.000000 0.000000

在频点33的位置幅值最高:

1* (FS)/N
那么怎样将256采样点转换为采样频率呢
我们可以通过以下函数转化频率:

float Get_Signal_Freq(int index)
{
	InitBuflnArray(index);
	DSP();
	return ((float)GetMaxData_Index()/256)*ADC_GetFREQ();
}

MyDSP.c

#include "MyDSP.h"
#include "math.h"
#include "ADC.h"

long 	FFT_256Pointln[N];
long 	FFT_256PointOut[N/2];
float IBufMagArray[N/2];
float Fs = 44800;	
float F = 44800/N;

void InitBuflnArray(int index)
{
	unsigned short i;
	float fx;
	Fs=ADC_GetFREQ();
	F = Fs/N;
	for(i = 0; i < N; i++)
	{
		fx = ADC_SourceData[i][index];
		FFT_256Pointln[i] = ((signed short)fx) << 16;	
	}
}

void GetPowerMag(void)
{
	signed short IX, IY;
	float X, Y, Mag;
	unsigned short i;
	for(i = 0; i < N/2;i++)
	{
		IX = (FFT_256PointOut[i] << 16) >> 16; 	
		IY = (FFT_256PointOut[i] >> 16);				
		X = N * ((float)IX) / 32768;
		Y = N * ((float)IY) / 32768;
		Mag = sqrt(X*X + Y*Y) / N;
		if(i == 0)
		{
			IBufMagArray[i] = (Mag * 32768);
		}
		else
		{
			IBufMagArray[i] = (Mag * 65536);
		}
	}
}


float GetMaxData(void)	
{
	int i = 0;
	float temp = 0;
	for(i = 1; i < N/2; i++)
	{
		if(temp < IBufMagArray[i])
		{
			temp = IBufMagArray[i];
		}
	}
	return temp;
}

int GetMaxData_Index(void)	
{
	int i = 0;
	float temp = 0;
	int tempindex=0;
	for(i = 1; i < N/2; i++)
	{
		if(temp < IBufMagArray[i])
		{
			temp = IBufMagArray[i];
			tempindex=i;
		}
	}
	return tempindex;
}


void DSP(void)	
{
	cr4_fft_256_stm32(FFT_256PointOut, FFT_256Pointln, N);
	GetPowerMag();
}

int Get_Adc_Max_Min(int index)
{
	int i = 0;
	int max = 0,min=0;
	if(index>1)index=0;
	for(i = 0; i < SAMPLS_NUM; i++)
	{
		if(max < ADC_SourceData[i][index])
			max = ADC_SourceData[i][index];
		if(min > ADC_SourceData[i][index])
			min = ADC_SourceData[i][index];
	}
	return max-min;
}

float Get_Signal_Freq(int index)
{
	InitBuflnArray(index);
	DSP();
	return ((float)GetMaxData_Index()/256)*ADC_GetFREQ();
}

(四)操作逻辑

main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "KEY.h"
#include "LCD_X.h"
#include "W25X16.h"
#include "malloc.h"
#include "SERVO.h"
#include "ADC.h"
#include "MyDSP.h"
u8 CHKEY=0; //0 CH0 1 CH1 2 

void DSO_Win()
{
	u8 data[3];
	int t=0;
	POINT_COLOR=GRAY;
	LCD_DrawFillRectangle(0,0,128,116);

	POINT_COLOR=BLUE;
	LCD_DrawFillRectangle(0,116,55,128);
	LCD_Show_Str(0,116,RED,BLUE,(u8*)"1HZ1V",12,1);

	POINT_COLOR=YELLOW;
	LCD_DrawFillRectangle(55,116,110,128);
	LCD_ShowString(55,116,12,(u8*)"1HZ1V",1);
	POINT_COLOR=GREEN;
	LCD_DrawFillRectangle(110,116,128,128);
	t=ADC_GetFREQ();
	sprintf((char*)data,"%3.1fK",(float)t/1000);
	LCD_ShowString(110,116,12,(u8*)data,1);
}

void CH1_Update(u32 freq,float vos)
{
	u8 data[10]={0};
	POINT_COLOR=BLUE;
	LCD_DrawFillRectangle(0,116,55,128);
	sprintf((char*)data,"%dHZ%1.1fV",freq,vos);
	LCD_Show_Str(0,116,RED,BLUE,(u8*)data,12,1);
}

void CH2_Update(int freq,float vos)
{
	u8 data[10]={0};
	POINT_COLOR=YELLOW;
	LCD_DrawFillRectangle(55,116,110,128);
	sprintf((char*)data,"%dHZ%1.1fV",freq,vos);
	LCD_Show_Str(55,116,RED,BLUE,(u8*)data,12,1);
}

void FREQ_Update(int freq)
{
	u8 data[3]={0};
	POINT_COLOR=GREEN;
	LCD_DrawFillRectangle(110,116,128,128);
	sprintf((char*)data,"%3.1f",(float)freq/1000);
	LCD_Show_Str(110,116,RED,BLUE,(u8*)data,12,1);
}
 int main(void)
 {	
	int i;
	u8 key;
	u32 freq1,freq2;
	float vos1,vos2;
	u32 freq;
	u8 line0[128];
	u8 line1[128];
	delay_init();	    	 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 
	uart_init(115200); 
	LED_Init();		  	
	KEY_Init();
	LCD_Init();
	LCD_Clear(WHITE);
	SPI_Flash_Init();
	Adc_Init();
	ADC_SetFreq(100);
	Servo_Init();
	DSO_Win();

	while(1){
		 key=KEY_Scan(0);
		 if(key==KEY0_PRES){
				CHKEY++;
				if(CHKEY>=3)CHKEY=0;
		 }
		 if(key==KEY1_PRES){
				freq=ADC_GetFREQ();
			  freq*=2;//²»Äܳ¬¹ý500K
			  if(freq>=500000)freq=100;
			  ADC_SetFreq(freq);
				FREQ_Update(freq);
		 }
			POINT_COLOR=GRAY;
			LCD_DrawFillRectangle(0,0,128,116);
		if(CHKEY==0){
			for(i=1;i<128;i++){
				line0[i]=116-ADC_SourceData[i][0]/37;
				LCD_DrawLine_Color(128-(i-1),line0[i-1],128-i,line0[i],BLUE);
			}
		}
		else if(CHKEY==1){
			for(i=1;i<128;i++){
				line1[i]=116-ADC_SourceData[i][1]/37;
				LCD_DrawLine_Color(128-(i-1),line1[i-1],128-i,line1[i],YELLOW);
			}		
		}
		else
		{
			for(i=1;i<128;i++){
				line0[i]=116-ADC_SourceData[i][0]/37;
				LCD_DrawLine_Color(128-(i-1),line0[i-1],128-i,line0[i],BLUE);
			}
			for(i=1;i<128;i++){
				line1[i]=116-ADC_SourceData[i][1]/37;
				LCD_DrawLine_Color(128-(i-1),line1[i-1],128-i,line1[i],YELLOW);
			}	
		}
		freq1=Get_Signal_Freq(0);
		freq2=Get_Signal_Freq(1);
		vos1=3.3*(float)Get_Adc_Max_Min(0)/4096;
		vos2=3.3*(float)Get_Adc_Max_Min(1)/4096;
		CH1_Update(freq1,vos1);
		CH2_Update(freq2,vos2);
	}
}

可以通过KEY1更改采样率
KEY0更改通道

(五)操作效果

采样50HZ PWM

0.1KHz

【单片机开发】STM32简易示波器开发_第9张图片

0.2KHz

【单片机开发】STM32简易示波器开发_第10张图片

0.4KHZ

【单片机开发】STM32简易示波器开发_第11张图片

0.8KHz

【单片机开发】STM32简易示波器开发_第12张图片

1.6KHz

【单片机开发】STM32简易示波器开发_第13张图片

3.2K

【单片机开发】STM32简易示波器开发_第14张图片

6.4KHz

【单片机开发】STM32简易示波器开发_第15张图片

双通道

【单片机开发】STM32简易示波器开发_第16张图片
经过在保证对于信号频率的测量准确的前提下,最高采样频率为500K。

(六)下载地址

下载地址

你可能感兴趣的:(STM32开发,c语言)