基于STM32的嵌入式数字示波器设计

目录
2系统方案设计 6
2.1 数字示波器的工作原理 6
2.2 数字示波器的重要技术指标 6
2.3 系统方案论证与比较 8
2.4 系统性能指标设计 9
3 系统硬件设计 12
3.1 耦合电路设计 12
3.2 信号调理电路设计 13
3.2.1 衰减网络电路设计 13
3.2.2 程控放大电路设计 14
3.3 高速A/D采集与FIFO缓存电路设计 15
3.4 测频整形电路设计 16
3.5 电源电路设计 17
3.6 微处理器最小系统电路设计 18
3.7 按键电路设计 19
3.8 液晶显示电路设计 19
本设计描述了一款嵌入式数字示波器,在硬件上采用了32位微处理器STM32和高速A/D转换器ADS830等器件,软件上搭载上µC/OS-II实时操作系统,简化编程,提高系统的效率和稳定性。输入信号从系统的无源探头接入,先经过的是AC/DC耦合电路,然后经过信号调理电路,被调理后的信号接着由A/D转换器转变成数字信号,再经过高速缓存器FIFO,信号数据即被传送到微处理器STM32中,由微处理器STM32完成对信号数据的处理,最后把波形还原到液晶上,并显示该信号的频率、电压等技术指标,本文转载自http://www.biyezuopin.vip/onews.asp?id=12695以供用户参考。

3、主要元器件列表
(1)STM32F103VCT6(主控制器)
(2)ADS830(高速A/D)
(3)IDT7204(高速缓存,FIFO)
(4)AD603(程控放大)
(5)AD8066(FET高速高性能放大器)
(6)TLV5618(双路12位串行DAC)
4、主体方案思路
如图所示:
在这里插入图片描述

 /*includes----------------------------------------------------------------*/
 #include "ad.h"
 /* 定义一个结构体,全局变量 */
 OSC ad;
 /*define variables -------------------------------------------------------*/

 /*-------主程序状态字-------*/
//  enum
// {
// 	StateHelp = 0;			//帮助
// 	StateRun  = 1;			//采集
// 	StateHold = 2			//暂停
// }

/*-------时间分度表,即每一格是多少时间,DSO.TimeBaseID 作为数组索引------*/
const uint32_t TimeTable[]=
{
	20   ,50   ,100,
	200  ,500  ,1000,
	2000 ,50000,10000,
	20000,50000,100000
};

/*--------衰减倍数 ,每大格电压--------*/
const uint32_t AttTable[][2]=
{
	{1400,5000},
	{560 ,2000},
	{280 ,1000},
	{140 ,500 },
	{56  ,200 },
	{28  ,100 }
};

static void DsoHelp(uint8_t *MainStatus);
static void DsoRun(uint8_t *MainStatus);

 /********************************************************************************
 **function name:DSO_Run
 **description  : DSO 全速运行
 **input        :none 
 **output       :none 
 **return       :none 
 **attention    :none 
 *****************************************************************************/
