简易波形系统(简易示波器部分)

简易波形系统(简易示波器部分)

具体知识内容:
1.整体框图
2.示波器重要驱动和软件设计

整体框图在这里插入图片描述

一、示波器重要驱动和软件设计

<1>重要驱动设计(PWM)

1.ADC+DMA+TIM的综合应用

ADC的采样频率由TIM定时器控制,采样周期=ADC自身的采样时间+TIM定时器的更新时间,ADC的自身采样时间在STM32标准库中设置ADC_RegularChannelConfig()函数来控制采样周期.
在72MHZ的主频下,ADC自身的采样频率:
在这里插入图片描述

计算公式:TCONV = 采样时间+ 12.5个周期
例如:
当ADCCLK=14MHz,采样时间为1.5周期
TCONV = 1.5 + 12.5 = 14周期 = 1μs
显然这并不满足采样各种频率,如果频率小于1KHZ一下,即使设置最大的采样频率也会造成后面在液晶屏上做出波形的麻烦,所以我们使用TIM定时器来控制ADC的采样频率,使ADC的整体采样频率调节灵活性得到最大提升。
ADC外部触发概览(使用的芯片为C8T6)
在这里插入图片描述
这里选择TIM3_TRGO事件为ADC采样的触发源,TRGO信号发生设置为定时器更新触发
在这里插入图片描述
---------------------------------------------------------------------------------------部分代码:

定时器初始化代码:
void Tim3_Timer_Config(uint16_t Period,uint16_t Prescaler,FunctionalState NewState)
{
    TIM_TimeBaseInitTypeDef TIM3_Init_Structure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	TIM3_Init_Structure.TIM_Period=Period;
  TIM3_Init_Structure.TIM_Prescaler=Prescaler;
	TIM3_Init_Structure.TIM_CounterMode=TIM_CounterMode_Up;
	TIM3_Init_Structure.TIM_ClockDivision=TIM_CKD_DIV1;

	TIM_TimeBaseInit(TIMx,&TIM3_Init_Structure);
	
//	Tim3_Nvic_Config();
//	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
	TIM_SelectOutputTrigger(TIMx,TIM_TRGOSource_Update);
	TIM_SelectMasterSlaveMode(TIMx,TIM_MasterSlaveMode_Enable);
	
	TIM_Cmd(TIMx,NewState);
}
ADC初始化代码:
	Adc_Init_Structure.ADC_Mode=ADC_Mode_Independent;//独立
	Adc_Init_Structure.ADC_ContinuousConvMode=DISABLE;//不使用ADC连续触发,不然第一次触发以后会连续触发!
	Adc_Init_Structure.ADC_DataAlign=ADC_DataAlign_Right;//右
	Adc_Init_Structure.ADC_ScanConvMode=DISABLE;//单通道
	Adc_Init_Structure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T3_TRGO;//用外部
	Adc_Init_Structure.ADC_NbrOfChannel=ADC_Channel_1;//通道数量

	ADC_Cmd(ADC1,ENABLE);	

	RCC_ADCCLKConfig(RCC_PCLK2_Div2);//ADC时钟设置
	//最大28us 最小0.5us   
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_1Cycles5);//选择通道,通道优先级,采样时间  12MHZ,26个周期,26/12=2.1us采样一次
	
	ADC_ExternalTrigConvCmd(ADC1,ENABLE);//使用外部触发转换
	// ADC开始校准
	ADC_StartCalibration(ADC1);
	// 等待校准完成
	while(ADC_GetCalibrationStatus(ADC1));

ADC代码注意点:
使用TIMx触发以后无需使能ADC连续采样和开启ADC触发函数!

示波器ADC采样存储思路:将ADC采样数据依次存储在长度为LEN的数组中,存储完成后主循环检测标志位进行处理。

问题:如何使存储更方便和高效呢?
:可使用DMA搬运ADC采样数据到指定的内存中,开启DMA中断,DMA处理完后触发中断,设置相应的标志位进行处理。

