LPC1343内部ADC的使用

发布者:breakthrough3最新更新时间:2016-01-18 来源: eefocus关键字:LPC1343  内部ADC 手机看文章 扫描二维码
随时随地手机看文章
本节来讲述LPC1343内部ADC的使用。设计一个实验,使用ADC的0通道进行AD转换,并且将转换结果通过UART发送在PC端的串口终端软件观察。

 

这次仍然以NXP提供的example作为例子,但是LPC1343内部ADC工作方式众多,所以该example用了许多的预编译结构,笔者在此将本次实验不会用到的语句全部去掉,程序变得简洁,也更易于理解。

同样的,在此节中将不再将所用到的寄存器一一列出,而只是一个各个寄存器设置的“线索”,因为至此各个读者一定已经拥有了自己翻阅用户手册查看对应寄存器内容的能力。

 

从主函数我们可以看出本次实验的进展过程:

int main (void)

{

    uint32_t i,j;

    UARTInit(115200);                        //初始化UART

    ADCInit( ADC_CLK );                       // 初始化 ADC

    while(1)

    {

    ADCRead( 0 );                             //读取0通道转换值

    while ( !ADCIntDone );                     //等待读取完成

         ADCIntDone = 0;                         //清除读取完成标志

         UARTBuffer[0]=(uint8_t)(*ADCValue>>8);     //分离高2位数据

         UARTBuffer[1]=(uint8_t)(*ADCValue);        //分离低8位数据

         UARTSend((uint8_t *)UARTBuffer, 2);        //向UART发送数据

         for(i=0;i<5000;i++)                       //延时

           for(j=0;j<1000;j++);

    }

}

 

大家应该在几个8位单片机上都设计过这种ADC转换程序,相信大家也肯定经历过这个基础的过程。

 

UART的初始化在上一节已经详述了,我们直接来看看ADC的初始化ADCInit():

 

void ADCInit( uint32_t ADC_Clk )

{

  LPC_SYSCON->;PDRUNCFG &= ~(0x1<<4);  //打开ADC供电

  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13);//开启ADC的AHB通道

  LPC_IOCON->JTAG_TDI_PIO0_11 = 0x02;  // 选择ADC0引脚功能

 

  LPC_ADC->CR = ((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/ADC_Clk-1)<<8;

#if ADC_INTERRUPT_FLAG        //使用ADC中断功能

  NVIC_EnableIRQ(ADC_IRQn);

  LPC_ADC->INTEN = 0x1FF;           

#endif

  return;

}

1、该函数唯一的参数填入欲设置的ADC工作速率,单位是Hz,本次实验填入4500000,即4.5MHz;

2、ADC初始化不同于前面其他设备的一个地方,在于它的电源是默认关闭的,所以首先要打开它的电源,明显是一个降低功耗的措施;

3、ADC的工作速率,从用户手册可以查看到如下描述:

The APB clock (PCLK) is divided by CLKDIV +1 to produce the clock for the ADC, which should be less than or equal to 4.5 MHz.由此我们知道该ADC的最大驱动时钟频率是4.5MHz。同时分频数是CLKDIV +1,所以程序中要“ADC_Clk-1”,至于为什么要左移8位呢?那是因为设置的分频数是存放于ADCCR(ADC控制寄存器)中的第8:15位。

4、如果使用中断功能,则除了要设置NVIC控制器之外,还需要在ADCINTEN中打开各个通道的中断功能,当某通道转换完成时,会触发对于中断。

初始化完毕之后,就可以开启ADC进行转换了。首先是ADCRead():

 

 

uint32_t ADCRead( uint8_t channelNum )

{

  if ( channelNum >= ADC_NUM )//判断通道号是否过大

  {

         channelNum = 0;//复位通道号

  }

  LPC_ADC->CR &= 0xFFFFFF00; // 清除所有转换通道的上一次选择状态

  LPC_ADC->CR |= (1 << 24) | (1 << channelNum);//选择通道,并开启转换    

  return ( channelNum );//返回通道号

}

1、本函数要求填入的唯一参数是所希望进行ADC的通道号;

2、转换前应该清除上一次通道被选状态;

3、在CR控制器中的26:24位控制着ADC的多种转换启动方式,本实验中使用最普通的一种:立即开始转换。

4、因为本实验使用了ADC的中断功能,转换结果在ADC中断中存储,所以此函数在使用ADC中断功能的情况下返回的是转换的通道号。

 

 

ADC中断功能的情况下返回的是转换的通道号。

 

所以当本函数运行结束之后,ADC转换开始,等待进入中断服务函数:

 

void ADC_IRQHandler (void)

