首页->【玩CortexM0】

20 0

[Nuvoton M0516] 实验六 2路ADC采样

先看设计手册6.4 模拟数字转换(ADC) 一章,了解M0516有8个通道的逐次逼近SAR的12位ADC[保证10位],采样速率为760Ksps,支持4种采样方式,本例采用连续采样方式。看寄存器设置手册6.11章节,其中的采样速率降到600Ksps,不过也够用了。因为这是12位的采样速率。ADC的采样基准电压可以是电源电压VDD,而M0516可以在最高5.5V——5V的电压下工作,因此基准可以是5V或3.3V或3V等。M0516芯片的ADC支持自校准功能以减少误差,一般自校准在初始化时完成即可。下边开始编程,首先在变量定义区增加2个INT型变量:

,adcTime,adcRes[]={0,0,0,0}

而后在主函数main前,加入ADC初始化函数:

//ADC Initial

void adcInit(void){

  IPRSTC2 |=ADC_RST;  //Reset ADC

  IPRSTC2 &=~ADC_RST; //ADC Normal mode

  APBCLK  |=ADC_CLKEN;//Enable ADC Clock

  CLKSEL1  =CLKSEL1 & (~ADC_CLK) | ADC_22M;//Select Int 22MHz Clock

  CLKDIV  |=0x00050000;//ADC Clock =BusCLK/6

  ADCR    |=ADEN;      //Enable ADC

  ADCALR  |=CALEN;     //ADC Self Check

  while(!(ADCALR & CALDONE));//Checked Pass

  P1_MFP   =P1_MFP & (~P10_AIN0_T2) | AIN0;//Set P10 for ADC0 Input

  P1_OFFD |=OFFD0;   //Disable P10 for Digi

  P1_PMD   =P1_PMD & (~Px0_PMD) | Px0_IN;//P10 for Input

  P1_MFP   =P1_MFP & (~P11_AIN1_T3) | AIN1;//Set P11 for ADC1 Input

  P1_OFFD |=OFFD1;   //Disable P11 for Digi

  P1_PMD   =P1_PMD & (~Px1_PMD) | Px1_IN;//P11 for Input

  ADSR    |=ADF;     //Clear ADC Flag

  ADCR    |=ADIE;    //ADC Int Enable

  NVIC_ISER =ADC_INT;//Interrupt Enable

  ADCR    |=ADST;    //ADC Start

}

上述语句完成P10,P11两个IO口的ADC输入,采用循环采样方式,有ADCR |=ADST;语句启动ADC转换[所有的通道]

在dispBase()函数中加入ADCx字符:

c2l(6,0,10);c2l(6,1,13);c2l(6,2,0);c2l(6,3,40);//AD0:

c2l(6,9,10);c2l(6,10,13);c2l(6,11,1);c2l(6,12,40);//AD1:

在dispMes()函数中加入:

c2l(6,4,(adcRes[0]/1000)%10);c2l(6,5,(adcRes[0]/100)%10);c2l(6,6,(adcRes[0]/10)%10);c2l(6,7,(adcRes[0])%10);

c2l(6,13,(adcRes[1]/1000)%10);c2l(6,14,(adcRes[1]/100)%10);c2l(6,15,(adcRes[1]/10)%10);c2l(6,16,(adcRes[1])%10);

在主函数main中加入ADC初始化:

adcInit();

由于ADC是中断完成的,为了保证转换的精度,我们用最基本的平均值法得到转换采样数值,再加一个计数值INT变量为adcTime,当adcTime计数到7[0~7为8次]开始计算输出ADC的数据,因此在ADC这段中将此变量以累加的方式加入,主循环函数中增加的代码为:

if(adcTime>7){

  adcTime=0;=0;

  adcRes[0]=adcRes[0]>>3;

  adcRes[1]=adcRes[1]>>3;

  dispMes();

  adcRes[0]=adcRes[1]=0;

  led();

}

左移3位相当于除以8,因为连续采样8次才获得采样数据。最后在主函数main之后边将ADC中断函数加入:

//ADC Interrupt

void ADC_IRQHandler(void){

  ADSR |= ADF;//Clear ADC flag  

  adcRes[0] += ADDR0 & 0x0FFF;//read ADC  Resualt

  adcRes[1] += ADDR1 & 0x0FFF;//read ADC  Resualt

  //ADCR |= ADST;//ADC Restart

  adcTime++;

}

M05xx系列M0芯片的ADC采样有一个函数,可以一次采样指定数量的通道,本例默认1次只能采样1个通道,因此执行1次仅仅ADC0完成采样,为此需要编写指定采样通道数量的函数,将他加在主函数main的前边:

//ADC around test

void adcTest(){

 ADCHER=0x000001003;//此为设置通道数

 ADCR=0x0000088B;

 ADCR |= ADST;//ADC Start

}

而将ADC中断函数中的启动ADC转换的ADCR |=ADST;注释掉就可以了,并且在主函数的ADC转换结果的语句体外增加一行:

adcTest();

1路计数器,2路PWM,2路ADC,1路脉冲输出的实验完成。在没有加延时是的LCD显示和串口显示见图61,61-高速采样LCD不清楚.JPG

图62。

62--高速采样模拟串口不清楚.JPG

为了转换结果可视——LCD,在循环体内的最后增加一句延时函数,尽管采样速率慢了,但可视性好点。见图63,63-增加延时LCD可视性好.JPG

图64。64-串口数据可视性好.JPG

从串口数据可以得到,每8次采样取平均值,即:ADC采样结果/8=采样结果>>3。

提个问题:如果想同时检测4路ADC,应该增加什么,改什么地方实现?算作而外思考实验的内容。

作者于2017-01-31 19:48:05修改!
楼主可见