lhcyy 发表于 2012-5-10 14:53:33

STC12C5A60S2里面ADC采样,结果转换,和结果存放问题




         最近我在弄STC12C5A60S2里面的ADC采样,现在想把结果转换成10进制,然后把八个通道的结果存放在数组里面,以备以后调用
下面是我的程序大家帮忙看看该这么弄
float ADC_CHresult;
//float ADC_avl;


void ADC_Init()
{
        P1M1=0xff;
        P1M0=0x00;
        P1ASF=0xff;//选择ADC通道
        ADC_CONTR=ADC_POWER|SPEEDHH;
        ADC_RES=0;
        ADC_RESL=0;

        }
uint GET_ADCresult(uchar ch)
    {
          int ADC_result;
          uchar ADC_f=0;
          ADC_RES=0;
          ADC_RESL=0;
          ADC_CONTR=ADC_POWER|SPEEDHH|ADC_START|ADC_CH;

          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          while(ADC_f==0)
             {
                   ADC_f=ADC_CONTR&0x10;
               }

          


          ADC_result=ADC_RES*4+ADC_RESL;
          ADC_CONTR &=0xf7;

          return(ADC_result);


       }
float ADC_av(uchar ch)
      {
          float ADC_avl=0;
       
                uchar num;
                num=10;
                for(num=10;num>0;num--)
                {
                  ADC_avl = ADC_avl +GET_ADCresult(ch);
                  
                }                                                               这里好像转换结果是带小数的,我想提取里面的整数部分然后存放在数组里面,可这个程序实际是不行的
            
                  ADC_avl/=10.0;
                  ADC_CHresult =(ADC_avl*20.0)/1024;         这个语句是把结果转为10进制,实际是(ADC_avl*5*1000/250)1024; 目的是为了算出最后出来的电流。有能帮忙分析下的吗

                  return(ADC_CHresult );                           或者有这个方面的资料:adc结果转换,并存入数组。
         }

weakdancer 发表于 2012-5-10 16:53:10

float ADC_CHresult;
这里应该使用两个字节的unsigned int型

lhcyy 发表于 2012-5-10 17:25:06

weakdancer 发表于 2012-5-10 16:53 static/image/common/back.gif
float ADC_CHresult;
这里应该使用两个字节的unsigned int型

呵呵主要是数组里面,如过我们得到的是20那放入数组里面该什么形式,取出来的时候什么样子,头疼

黑暗深处 发表于 2012-5-10 18:58:02

看程序,你用的A/D应该是10位的,不是八位的

你试试看把
ADC_CHresult =(ADC_avl*20.0)/1024;
改成
ADC_CHresult =(unsigned int)((ADC_avl*20.0)/1024);

weakdancer 发表于 2012-5-10 23:15:07

lhcyy 发表于 2012-5-10 17:25 static/image/common/back.gif
呵呵主要是数组里面,如过我们得到的是20那放入数组里面该什么形式,取出来的时候什么样子,头疼 ...

uint GET_ADCresult(uchar ch)
int ADC_result;
return(ADC_result);
这里函数返回unsigned int
ADC_result 你却定义成了int型

如果想要对位进行控制,数据类型是必须了解的。

int和unsigned int 是不同的。

同样 我不理解这里用float干什么?
另外也不太理解你的问题到底是什么意思?

我觉得没必要用小数。8位时0-255十位时自然的0-1023就行了。

因为10比8 多二位是在二进制上的,不是十进制。

lhcyy 发表于 2012-5-11 09:00:02

回复楼上的,同样也再解释下。我做的是一次循环采集8个通道AD采集数据。现在每个通道采集10次求平均。然后把十位数据,通过float转换为浮点数据,最后把数据存放在一个数组里面。比如我这次转换后数据是15.368.那么这个数据怎么放入数组呢。还有如何从中取出整数部分呢。求解答

lhcyy 发表于 2012-5-11 09:01:07

weakdancer 发表于 2012-5-10 23:15 static/image/common/back.gif
uint GET_ADCresult(uchar ch)
int ADC_result;
return(ADC_result);


我已经补充了问题。还有对于你说的int型数据确实是我的疏忽,谢谢,

cy_ygs 发表于 2012-6-5 14:16:05

不错,学习

yao1 发表于 2012-6-5 17:20:47

int filter(unsigned char channel)//滤波
{
                              unsigned char i;
                unsigned int adc_value;        //AD转换缓冲区       
                unsigned int adc_value_ave=0;
                unsigned int max_value=0,min_value=0,max_index=1,min_index=1;

                for (i=0;i<8;i++) //连续转换8次
                     {
                                          adc_value = get_AD_result(channel); //将单次ADC转换结果放入缓冲区         
                           //   delay(10);        //每次转换延迟时间
                     }
                for(i=1;i<8;i++) // 去掉第一次测量值
                {
                        adc_value_ave+=adc_value;       
                }
                adc_value_ave/=7; // 去掉一个值外的平均值                                                                          
                for(i=1;i<8;i++) // 计算最大值和最小值索引号 排序
                { //排序 最大值第1位 最小值最后1位
                        if(adc_value>adc_value_ave)//大于平均值
                        {                                                
                                if((adc_value-adc_value_ave)>max_value)                                                                                 
                                {                                 
                                        max_value=adc_value;
                                        max_index=1;
                                }
                        }               
                        else//小于平均值
                        {
                                if((adc_value_ave-adc_value)>min_value)
                                {
                                        min_value=adc_value_ave-adc_value;
                                        min_index=i;
                                }
                        }
                }
                adc_value_ave=0;       
                for(i=1;i<8;i++) // 计算去掉最大值和最小值后的总和
                {
                        if((i!=max_index)&&(i!=min_index))//去掉最大值和最小值
                        {
                                adc_value_ave+=adc_value;       
                        }
                }
                if(max_index!=min_index) // 如果测量值不同
                {
                        adc_value_ave/=5; // 计算平均值
                }
                else        // 如果测量值相同
                {
                        adc_value_ave/=6; // 计算平均值
                }
       
                return adc_value_ave;

}

lhcyy 发表于 2012-6-6 09:54:28

yao1 发表于 2012-6-5 17:20 static/image/common/back.gif
int filter(unsigned char channel)//滤波
{
                              unsigned char i;


这个不错,我做的时候没考虑这个,谢谢了,不错的思路

zhenglingo 发表于 2012-10-8 23:07:27

yao1 发表于 2012-6-5 17:20 static/image/common/back.gif
int filter(unsigned char channel)//滤波
{
                              unsigned char i;


      if((adc_value-adc_value_ave)>max_value)                                                                                 
                              {                                 
                                        max_value=adc_value;
                                        max_index=1;
                              }
这里的max_index是为 i还是1?

yao1 发表于 2012-10-9 08:16:39

zhenglingo 发表于 2012-10-8 23:07 static/image/common/back.gif
if((adc_value-adc_value_ave)>max_value)                                                    ...

max 1
min i

BXAK 发表于 2012-10-9 09:48:42

lhcyy 发表于 2012-5-11 09:00 static/image/common/back.gif
回复楼上的,同样也再解释下。我做的是一次循环采集8个通道AD采集数据。现在每个通道采集10次求平均。然后 ...

干嘛用浮点?用浮点很浪费空间和速度

uint16ADC_CHresult;

uint16 ADC_av(uchar ch)
{
      uint16 dat,ADC_avl;
      uchar num;

      ADC_avl = 0;
      for (num=10; num>0; num--)
       {
         ADC_avl+=GET_ADCresult(ch);
       }            
               
       //这里取消 ADC_avl/= 10;,把它看成放大10倍
       //dat = (ADC_avl*20) / 1024;         这个语句是把结果转为10进制,实际是(ADC_avl*5*1000/250)1024; 目的是为了算出最后出来的电流。有能帮忙分析下的吗
   
       dat = (ADC_avl*20*100UL) / 1024;   //再放大100倍,共1000倍

       return (dat );                                 
}

比如返回 dat = 15368 ,则是15.368,如果想在液晶屏上显示十进制,把 2字节十六进制数dat 分离成 非压缩BCD码 就行:
uint8 i,n;

for (i=5; i>0; )
{
      i--;
      n = dat%10;
      dat /= 10;
}   

结果:n=1,n=5,n=3,n=6,n=8,

xielong4183 发表于 2012-10-9 10:22:17

楼上的观点我赞同,我也一直这样做的,基本不用浮点数计算,单片机不比PC浮点是很耗时的,另外附上我的一段程序希望对楼主有帮助
//-----------------------------------------------------------------------------
// 函数原型:unsigned int ADC_measure(unsigned char ch)
// 功    能:测量多次某个通道的AD值,并将最大和最小值去掉,再求平均值
//-----------------------------------------------------------------------------
unsigned int ADC_measure(unsigned char ch)
{
        unsigned int adc_value=0x00;
        unsigned int vArry;
        unsigned char i;
        unsigned int temp;
       
        for(i=0;i<ARRAYNUM;i++)
        {
                vArry = get_AD_result(ch);//测量
        }
        for(i=0;i<ARRAYNUM-1;i++)                       //最大值放在最右边
        {
                if(vArry>=vArry)
                {
                        temp = vArry;
                  vArry = vArry;
                        vArry = temp;
                }
        }
        for(i=0;i<ARRAYNUM-2;i++)   //最小值放在右边倒数第二位置
        {
                if(vArry<=vArry)
                {
                        temp = vArry;
                  vArry = vArry;
                        vArry = temp;
                }
        }
        for(i=0;i<ARRAYNUM-2;i++)      
        {
                adc_value += vArry;                                //求0-ARRYUM-2的和
        }
        adc_value /= ARRAYNUM-2;                          //求平均数
        return(adc_value);
}

zhenglingo 发表于 2012-10-12 00:01:36

yao1 发表于 2012-10-9 08:16 static/image/common/back.gif
max 1
min i

                  for(i=1;i<8;i++) // 计算最大值和最小值索引号 排序
                { //排序 最大值第1位 最小值最后1位
                        if(adc_value>adc_value_ave)//大于平均值
                   {                                                
                              if((adc_value-adc_value_ave)>max_value)                                                                                 
                              {                                 
                                             max_value=adc_value
                                             max_index=1;
                              }
                            }
这里我始终无法理解,max_value=adc_value   max_index=1;   你的意思是将adc_value中的后7个值选出最大值,并排在第一假设adc_value=8,adc_value=9,adc_value_ave=6,那么第一次进来max_value=8,默认max_index=1,但是第二次进来时显然不会9-6=3<6,能解释下吗?


                                          

eddia2012 发表于 2012-10-12 08:34:33

滤波算法不用那么麻烦先排序:

unsigned int ADC_measure(unsigned char ch)
{
    unsigned long adc_value=0;
    unsigned int vArry,Max = 0x0000,Min = 0xffff;
    unsigned char i;
    unsigned int temp;
      
    for(i=0;i<ARRAYNUM;i++)
    {
      vArry = get_AD_result(ch);//测量
      if(vArry > Max) Max = vArry;
      if(vArry < Min) Min = vArry;
      adc_value += vArry;
    }
    adc_value = adc_value - Max -Min;
    adc_value /= ARRAYNUM-2;                        //求平均数
    return(adc_value);
}

15813191501 发表于 2012-10-12 16:33:31

eddia2012 发表于 2012-10-12 08:34
滤波算法不用那么麻烦先排序:

unsigned int ADC_measure(unsigned char ch)


这个办法好,去掉最大和最小求平均值.

actshuishan 发表于 2012-10-13 07:11:49

标记学习
页: [1]
查看完整版本: STC12C5A60S2里面ADC采样,结果转换,和结果存放问题