static void OscRun(uint8_t *MainStatus)
{
	uint8_t Fresh_flag = 1;  //TFT 刷新标志
	
	InitDsoParam(); 				 //初始化示波器参数
	InitDso();							 //配置外设 	ADC,DMA,TIM 
	SSD1289_FullScreen(Blue);//背景颜色:蓝色
	Timer_Fresh();					 //定时器1刷新,100ms 刷新一次
	
	while(*MainStatus == StateRun)
	{
		
	}
		
}

 /********************************************************************************
 **function name:DSO_Init
 **description  : 对ADC的GPIO、ADC、定时器和DMA的配置
                  PC0 = ADC1_IN10	
                  PC3 = ADC2_IN11
				  GPIO的输入模式设置为模拟输入AIN
 **input        :none 
 **output       :none 
 **return       :none 
 **attention    :none 
 *****************************************************************************/
 void DSO_Init(void)
 {
   DMA_InitTypeDef DMA_InitStructure;
	 ADC_InitTypeDef ADC_InitStructure;
	 GPIO_InitTypeDef GPIO_InitStructure;

	 /*enable the clock*/
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE);

	 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_3;
	 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	 GPIO_Init(GPIOC,&GPIO_InitStructure);

	 /*config the DMA1 */
	 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1|RCC_AHBPeriph_DMA2,ENABLE);
	 /*因为ADC1是通过DMA1的五个通道中的通道1连接到DMA1的,所以事先要清除通道1*/
	 DMA_DeInit(DMA1_Channel1);
	 /* 选择ADC1的数据寄存器作为源 */
	 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
	 /* 目标地址 */	               
   DMA_InitStructure.DMA_MemoryBaseAddr = (u16)&DSO.AD_value;
   /* 设置DMA传输方向,外设(ADC)作为源 */	            
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	 /* 设置缓冲区大小 */	                        
   DMA_InitStructure.DMA_BufferSize = Sample_count;
	 /* 外设地址不自增 */	                            
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   /* 存储器地址需要自增 */	           
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   /* 选择外设传输单位:16bit */	                   
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   /* 选择内存传输单位:16bit */
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   /* 无需循环模式   */	       
   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;	   
   /* 选择DMA优先级 */                           
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;	
   /* DMA传输类型,不是内存到内存 */                       
   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;	  
	 
	 /*enable DMA1 to channel1*/ 
	 DMA_Cmd(DMA1_Channel1,ENABLE);

	 /* 配置DMA2_5 用于CH2 */

   /* Enable DMA2 clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

  DMA_DeInit(DMA2_Channel5);		                                            /* 复位DMA2寄存器到缺省状态 */
	DMA_InitStructure.DMA_PeripheralBaseAddr = ADC3_DR_Address;	                /* 选择ADC3的数据寄存器作为源 */
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ad.CH2buffer;	            /* 目标地址 */
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;	                        /* 设置DMA传输方向,外设(ADC)作为源 */
  DMA_InitStructure.DMA_BufferSize =  Sample_count;	                            /* 设置缓冲区大小 */
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;	            /* 外设地址不自增 */
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;	                    /* 存储器地址需要自增 */
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;	/* 选择外设传输单位:16bit */
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	        /* 选择内存传输单位:16bit */
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;	                                /* 无需循环模式   */
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;	                        /* 选择DMA优先级 */
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;	                                /* DMA传输类型,不是内存到内存 */
  DMA_Init(DMA2_Channel5, &DMA_InitStructure);

   /* Enable DMA2 channel5 */
  DMA_Cmd(DMA2_Channel5, ENABLE);
	 
	/*ADC1 Configuration*/

	/*enable the clock*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	/*ADCCLK=PCLK2/6=12MHz*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExteralTrigConv_T1_CC3; //选择T1的捕获比较CC3作为触发源
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;    //数据右对齐,高位为0
  ADC_InitStructure.ADC_NbrOfChannel = 1;										//采集通道数目为1
  ADC_Init(ADC1, &ADC_InitStructure);
	 
	/*ADC1 regular external trigger conversion ,sample_time = 1.5 cycle*/
	ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_1Cycles5);
	/*enable ADC1 external trigger conversion */
	ADC_ExternalTrigConvCmd(ADC1,ENABLE);
	ADC_Cmd(ADC1, ENABLE);
	ADC_DMACmd(ADC1, ENABLE);

  /* 使能 ADC1 复位校准寄存器 */
  ADC_ResetCalibration(ADC1);
  /* 检测复位校准寄存器 */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* 开始 ADC1 校准 */
  ADC_StartCalibration(ADC1);
  /* 等待校准结束 */
  while(ADC_GetCalibrationStatus(ADC1));

	/*ADC3 是通过DMA2的通道5连接到DMA2的*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3,ENABLE);

	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;		                /* 连续转换静止 */
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3;	    /* 选择TIM1的CC3做触发 */
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	                /* 数据右对齐,高位为0 */
  ADC_InitStructure.ADC_NbrOfChannel = 1;	                                /* 1个通道 */
  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC1 regular channels configuration */
  ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 1, ADC_SampleTime_1Cycles5);

  /* Enable ADC3 external trigger conversion */
  ADC_ExternalTrigConvCmd(ADC3, ENABLE);

  /* 使能 ADC3 */
  ADC_Cmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */
  ADC_DMACmd(ADC3, ENABLE);

  /* 使能 ADC3 复位校准寄存器 */
  ADC_ResetCalibration(ADC3);
  /* 检测复位校准寄存器 */
  while(ADC_GetResetCalibrationStatus(ADC3));

  /* 开始 ADC3 校准 */
  ADC_StartCalibration(ADC3);
  /* 等待校准结束 */
  while(ADC_GetCalibrationStatus(ADC3));

  /*配置采样触发定时器,使用TIM CC1*/
	/*修改采样频率*/
	 Sample_Rate(ad.SampleFre);	                            
 }

 /*************************************************************************
 **function name:Sample_Rate
 **description  : 修改ADC的采样频率
                  配置定时器1第3通道CC3作为ADC1的触发源,工作在PWM模式
 **input        : U32  frequency 采样频率,单位Hz
 **output       : none 
 **return       : none
 **attention    : none 
 **************************************************************************/
 void SetSampleRate(u32 frequency)
 {
	/*时基结构体和比较输出结构体定义*/ 
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
	  
	/*定义定时器的工作周期*/ 
	u16 period;
	/* 采样频率计算公式 : period = 72000000 / freq */
	period=72000000/frequency;

	TIM_Cmd(TIM1, DISABLE);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	 
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	/* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = period;
	/*预分频: 不分频,那么计数频率 = 72000 000 / 18 = 4000 000*/
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	/*向上计数模式*/
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	/*初始化定时器1*/
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	/* 比较/PWM 通道的值*/
  TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period / 2;
	/*设置输出有效的高低电平,这里是低有效*/
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
	/*比较输出设置为定时器1*/
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);
   
	/*定时器计数使能*/
	TIM_Cmd(TIM1,ENABLE);
	/*TIM1 主要输出使能*/
  TIM_CtrlPWMOutputs(TIM1,ENABLE);
 }

 /*************************************************************************
 **function name:Stop_ADC
 **description  : 暂停采样
 **input        : none
 **output       : none 
 **return       : none
 **attention    : none 
 **************************************************************************/
 void Stop_ADC(void)
 {
  /*禁用TIM1*/
	TIM_Cmd(TIM1,DISABLE);
	/*禁用DMA1 channel 1 和DMA2 channel 5*/
	DMA_Cmd(DMA1_Channel1,DISABLE);
	DMA_Cmd(DMA2_Channel5,DISABLE);
 }

 /*************************************************************************
 **function name: Start_ADC
 **description  : 开始采样                 
 **input        : none
 **output       : none 
 **return       : none
 **attention    : none 
 **************************************************************************/
 void Start_ADC(void)
 {
	 /*启动TIM1*/
	 TIM_Cmd(TIM1,ENABLE);
	 /*启动DMA1 channel 1 和DMA2 channel 5*/
	 DMA_Cmd(DMA1_Channel1,ENABLE);
	 DMA_Cmd(DMA2_Channel5,ENABLE);

 }

 /*************************************************************************
 **function name: Draw_Wave
 **description  : 开始画示波器波形                 
 **input        : none
 **output       : none 
 **return       : none
 **attention    : none 
 **************************************************************************/
 void Draw_Wave(void)
 {
   u8 i,m,n;
	 u8  x=7,y=16;
	 u8 buffer_CH1[240];
     /*缓冲区1数据用完了,马上用缓冲区2 的数据
     if(ad.BufUsed==0)
	 {
	     ad.BufUsed=1;
	 }
	 else 
	 {
	     ad.BufUsed=0;
	 }
	 */
	 for(i=0;i<240;i++)
	 {
	     buffer_CH1[i]=(u8)(0.05*(ad.CH1buffer[i]));		 
	 }
	 	for(i=0;i<240;i++)
	 {
		if( buffer_CH1[i]< buffer_CH1[i+1])
		{
		     for(n=buffer_CH1[i];n< buffer_CH1[i+1];n++)
		    {
		         m=y+n;
		         SSD1289_SetCursor(x,m);
     	         SSD1289_WriteColor(Red);
				 m=0;
		    }
	 	 }
		else	if( buffer_CH1[i]== buffer_CH1[i+1])
		         {
				       m=y+ buffer_CH1[i];
				  	   SSD1289_SetCursor(x,m);
     	               SSD1289_WriteColor(Red);
					   m=0;			         
				 }
		        else 
		        {
		           for(n= buffer_CH1[i];n> buffer_CH1[i+1];n--)
			       {
                         m=y+n;
		                 SSD1289_SetCursor(x,m);
     	                 SSD1289_WriteColor(Red);
						 m=0;
			       }
		        }
		 x++;
	  }						
 }
 
 
 /*************************************************************************
 **function name: Display_Wave
 **description  : display wave                
 **input        : none
 **output       : none 
 **return       : none
 **attention    : none 
 **************************************************************************/
 static void Display_Wave(void)
{
	static u8 Display_First = 0;  //第一次调用时刷屏
	
	if(Display_First == 0)
	{
		Display_First = 1;
		SSD1289_FullScreen(Blue);   //背景是蓝色
	}
	
	
}

void display_adc1(void)
{
   u8 num[5]={'0','0','0','0'};
   num[0]=(u8)(ADC1ConvertedValue/1000+0x30);
   num[1]=(u8)(ADC1ConvertedValue%1000/100+0x30);
   num[2]=(u8)(ADC1ConvertedValue%100/10+0x30);
   num[3]=(u8)(ADC1ConvertedValue%10+0x30);
   SSD1289_DisplayString(7,223,num,Blue2,Grey);
}







在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 8
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

shejizuopin

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

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

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

打赏作者

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

抵扣说明:

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

余额充值