先看基础部分第一问,首先经过测试,我的共射放大电路的放大倍数是280左右(分立元件每个人都不一样),选择放大倍数越小的三极管越好做(1)中有作解释。
基础部分硬件
输入电阻
DDS输出的正弦波幅值为1.1v,经过分压后,串联一个电阻,根据公式计算即可得出。电路图如下:
上面那一路是分压十分之一,底下是百分之一,先说上面的作用,可以看到,上面是DDS接跟随后,经过隔直,再经过跟随后串联电阻,因为题目要求做的是输入电阻1K-50K,范围跨度比较大,所以在输入电阻比较大时串联大电阻,比较小时串联小电阻。
因为在实际过程中,AD对波形峰值判断不准(我也不懂为什么,我的学长也是同样的情况),加了算法以后效果不是特别理想,所以采用AD637峰值检波模块,这里介绍一下AD637,也算是记录一下这个芯片性能,以免忘掉。
AD637 是一款完整的高精度、单芯片均方根直流转换器,可计算任何复杂波形的真均方根值。它提供集成电路均方根直流转换器前所未有的性能,精度、带宽和动态范围与分立和模块式设计相当。AD637 提供波峰因数补偿方案,允许以最高为 10 的波峰因数测量信号,额外误差小于 1%。宽带宽允许测量 200 mV 均方根、频率最高达 600 kHz 的输入信号以及 1V 均方根以上、频率最高达 8 MHz 的输入信号。
中文资料网上都有,这里就不啰嗦了
原理图
当±5V供电时,输入有效值电压范围:0 ~ 3 V,当±15V供电时,输入有效值电压范围:0 ~ 6 V
所以直接将检出来的值接给AD,误差非常小并且非常稳定。
输出电阻与输入电阻非常类似,就不再详细展开说明了。
放大倍数
放大倍数是输入放大电路的Ui和带载的Uo,不可以直接拿DDS输出或者分压的输出算,必须是进入放大电路的Ui,直接用32AD两个通道采集峰值检波的值就一除就可以了。
幅频特性曲线
幅频特性曲线(1)中说过,要保证DDS在变频时,幅值变化不大,不然需要重新采集输入,会消耗时间,题目是有时间规定的,超时扣分。
(1)中提到过,可以用示波器或者扫频仪先测量出0.707倍时对应的频率,方便代码编写DDS输出频率
经测量我手头9850在100HZ-20M幅值都是1.1V,故不需要采集输入,因为输入端固定不变。测量后上下限频率分别是260HZ到十几MHZ,用DDS变一次频率就算一次放大倍数,最后将其显示在stm32lcd屏幕上。
需要注意的是:
一在放大倍数有变化的端可以多采集一些点,在中间放大倍数很固定的点可以少采集一点,这样曲线就会很平滑,不会像一次函数一样非常直。
二电阻分压噪声还是有些大,用运放会好一点。
基础部分硬件到这里就结束了,基础分是很好拿的,几乎没有难度很流畅。
代码
#include “adc.h”
#include “delay.h”
#include “stdio.h”
#include “math.h”
#include “lcd.h”
#include “led.h”
#include “ad9850.h”
u8 Res_select=0;
u32 large_Res=20000;
u32 little_Res=3000;
u32 ui1=55; //DDS_OUT直接用万用表测量解写入代码(单位:mv)
//DDS输出1.1v 经过分压后值是可知的不需要用ad或者峰值检波测量
//但为了误差小数据精确 用台式万用表测量写入代码
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3
void Adc1_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 3; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
//设置指定ADC的规则组通道,一个序列,采样时间
//ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
//ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 2, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
//ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 3, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
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值
//ch:通道值 0~3
u16 Get_Adc1(u8 ch)
{
// //设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average1(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc1(ch);
delay_ms(5);
}
return temp_val/times;
}
/*
//可以采用此函数计算波形峰值 但ad采不准 故我采用的方案为峰值检波
//用ad直接采集峰值检波口的波形幅值比较精确
#define N 50
u16 filter(u8 ch,u8 times)
{
char count,i,j;
u32 Value_buf[N];
u32 temp;
u32 sum=0;
for(count=0;count<N;count++)
Value_buf[count]= 0;
for(count=0;count<N;count++)
Value_buf[count]= Get_Adc1(ch);
for(j=0;j<(N-1);j++)
for(i=0;i<(N-j);i++)
if(Value_buf[i]>Value_buf[i+1])
{
temp = Value_buf[i];
Value_buf[i]= Value_buf[i+1];
Value_buf[i+1]=temp;
}
for(count =1;count<N-1;count++)
sum += Value_buf[count];
return (u16)(sum/(N-2));
}
void adc_ch_data(u8 Channel)
{
u32 adcx[128];
u16 i;
for(i=0;i<128;i++)
{
adcx[i] = Get_Adc_Average1(Channel,10); // 检测通道1的电压
printf(“%d\r\n”,adcx[i]);
}
}
*/
void get_resin(void)
{
float res_in=0;
float adc_ch10=0;
float adc_ch10_v=0;
jidianqi7=0;
delay_ms(200);
adc_ch10 = Get_Adc_Average1(ADC_Channel_10,10); //采集通道1 的adc数值
//Y1=0.6715X-1.2403
//adc_ch10_v=((((adc_ch10+1.2403)/0.6715)*2)/80);
adc_ch10_v=((((adc_ch10+1.2403)/0.6715)*2)/110);
//将其转换为电压
//将其反算回去以后乘2的目的是使用峰峰值
//除100的目的是 因为这个值比较小 实际测量中只有4mv
//所以我在4mv输出后加了一级放大倍数为80倍的同相比例放大
//故要在代码中除100 若不加放大则不需要除这100
//不加放大测量结果正确 但是因为幅值比较小 采集不稳定 值跳变的厉害 但有正确的结果
delay_ms(200);
if(Res_select==1)
{
res_in=(adc_ch10_v*large_Res)/(ui1-adc_ch10_v);
//输入电阻计算公式: (Ui2*R)/(Ui1-Ui2)
}
else
{
res_in=(adc_ch10_v*little_Res)/(ui1-adc_ch10_v);
}
printf(“%f\r\n”,res_in);
//res_in=res_in/1000;
LCD_ShowxNum(100,0, res_in,5,24,0);//显示ADC的值
LCD_ShowxNum(100,120, adc_ch10_v,5,24,0);//显示ADC的值
//printf(“%f\r\n”,res_in);
}
void get_resout(void)
{
float res_out=0;
float adc_ch11=0;
float adc_ch11_1=0;
float adc_ch11_v1=0;
float adc_ch11_v2=0;
jidianqi6=1; //空载
//Y1=0.6715X-1.2403
adc_ch11 = Get_Adc_Average1(ADC_Channel_12,10); //采集通道11 的adc数值
//adc_ch11_v1=(((adc_ch11+1.2403)/0.6715)*2)+1.1; //将其转换为电压
//adc_ch11_v1=adc_ch11*3.3/4096;
//jidianqi闭合 低电平
jidianqi6=0; //带载
LCD_ShowxNum(100,150, adc_ch11_v1,5,24,0);//显示ADC的值
delay_ms(500);
adc_ch11_1 = Get_Adc_Average1(ADC_Channel_12,10); //采集通道11 的adc数值
//adc_ch11_v2=adc_ch11_1*3.3/4096;
//adc_ch11_v2=(((adc_ch11_1+1.2403)/0.6715)*2);
//输出电阻测量 Ro=(Uo1-Uo2)*R/Uo2 R:带载阻值
LCD_ShowxNum(100,180, adc_ch11_v2,5,24,0);//显示ADC的值
//res_out=((adc_ch11_v1-adc_ch11_v2)*2000)/adc_ch11_v2;
res_out=((adc_ch11-adc_ch11_1)*2000)/adc_ch11_1;
//res_out=((adc_ch11-adc_ch11_1)*2000)/adc_ch11_1;
delay_ms(2);
//res_out=res_out/1000;
//printf(“%f\r\n”,res_out);
LCD_ShowxNum(100,30, res_out,5,24,0);//显示ADC的值
}
void get_Au(void)//增益
{
u16 Au=0;
float Uo=0;//经过放大电路以后并未通过继电器的波形峰值
//输出的波形峰值需要将直流量减掉 再进行峰值检波
float Ui_v=0;
float Uo_v=0;
float Ui=0;//输入放大电路的波形峰值
Ui= Get_Adc_Average1(ADC_Channel_10,10);
Ui_v=((((Ui+1.2403)/0.6715)*2)/100);
delay_ms(200);
Uo= Get_Adc_Average1(ADC_Channel_12,10);
Uo_v=(((Uo+0.12)*4)-6.35)*2;
//Uo_v=(((Uo+1.2403)/0.6715)*2);
delay_ms(10);
Au=Uo_v/Ui_v;
//printf(“%d\r\n”,Au);
LCD_ShowxNum(100,60, Au,5,24,0);//显示ADC的值
}
输入电阻、输出电阻、放大倍数都封装成了函数,在主函数中直接调就可以了。
幅频特性曲线坐标显示:
void zuobiao(void)
{
POINT_COLOR = RED;
LCD_Display_Dir(0);
LCD_ShowString(30,0,210,24,24,”Ri = “);
LCD_ShowString(30,30,210,24,24,”R0 = “);
// LCD_ShowString(30,60,210,24,24,”fL = “);
// LCD_ShowString(30,90,210,24,24,”fH = “);
LCD_ShowString(30,60,210,24,24,”Au = “);
LCD_DrawLine(0,305,240,305);
LCD_DrawLine(15,140,15,320); //x轴y轴
LCD_DrawLine(240,305,230,315);
LCD_DrawLine(240,305,230,295); //箭头
LCD_DrawLine(15,140,5,150);
LCD_DrawLine(15,140,25,150); //箭头
LCD_DrawLine(40,305,40,300);
LCD_DrawLine(65,305,65,300);
LCD_DrawLine(90,305,90,300);
LCD_DrawLine(115,305,115,300);
LCD_DrawLine(140,305,140,300);
LCD_DrawLine(165,305,165,300);
LCD_DrawLine(195,305,195,300);
LCD_DrawLine(15,275,20,275);
LCD_DrawLine(15,245,20,245);
LCD_DrawLine(15,215,20,215);
LCD_DrawLine(15,185,20,185);
LCD_ShowString(220,307,200,12,12,”Hz”);
LCD_ShowString(20,307,200,12,12,”100″);
LCD_ShowString(40,307,200,12,12,”200″);
LCD_ShowString(60,307,200,12,12,”1K”);
LCD_ShowString(80,307,200,12,12,”1.5K”);
LCD_ShowString(100,307,200,12,12,”10K”);
LCD_ShowString(120,307,200,12,12,”50K”);
LCD_ShowString(140,307,200,12,12,”100K”);
LCD_ShowString(160,307,200,12,12,”150K”);
LCD_ShowString(180,307,200,12,12,”170K”);
LCD_ShowString(2,270,200,12,12,”80″);
LCD_ShowString(2,240,200,12,12,”10O”);
LCD_ShowString(2,210,200,12,12,”12O”);
LCD_ShowString(2,180,200,12,12,”14O”);
LCD_ShowString(7,307,200,12,12,”O”);
LCD_Display_Dir(1);
LCD_ShowString(145,0,200,12,12,”Gain”);
LCD_Display_Dir(0);
}
幅频特性曲线的显示:
//因为我手头的AD9850在变频率的时候不会变幅值
//9854在变频率的时候会改变幅值
//测量幅频特性曲线的时候 需要测量增益 若是DDS输出不变则不需要每次变频率采输入幅值
//同理若是变频率扫频时 幅值会变 则每变一次频率就应该采集一次输入 代码工作量比较大
//幅频特性曲线显示
float signal[11]={100,200,500,1000,10000,50000,100000,150000,170000};//DDS输出频率
void boxin(void)
{
u32 Ui1=55; //DDS_OUT直接用万用表测量解写入代码(单位:mv)
//DDS输出1.1v 经过分压后值是可知的不需要用ad或者峰值检波测量
//但为了误差小数据精确 用台式万用表测量写入代码
u8 Au[9]={0,0,0,0,0,0,0,0,0};
u8 i;
float adc_ch11_1=0;
float adc_ch11_v2=0;
for(i=0;i<11;i++)
{
ad9850_wr_serial(0x00,(double)signal[i]);//DDS输出信号
adc_ch11_1 = Get_Adc_Average1(ADC_Channel_12,10); //采集通道11 的adc数值
adc_ch11_v2=(((adc_ch11_1+1.2403)/0.6715)*2)+1.1; //将其转换为电压
Au[i]=adc_ch11_v2/Ui1;
}
// for(i=0;i<8;i++)
// {
// au[i]=Au[i];
// }
// au[5]=au[4]-30;
// au[6]=au[4]-60;
// au[7]=au[4]-100;
LCD_DrawPoint(20,305-Au[0]/20*30);
LCD_DrawPoint(40,305-Au[1]/20*30);
LCD_DrawPoint(60,305-Au[2]/20*30);
LCD_DrawPoint(80,305-Au[3]/20*30);
LCD_DrawPoint(100,305-Au[4]/20*30);
LCD_DrawPoint(120,305-Au[5]/20*30);
LCD_DrawPoint(140,305-Au[6]/20*30);
LCD_DrawPoint(160,305-Au[7]/20*30);
LCD_DrawPoint(180,305-Au[8]/20*30);
LCD_DrawLine(20,305-Au[0]/20*30,40,305-Au[1]/20*30);
LCD_DrawLine(40,305-Au[1]/20*30,60,305-Au[2]/20*30);
LCD_DrawLine(60,305-Au[2]/20*30,80,305-Au[3]/20*30);
LCD_DrawLine(80,305-Au[3]/20*30,100,305-Au[4]/20*30);
LCD_DrawLine(100,305-Au[4]/20*30,120,305-Au[5]/20*30);
LCD_DrawLine(120,305-Au[5]/20*30,140,305-Au[6]/20*30);
LCD_DrawLine(140,305-Au[6]/20*30,160,305-Au[7]/20*30);
LCD_DrawLine(160,305-Au[7]/20*30,180,305-Au[8]/20*30);
// LCD_DrawLine(65,305-Au[1]*t,70,305-Au[1]*t+k2*5-4);
// LCD_DrawLine(70,305-Au[1]*t+k2*5-4,75,305-Au[1]*t+k2*10-5);
// LCD_DrawLine(75,305-Au[1]*t-5+k2*10,80,305-Au[1]*t+k2*15-4);
// LCD_DrawLine(80,305-Au[1]*t-4+k2*15,85,305-Au[1]*t+k2*20-3);
// LCD_DrawLine(85,305-Au[1]*t-3+k2*20,90,305-Au[2]*t);
// LCD_DrawLine(40,305-Au[0]*t,65,305-Au[1]*t);
// LCD_DrawLine(65,305-Au[1]*t,90,305-Au[2]*t);
// LCD_DrawLine(90,305-Au[2]*t,115,305-Au[3]*t);
// LCD_DrawLine(115,305-Au[3]*t,140,305-Au[4]*t);
// LCD_DrawLine(140,305-Au[4]*t,148,305-Au[5]*t);
// LCD_DrawLine(148,305-Au[5]*t,156,305-Au[6]*t);
// LCD_DrawLine(156,305-Au[6]*t,165,305-Au[7]*t);
// LCD_DrawLine(165,305-Au[7]*t,195,305-Au[8]*t);
}
上面就是基础部分的全部了,都是已经测试完毕了的,没有问题。
文章出处登录后可见!