{

  uint32_t regVal;

  LPC_ADC->CR &= 0xF8FFFFFF;    

  regVal = LPC_ADC->STAT;             

  if ( regVal & 0x0000FF00 )       

  {

        

         regVal = (regVal & 0x0000FF00) >> 0x08;//如果有,确认通道

         switch ( regVal )//通过读取转换值来清除ADC数据,注意这部分是错误数据,是丢弃的

         {

           case 0x01:regVal = LPC_ADC->DR0;break;

           case 0x02:regVal = LPC_ADC->DR1;break;

           case 0x04:regVal = LPC_ADC->DR2;break;

           case 0x08:regVal = LPC_ADC->DR3;break;

           case 0x10:regVal = LPC_ADC->DR4;break;

           case 0x20:regVal = LPC_ADC->DR5;break;

           case 0x40:regVal = LPC_ADC->DR6;break;

           case 0x80:regVal = LPC_ADC->DR7;break;

           default:break;

         }

         LPC_ADC->CR &= 0xF8FFFFFF;         

         ADCIntDone = 1;

         return;    

  }

  if ( regVal & ADC_ADINT )//判断是否有任何一个通道转换结束

  {

         switch ( regVal & 0xFF )   

         {

           case 0x01:ADCValue[0] = ( LPC_ADC->DR0 >> 6 ) & 0x3FF;break;

           case 0x02:ADCValue[1] = ( LPC_ADC->DR1 >> 6 ) & 0x3FF;break;

           case 0x04:ADCValue[2] = ( LPC_ADC->DR2 >> 6 ) & 0x3FF;break;

           case 0x08:ADCValue[3] = ( LPC_ADC->DR3 >> 6 ) & 0x3FF;break;

           case 0x10:ADCValue[4] = ( LPC_ADC->DR4 >> 6 ) & 0x3FF;break;

           case 0x20:ADCValue[5] = ( LPC_ADC->DR5 >> 6 ) & 0x3FF;break;

           case 0x40:ADCValue[6] = ( LPC_ADC->DR6 >> 6 ) & 0x3FF;break;

           case 0x80:ADCValue[7] = ( LPC_ADC->DR7 >> 6 ) & 0x3FF;break;

           default:break;

         }

         ADCIntDone = 1;//读取结束标志

  }

  return;

}

1、进入中断服务程序之后,首先停止AD转换;

2、和UART一样,ADC中断标志也是通过读取来清除的;

3、首先要检查溢出错误,如果有,则数据无效,要通道读取来清除ADC转换数据寄存器(ADCDR);

4、ADC中断有两种,一种是任何一个通道完成转换都会触发,一种是某个中断完成转换就会触发,本实验中两种中断都打开了,因此先判断是否有转换完成,再判断是哪个通道完成转换;

中断函数的结束意味着读取完成,剩下的就是将读出数据发送到UART去显示了。但在这之前,因为LPC1343的ADC默认情况下是10位精度,而我们的UART是以字符为数据长度发送的,所以笔者特意将转换结果转换成了16位长度,分两次发送。现将本次实验运行过程概况如下:

UART初始化——ADC初始化——开始转换——转换结束触发中断——判断有无错误——有错误则放弃无效数据,无错误则读出有效数据——数据处理——发至UART

附上运行结果jpg两张,第一张,0通道引脚接在GND:

 

 

 

 

第二张,0通道接在VCC 3.3:

 

LPC1343内部ADC的使用

 

 

 

理论上3.3V为满赋值,转换结果应该是是11 1111 1111=0x3ff,不过实际并非如此,说明其实我们板子上引出的电源还是有一定波动的。

关键字:LPC1343  内部ADC 引用地址:LPC1343内部ADC的使用

上一篇:STM32学习 LED跑马灯实验
下一篇:LPC1343串口学习

推荐阅读最新更新时间:2024-03-16 14:44

ADμC812内部ADC的应用
1 ADμC812单片机内部ADC简介 1.1 ADC电路   ADμC812内部的ADC转换块包含一个5μs转换时间、8通道、12位、单电源的A/D转换器。A/D转换器由电容式DAC的常规逐次转换器组成。ADC具有单独的模拟电源和参考电压,可最大限度地减少数字电路的干扰。转换器接受的模拟电压输入范围为0~+VREF;片内提供高精度、低漂移并经厂家校准的2.5 V基准电压。ADμC812内集成的ADC转换模块有其特殊性,如果应用不当,轻则影响ADC的性能,重则电路完全不能工作,甚至烧毁器件。下面对基准电压和模拟输入电压作详细的介绍。   (1) 基准电压   ADμC812内A/D转换器的2.5 V基准电压既可由片内提供,
[单片机]
ADμC812<font color='red'>内部</font><font color='red'>ADC</font>的应用
STM32内部ADC精度的见解
从ST提供的技术手册来看,STM32F103的ADC参数是相当优秀的,高达1MHz的采样速率,12Bit,各类误差也低于中低端的专用ADC芯片。 但在实际使用,却与文档介绍的出入较大,因为开发的产品对精度要求较高,不考虑成本因素,因此PCB已经充分考虑影响精度的各个要素,采用了数字地与模拟地单点接地、多层板设计、地层完整性、AVCC单独供电,高精度AD公司的参考源提供VREF电压。在启用DMA方式采集数据时,发现虽然数据总体上的误差值很小,完全可以和大部分专用ADC媲美,但却会时不时出现一两个数值误差很大,甚至能达到+-8LSB以上。板上无任何干扰源,甚至直接把STM32上面的ADCIN引脚与AGND引脚连接,仍然不
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved