[原创] 谈谈430中ADC10四种通道采样的问题,希望能对大家有所帮助

Domen   2012-7-17 16:45 楼主
起始对于ADC10四种通道采样的问题,如何操作ADC10,我想大家应该都知道,不知道的就去看手册吧。对于大多数人来说,就像我自己,最大的困难就是如何取值,ADC10中自带一个DTC可以不借助CPU而自动传值,但是传到RAM里的值如何读出来输入到引脚上,这个肯定会令初学者头疼一阵子,其实ADC10在将模拟量转化成数字量后会储存在ADC10MEM中,然后传值时由用户设定ADC10SA的首地址,我们只要将自定义的数组首地址赋值给ADC10SA就可以了,每次传值都是按你设定通道的先后来,如果是序列通道多次转换,加入你ADC10AE0=0X06,那么首先将P1^1通道的值传到数组上,然后会自动跳转到P1^2通道的值传给数组,然后再跳回P1^1通道,单通道就只有那一个通道来回跳转,以下我赋上了自己写好的序列通道多次转换的代码,带详细注解,如果有什么错误希望大家指出:
#include
unsigned int a[32];
unsigned int i,b=0;
float v=0;
void main(void) {
        WDTCTL=WDTPW+WDTHOLD;
        P1OUT=0;
        ADC10CTL0|=ADC10ON+ADC10IE+REFON+REF2_5V+SREF_1+MSC+ADC10SHT_2;//取内部参考电压2.5V,使采样时间为16xADC10CLK,以增大采样时间以保证采样的准确性;
        ADC10CTL1|=INCH_4+CONSEQ_3;//最大采样通道为P1^4,采用序列多次采样的模式
        ADC10DTC1|=0X20;//每一个通道连续采样32次
        ADC10AE0|=0X1a;//使能通道P1^4,3,1;
        P1DIR=BIT0+BIT6;
        while(1)
        {
                ADC10CTL0&=~ENC;//关闭采样使能
                while(ADC10CTL1&ADC10BUSY);//判断是否有采样或转换动作
                ADC10CTL0|=ADC10SC+ENC;//开始采样
                ADC10SA=(unsigned int )a;//将组数a的首地址作为采样的起始地址,首先是对P1^1通道采样32次,  放入数组a中,一次循环后再对P1^3采样32次,以此类推,向下循环
                __bis_SR_register(LPM0_bits+GIE);//关闭CPU,开启总中断
                for(i=0;i<32;++i)
                {
                        b+=a;
                }
                b=b/32;//取32次采样的平均
                v=b*25;
                v=(v/1023)/10;//转化为电压值
                if(v>1.25)
                P1OUT^=BIT0;
                else
                P1OUT^=BIT6;
        }
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
        LPM0_EXIT;
}

回复评论 (55)

#include
点赞  2012-7-17 16:46
MSP430G2553.H
点赞  2012-7-17 16:50
b+=a;应该是b+=a;吧,你在取平均值的时候确定他们都32个数据都已经采样好了?而且你P1.1和P1.3两个采样的数据是不是没有全部利用啊。我也是小白,可能意见不是很给力。对了,问个问题,AD的中断触发条件到底是一次成功转换结束后触发的还是转换时间溢出才触发的?ADC10SC使能后是不是进行一次AD采样转换,然后转换结束触发中断,想要再AD采样转换就要再使能ADC10SC?有时候对一些中断的触发条件真的不了解,有没帖子或者资料总结过推荐我下。
点赞  2012-7-17 17:58
不好意思,我理解上出了点偏差,经过再次调试,发现不是对一个通道取32次值后再到下一个通道,而是以此取值,就是a【0】装的是P1^4的值,a【1】装的是P1^3的值,a【2】装的是P1^2的值,a【3】装的是P1^1的值,a【4】装的是P1^0的值,然后又是a【5】装的是P1^4的值,至于为什么P1^2和P1^0都有用,调试发现INCH_x,那个x是几那么前面所有的通道都可以用,在CONSEQ_3的模式下,也就是说ADC10AE0无效,至于为什么,我也不知道,有哪位知道的解释一下,谢谢了,楼上那位的ADC10CTL0=ENS+ADC10SC这一句是开始转换的标志,
GIE的开启标志着进入中断,资料的话我只有ADC10的中文手册,其它的没了,真抱歉……
点赞  2012-7-17 21:38
这是更正后的代码:
#include"msp430g2553.h"
unsigned int a[32],b[8];
unsigned int i,j;
float v[8];
void main(void) {
        WDTCTL=WDTPW+WDTHOLD;
        P1OUT=0;
        ADC10CTL0|=ADC10ON+ADC10IE+REFON+REF2_5V+SREF_1+MSC+ADC10SHT_2;//取内部参考电压2.5V,使采样时间为16xADC10CLK,
                                                                                                                                        //增大采样时间以保证采样的准确性;
        ADC10CTL1|=INCH_7+CONSEQ_3;//最大采样通道为P1^7,采用序列多次采样的模式,INCH_X决定了采样通道为AX~A0;
        ADC10DTC1|=0X20;//一共采样32次
        //ADC10AE0|=0XFF;//使能通道A7~A0;
        P1DIR=BIT0+BIT6;
        while(1)
        {
                ADC10CTL0&=~ENC;//关闭采样使能
                while(ADC10CTL1&ADC10BUSY);//判断是否有采样或转换动作
                ADC10CTL0|=ADC10SC+ENC;//开始采样
                ADC10SA=(unsigned int )a;//将组数a的首地址作为采样的起始地址,首先是对A7~A0依次采样放入数组a【0】~a[7]中,在循环对A7~A0依次采样,放入数组a【8】~a【15】
                                                                        //中,以此类推,向下循环直到32次结束
                __bis_SR_register(LPM0_bits+GIE);//关闭CPU,开启总中断
                for(i=0;i<8;++i)
                {
                        b=0;
                        for(j=0;j<4;++j)
                        {
                                b+=a[i+j*8];
                        }
                }
                for(i=0;i<8;++i)
                {
                        b=b/4;//取4次采样的平均
                        v=b*25;
                        v=(v/1023)/10;//转化为电压值
                }
                if(v[6]>1)
                P1OUT^=BIT6;
                else
                P1OUT^=BIT0;
        }
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void)
{
        LPM0_EXIT;//退出CPU中断
}
为了让灯亮,方便测试,我把使能ADC10AE0关了
点赞  2012-7-18 12:30
好帖,新手发现每写一句代码都要查手册上的对应语句
点赞  2012-7-18 22:43
多谢楼主的示例,我终于搞出来了
但是有个问题,在我不接输入时,显示采样的电压总是1.4V左右,为什么?
点赞  2012-7-19 10:57

楼主的代码各种编译不过啊

能不能发个能过的呢?
第一个
b+=a;报错
第二个
b,v都报错
点赞  2012-7-19 17:49
晕,那个数组框在发上去的时候没显示出来,是b 【i】和v【i】,要自己添加下,至于不接的时候会显示电压,是因为所用的引脚没有接地,所以一开始会有显示
点赞  2012-7-19 18:46
本来是使用AD12的,刚接触AD10感觉很难用,楼主这个帖子,解开了迷惑了, 现在看看看,这430的功能的确很强大,AD很灵活
点赞  2012-7-20 11:17
一直不明白采样保持shi是什么意思
点赞  2012-7-26 11:53

嘿嘿

学到啦。。。谢谢!
点赞  2012-7-26 16:40

回复 5楼 Domen 的帖子

谢谢楼主,看了你的讲解,我懂了!谢谢。期待楼主对其他模块的详细讲解!
点赞  2012-7-27 00:51
好贴
点赞  2012-7-28 16:32
不错。记得我以前也是很纠结,面对这些设置。现在写这些都是先看手册能少走很多弯路。手册说的很清楚。楼主加油。
点赞  2012-7-29 15:11

回复 6楼 Domen 的帖子

void main(void)
{

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  ADC10CTL1 = INCH_1 + ADC10DIV_0 + CONSEQ_3;         // Temp Sensor ADC10CLK/4
  ADC10CTL0 |= ADC10ON + ADC10IE + REFON + REF2_5V + SREF_1 + MSC + ADC10SHT_2;
  ADC10AE0 = 0X03;  //P1.0 P1.1 analog enable
  ADC10DTC1|=0X0a;
  delay_us(40);
  
  //LCD初始化
  LCD_init_first();
  LCD_init();

  while(1)
  {
   ADC10CTL0 &= ~ENC;//关闭采样使能
   while(ADC10CTL1 & ADC10BUSY);//判断是否有采样或转换动作
   
   ADC10CTL0 |= ADC10SC + ENC;//开始采样
   ADC10SA = (uint)a;
   _EINT();//关闭CPU,开启总中断
   LPM0;

   for(num1=0;num1<2;num++)
   {
     for(num=0;num<5;num++)
     {
        b[num1]+=a[num1+num*2];
     }
   }
   P10=b[1]/5;
   P11=b[0]/5;
   display();   
   P10_v=P10/1023*2.5;
   P11_v=P11/1023*2.5;
   display_v_P10(P10_v);
   display_v_P11(P11_v);   
  }
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
  LPM0_EXIT;// Clear CPUOFF bit from 0(SR)
}
我照着大虾写的程序来的,可是为什么没有反映呢?求助!!!
点赞  2012-7-30 09:11

回复 5楼 Domen 的帖子

楼主,这里我有点不理解,那个p1.4到p1.0循环32次的话,那数组a你一开始只定义了32,是不是不够?数组a的大小是不是应该定义为【5*32】?
点赞  2012-7-30 09:56
自己解决了
点赞  2012-7-30 11:40

回复 18楼 zhujunjiejuan 的帖子

我一开始的理解有点偏差,不是每一个通道取32次,是所有通道一共取32次值我后面的回复有更改的
点赞  2012-7-30 16:02
123下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复