×
嵌入式 > 技术百科 > 详情

CC2430单片机AD转换使用方法总结

发布时间:2020-05-28 发布时间:
|

CC2430单片机标称AD转换精度为14位,在单片机中算是比较高的了,CC2430最广泛的用途是作为传感器来使用的,而传感器测量的物理量的原理多半是将物理量转换成电流、电压等模拟信号,再通过AD转换进入单片机处理。所有用好CC2430的AD是使用好CC2430的一项基本技能。

一、CC2430的ad的几个重要参数

      1、量化精度14位

       2、转换方式为代儿塔-西格玛方式

       3、8路独立通道、4路差分通道

      4、参考电压可选内部、外部参考电压;(具体参考datasheet)

      5、有DMA功能;(每个通道都能触发),这个功能我认为非常重要,主要是做交流采样,很方便也很容易处理

      6、精度可选;

二、单通道AD转换

      单通道ad转换很简单,需要注意的是

     1、搞清几个AD寄存器的作用、设置的方法P0IFG、PERCFG、P0SEL、ADCCFG、P0DIR

     2、被测电压的负极要连到CC2430的GND上

     3、转换后数值的ADCL、ADCH内数值的处理,要将ADCH放在低字节、ADCL放在高字节。将一个Uint16右移两位(最后两位没有用);即可得到所要的ADC值;

     4、电压计算公式=ADC/精度*参考电压;

          ADC:第3条所得

          精度:根据所选位数,例如位数选14位,精度=2的14次方=16384

          参考电压:可选内部或者外部,例如选内部的1.25伏。

    5、输入电压不要超过参考电压。

二、差分通道转换

    1、选对输入引脚、设对寄存器

     2、电压计算公式=ADC/精度*参考电压;这里的精度相对于单通道的精度要再除以2

        例如:转换的值=4567; 位数=14位 ;参考电压=1.25v 则被测电压=4567/16384*2*1.25=0.6969 伏

        再例如:转换的值为=12345; 位数=14位 ;参考电压=1.25v 则被测电压=(12345-16384)/16384*2*1.25=-0.6163 伏

三、使用差分通道转换时如何进行补偿

      所有的AD器件都有可能有一定的0点偏差,即电压输入为0时,转换结果不为0,有可能大于0,也有可能小于0.所以,要得到正确的结果就要进行补偿。应遵循以下几个步骤:

       1、测channel=0x0c,时的AD值

            通道号选0xc时,单片机认为被测电压为0,测得AD值为ADoffset1(有可能为+、也有可能为-);

       2、测被测通道的AD值

            假设测P0.4、P0.5两个引脚间的电压,测得AD值为ADC(有可能为+、也有可能为-);

       3、被测电压=(ADC-ADoffset)/精度*2*参考电压;

四、使用DMA通道进行AD采样;

        CC2430的DMA通道功能很强大,有多个触发源。详见datasheet;

        交流采样时使用DMA AD转换有很多好处

        a、采样间隔容易计算

          采样间隔可通过公式Tconv = (decimation rate + 16) x 0.25 μs.来计算14位是decimation=512

        b、AD采用的同时、单片机可以做其他事情,互相不干扰

       c、存储在一个数组之中,便于以后计算。

      

        1、首先要了解CC2430的DMA怎么使用

         2、可参考我的另一篇文章《CC2430 利用dma存储adc连续转换数据的存储,及转换时间的计算》

        3、举例说明:程序比较长可以只看前半部分,后半部分功能为计算对正弦波正弦波正半周平均值,DMA转换的精髓在上半部分。

float getseadc (uint8 channel, uint8 refvolt)
{
volatile uint16 reading = 0;
uint8 resbits;
volatile uint16   adctemp,i;
volatile uint8 tmp;
uint8 adcChannel = 1;
volatile float sum,sum1;
int tmp1,max,m,n,X,lst;//m为大数,n为小数
ADCCFG |= adcChannel;

   if (channel==0x0A)
{
    ADCCFG=0x30;
};


resbits=0x30;

tmp = ADCL;
tmp = ADCH;

osal_int_disable( INTS_ALL );
//配置dma
adcdma.srcAddrH=0xDF;           //adch的逻辑地址
adcdma.srcAddrL=0xBA;         //adcl的逻辑地址
adcdma.dstAddrH=(uint8)((uint16)&adctab>>8);   //目标内存块中的地址高位
adcdma.dstAddrL=(uint8)&adctab;                //目标内存块中的地址地位
adcdma.xferLenV=0x03;                          //
adcdma.xferLenL=0x20;                          //传送0x320个字符
adcdma.ctrlA=0xd7;                             // word传送 not bytes ;重复单次传送;1号差分通道结束后触发
adcdma.ctrlB=0x10;                             //目的地址自动加1,中断不打开。
DMA0CFGL=(uint8)&adcdma;                       //将0号dma通道设置为上述结构
DMA0CFGH=(uint8)((uint16)&adcdma>>8);                  
DMAARM=0x01;                                   //投入0号dma通道asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

adctemp = channel | resbits | (refvolt<<6);


ADCCON2 = adctemp;
ADC_SAMPLE_CONTINUOUS();


tmp=0;
while (!(DMAIRQ & 0x01));
DMAARM|=(1<<7);
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");

DMAIRQ=0;

ADC_STOP();       //转换结束 ,至此所有800次AD转换的值已经存在adctab中了。
tmp=ADCL;
tmp=ADCH;
ADCCFG &= ~adcChannel;
sum=0;
sum1=0;
max=0;
tmp1=0;
X=-1;
lst=-1;
for(i=0;i<800;i++)
{
//int AdtoInt(uint16 adctmp,int offset)

   //转换成int
   tmp1=AdtoInt(adctab[i],(int)ADoffset2);
   //存储到原来的空间里
   adctab[i]=(uint16)tmp1;
   //判断过零点
   if((i>0) && ( *((int*)(adctab+i))<0) && (*((int*)(adctab+i-1))>=0))
   {
      if(X==-1)
      {
        n=(int)i;
        lst=(int)i;
        X=0;
      }
      else
      {
        if((i-lst)>120)
        {
      X++;
      lst=i;
        }
      }
      if(X==4)
      {
        m=(int)i;
      }
   }
    //取绝对值
   if(tmp1<0)
   {
   tmp1=0-tmp1;
   }
   //累加
   if(X>=0 && X<4)
   {
   sum+=(float)tmp1;
   }
   //取最大值
   if(tmp1>max)
   {
     max=tmp1;
   }
   sum1+=(float)tmp1;
}
osal_int_enable(INTS_ALL);

// 最大值如果小于 0x2000的5%则有可能杂波干扰比较大,真正的过零点难找,而又因为只有5%,所以累加后求平均值对最后的计算结果影响很小
if(max<410)
{
    return (sum1/800);
}
else
{
    return (sum/(m-n));
}

};


//将无符号整数转换为int 大于0x1fff的为负数   偏移量要从float转成int
int AdtoInt(volatile uint16 adctmp,int offset)
{
    int tmp1;
    adctmp=(adctmp<<8)|(adctmp>>8);
    adctmp>>=2;
    if(adctmp>8191)
    {
      tmp1=(int)adctmp-0x4000-offset;
    }
    else
    {
      tmp1=(int)adctmp-offset;
    }

    return tmp1;
}

 

五、至此我使用cc2430AD转换的心得已经讲完了,希望对大家的开发工作有点帮助。

 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
分布式光纤温度传感器(DTS)系统的应用