DMA配置代码:
	Dma_Init_Structure.DMA_PeripheralBaseAddr=(uint32_t)(&(ADC1->DR));//外设地址是ADC1_DR寄存器地址;
	Dma_Init_Structure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//双字节
	Dma_Init_Structure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//ADC不自增
	Dma_Init_Structure.DMA_MemoryBaseAddr=(uint32_t)(&Adc_Arr[0]);
	Dma_Init_Structure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//双字节
	Dma_Init_Structure.DMA_MemoryInc=DMA_MemoryInc_Enable;//目标地址自增
	Dma_Init_Structure.DMA_BufferSize=DATA_LEN;
	Dma_Init_Structure.DMA_Mode=DMA_Mode_Circular;//循环存储
	Dma_Init_Structure.DMA_DIR=DMA_DIR_PeripheralSRC;//方向 从外设到内存
	Dma_Init_Structure.DMA_M2M=DMA_M2M_Disable;
	Dma_Init_Structure.DMA_Priority=DMA_Priority_High;
	
	DMA_Init(DMA1_Channel1,&Dma_Init_Structure);
	DMA_Cmd(DMA1_Channel1,ENABLE);
	Dma_Nvic_Config();
	DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);//开启DMA中断
	ADC_DMACmd(ADC1,ENABLE);

2.通过PWM捕获+ADC数据实现10-300KZ的波形捕获
思路:要实现捕获一定范围内的频率,还需要提前知道波形的频率,通过波形的频率来设置ADC采样频率,达到获取合理的数据,这个过程可看作Auto功能。
1.配置PWM捕获
2.在捕获中断中设置ADC采样频率
注意:输入的芯片引脚需要既有ADC通道,还有TIMx CH1/CH2功能,捕获和采样不能同时进行,这里使先捕获后采样,反复循环。具体根据所选的芯片选择引脚,如C8T6的PA0
在这里插入图片描述
部分代码(处理频率部分,根据自身情况配置定时器采样频率):

u8 Cap_Cnt=0;
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET)
{
	Wave_Mag.Cycle=TIM2->CCR1;
	Wave_Mag.Pulse_W=TIM2->CCR2;
	Cap_Cnt++;
	Wave_Mag.Frequency=(float)(72000000.0/72.0/TIM2->CCR1);
//		printf("%d\n",Wave_Mag.Pulse_W);
  if(Wave_Mag.Frequency>=1000)
	{	
		if((Wave_Mag.Frequency/1000>20))//高频信号
		{
			TIM3->ARR=5;
			TIM3->PSC=Con_Shape.Hight_Psc; 
		}
		else if((Wave_Mag.Frequency/1000>=15)&&(Wave_Mag.Frequency/1000<=20))
		{
			TIM3->ARR=20;
			TIM3->PSC=Con_Shape.Hight_Psc; 
		}//高频信号
		else//中频信号
		{
			TIM3->ARR=(uint32_t)(Con_Shape.Wave_Expand/(Wave_Mag.Frequency/1000.0));
			TIM3->PSC=71; 
		}
	}
	else//低频信号
	{
		 TIM3->ARR=(uint32_t)(Con_Shape.Wave_Expand*(1000.0/Wave_Mag.Frequency));
		 TIM3->PSC=71; 
	}
	
	if(Cap_Cnt>5)//多次捕获频率为了获取到稳定的数据
	{
		 Cap_Cnt=0;
		 Cap_Flag=1;
		 Scope_Shut_Cap(0);//关闭捕获开启ADC采样
	}
}
	 TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}

3.在TFT液晶上显示波形

TFT选择2.2寸的ST7789,编写基本的显示驱动函数:画点/线,显示中文字符/英文字符,显示图片。

波形显示思路:
在获取的ADC数据中截取一段显示(增加显示的稳定性)
缺陷和问题:占空比无法显示,液晶刷新问题,格子无意义
在这里插入图片描述

总结

示波器部分还有很多欠缺,需要不断的修改和完善,代码波形处理写的比较烂,后续有更好的想法了再优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值