標(biāo)題: STC8a單片機雙通道AD采集問題 [打印本頁]

作者: shijie240    時間: 2019-3-20 17:27
標(biāo)題: STC8a單片機雙通道AD采集問題
單片機 stc8a8k
2路電壓采集異常,求大佬指導(dǎo)一下程序,哪邊有問題?
調(diào)試設(shè)置單通道,能采集單通道電壓,設(shè)置雙通道,2個都采集不了求大佬指導(dǎo)一下
#include"stc8f.h"#include <intrins.h>
#include <stdio.h>
#define VCC  2.50
#define uint unsigned int
#define uchar  unsigned char

#define ADC_CHANNEL0         0x00            //轉(zhuǎn)換通道P1.0
#define ADC_CHANNEL1         0x01            //轉(zhuǎn)換通道P1.1
#define ADC_CHANNEL2         0x02            //轉(zhuǎn)換通道P1.2
#define ADC_CHANNEL3         0x03            //轉(zhuǎn)換通道P1.3
#define ADC_CHANNEL4         0x04            //轉(zhuǎn)換通道P1.4
#define ADC_CHANNEL5         0x05            //轉(zhuǎn)換通道P1.5
#define ADC_CHANNEL6         0x06            //轉(zhuǎn)換通道P1.6
#define ADC_CHANNEL7         0x07            //轉(zhuǎn)換通道P1.7
#define ADC_CHANNEL8         0x08            //轉(zhuǎn)換通道P0.0
#define ADC_CHANNEL9         0x09            //轉(zhuǎn)換通道P0.1
#define ADC_CHANNEL10         0x0a            //轉(zhuǎn)換通道P0.2
#define ADC_CHANNEL11         0x0b            //轉(zhuǎn)換通道P0.3
#define ADC_CHANNEL12         0x0c            //轉(zhuǎn)換通道P0.4
#define ADC_CHANNEL13         0x0d            //轉(zhuǎn)換通道P0.5
#define ADC_CHANNEL14         0x0e            //轉(zhuǎn)換通道P0.6

uint a;
bit flag_1= 0;bit flag_2=0;bit flag_3=0; bit flag_4=0;
uchar count=0;  // 變量計數(shù)器


void Delay500ms()                //@11.0592MHz
{
        unsigned char i, j, k;

        i = 29;
        j = 14;
        k = 54;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}


void Delay1ms(a)                //@11.0592MHz
{
        unsigned char i, j;

        i = 15;
        j = 90;
        do
        {
                while (--j);
        } while (--i);
}





void UartInit(void)                //9600bps@11.0592MHz
{
        SCON = 0x50;                //8位數(shù)據(jù),可變波特率
        AUXR |= 0x40;                //定時器1時鐘為Fosc,即1T
        AUXR &= 0xFE;                //串口1選擇定時器1為波特率發(fā)生器
        TMOD &= 0x0F;                //設(shè)定定時器1為16位自動重裝方式
        TL1 = 0xE0;                //設(shè)定定時初值
        TH1 = 0xFE;                //設(shè)定定時初值
        ET1 = 0;                //禁止定時器1中斷
        TR1 = 1;                //啟動定時器1
        TI=1;
}

void ADC_init()
  {
   P1M0 = 0x00;
   P1M1 = 0xff;
   P0M0 = 0x00;
   P0M1 = 0xff;
   ADCCFG = 0x0f;
   ADC_CONTR|=0x80; //開啟AD轉(zhuǎn)換電源
   Delay1ms(2);
  }

uint ADC_GetResult(unsigned char ch)
{
   uint ADC_Value=0;
   ADC_RES=0;
   ADC_RESL=0;
   ADC_CONTR|= ch;
   ADC_CONTR|= 0x40;//啟動AD轉(zhuǎn)換
   Delay1ms(1);
   while(!(ADC_CONTR&0x20));
   ADC_CONTR&=~0x20;                  //清完成標(biāo)志
   ADC_Value=ADC_RES;                                                                //讀取ADC高八位
  ADC_Value=(ADC_Value<<8)|ADC_RESL;//讀取ADC低四位,并且數(shù)據(jù)合并
  ADC_Value>>=4;                                                                                //數(shù)據(jù)右移4位,高12位為所需要的數(shù)據(jù)
  return ADC_Value;  

  }

void Timer0Init(void)                //1毫秒@11.0592MHz
{
        AUXR |= 0x80;                //定時器時鐘1T模式
        TMOD &= 0xF0;                //設(shè)置定時器模式
        TL0 = 0xCD;                //設(shè)置定時初值
        TH0 = 0xD4;                //設(shè)置定時初值
        TF0 = 0;                //清除TF0標(biāo)志
        TR0 = 1;                //定時器0開始計時
        EA = 1;                        //開總中斷
        ET0 = 1;           //開定時器T1中斷
}

void Timer0(void) interrupt 1
  {
   TL0 = 0xCD;                //設(shè)置定時初值
   TH0 = 0xD4;                //設(shè)置定時初值
        count++;                 //每次中斷加1
   if(count>=20)         //如果計數(shù)到了100ms
         {
           flag_1= 1;
         }
   if (count>=40)
     {
           flag_2= 1;
         }
   if (count>=60)
          {
           flag_3= 1;
          }
   if (count>=80)
      {
           count=0;
           flag_4= 1;
          }
   }


void main()
{
  float Vin1,Vin2;
  uint AD1=0;
  uint AD2=0;
  ADC_init();
  Timer0Init();
  UartInit();
  printf("串口初始化完畢");
  while(1)
  {
    if(flag_1==1)
          {        
           flag_1=0;
           AD1=ADC_GetResult(ADC_CHANNEL6);
                }                           
        if(flag_2==1)
          {
           flag_2=0;
         Vin1 = VCC*AD1/4090;
          }
        if(flag_3==1)
          {        
           flag_3=0;
          AD2=ADC_GetResult(ADC_CHANNEL5);
          }                           
         if(flag_4==1)
          {        
           flag_4=0;
         Vin2 = VCC*AD2/4090;
           }
        printf ("%.2f,%.2f",Vin1,Vin2);
        Delay500ms();
   }
}

作者: hhh402    時間: 2019-3-20 21:18
紅色部分有問題,應(yīng)該用else if語句,先寫:
if (count>=80)

flag_4= 1;

else if (count>=60)

flag_3= 1;

......
void Timer0(void) interrupt 1
  {
   TL0 = 0xCD;                //設(shè)置定時初值
   TH0 = 0xD4;                //設(shè)置定時初值
        count++;                 //每次中斷加1
  if(count>=20)         //如果計數(shù)到了100ms
         {
           flag_1= 1;
         }
   if (count>=40)
     {
           flag_2= 1;
         }
   if (count>=60)
          {
           flag_3= 1;
          }
   if (count>=80)
      {
           count=0;
           flag_4= 1;

          }
   }
作者: shijie240    時間: 2019-3-20 23:40
hhh402 發(fā)表于 2019-3-20 21:18
紅色部分有問題,應(yīng)該用else if語句,先寫:
if (count>=80)


不行啊,朋友這樣改,連子程序都進(jìn)不去
作者: shijie240    時間: 2019-3-21 00:10
自己解決了,多通道采集需要把原通道清零
作者: Y_G_G    時間: 2019-3-21 09:57
shijie240 發(fā)表于 2019-3-21 00:10
自己解決了,多通道采集需要把原通道清零

緩存要清除而已,兩個ADC結(jié)果保存的寄存器不需要清除的,一次完整的ADC運行之后,這兩個寄存器自然就保存了本次ADC的結(jié)果了
作者: shijie240    時間: 2019-3-21 11:46
Y_G_G 發(fā)表于 2019-3-21 09:57
緩存要清除而已,兩個ADC結(jié)果保存的寄存器不需要清除的,一次完整的ADC運行之后,這兩個寄存器自然就保存了 ...

ADC_CONTR|= ch;通道選擇要清除上一個選擇的通道,要不然進(jìn)不了下一個,多通道循環(huán)采集不了
作者: Y_G_G    時間: 2019-3-21 16:29
shijie240 發(fā)表于 2019-3-21 11:46
ADC_CONTR|= ch;通道選擇要清除上一個選擇的通道,要不然進(jìn)不了下一個,多通道循環(huán)采集不了

ADC_CONTR|= ch
這個是通道選擇,單片機只有一個ADC電路,但它有15個ADC的IO端口,所以,你是一定要選擇哪個通道進(jìn)行ADC才能正確的進(jìn)行ADC,它實際上是一個類似選擇開關(guān)的樣子
其實我看不懂你的程序,我是用匯編的,但我感覺你的代碼是有點多了,就是匯編也用不了那么多的代碼量的,更何況是C呢
作者: shijie240    時間: 2019-3-25 11:42
Y_G_G 發(fā)表于 2019-3-21 16:29
ADC_CONTR|= ch
這個是通道選擇,單片機只有一個ADC電路,但它有15個ADC的IO端口,所以,你是一定要選擇哪個 ...

我這個是測試代碼,隨便編的
作者: FJ2018    時間: 2019-3-29 13:45
學(xué)習(xí)了,樓主,我也正用到
作者: 609763691    時間: 2019-3-30 11:20
樓主,你不把這個寫在中斷里面,直接在主函數(shù)中調(diào)用一個函數(shù)直接在主函數(shù)中直接顯示會比較好,我之前都有做過,最多幾毫秒的延時就夠了,直接改變通道就行了
作者: shijie240    時間: 2019-4-3 09:50
609763691 發(fā)表于 2019-3-30 11:20
樓主,你不把這個寫在中斷里面,直接在主函數(shù)中調(diào)用一個函數(shù)直接在主函數(shù)中直接顯示會比較好,我之前都有做 ...

我采集的13個通道數(shù)據(jù),必須精確的微秒,這個是我的測試程序,項目是在子程序里面的
作者: 6726234500    時間: 2019-4-23 15:43
609763691 發(fā)表于 2019-3-30 11:20
樓主,你不把這個寫在中斷里面,直接在主函數(shù)中調(diào)用一個函數(shù)直接在主函數(shù)中直接顯示會比較好,我之前都有做 ...

分下下你的程序唄大佬
作者: 6726234500    時間: 2019-4-23 15:45
我想寫一個7通道的  該怎么搞啊  能不能分享下你的程序
作者: 6726234500    時間: 2019-4-24 15:35
shijie240 發(fā)表于 2019-3-21 00:10
自己解決了,多通道采集需要把原通道清零

怎么清零原通道 我試了下 沒成功
作者: 6726234500    時間: 2019-4-24 17:25
609763691 發(fā)表于 2019-3-30 11:20
樓主,你不把這個寫在中斷里面,直接在主函數(shù)中調(diào)用一個函數(shù)直接在主函數(shù)中直接顯示會比較好,我之前都有做 ...

能分享下程序嗎
作者: 野朝2016    時間: 2019-7-10 16:11
您好,關(guān)于STC8A單片機雙通道AD采集源碼,您這邊能不能分享一下。
作者: echowilson    時間: 2019-7-10 21:13
樓主。怎么清零通道?我也遇到這個問題了。
我的ADC函數(shù)和你差不多的。
uint GetADCresults(uchar adcch)
{
        ADC_RES  = 0;
        ADC_RESL = 0;

        ADC_CONTR |= ADC_START|adcch;               //¿aÆôADC
        Delay(10);
        while(!(ADC_CONTR & ADC_FLAG));            
        ADC_CONTR &= ~ADC_FLAG;                  
        ADC_CONTR &= ~ADC_START;                  
       
        return (ADC_RES<<8 | ADC_RESL);
}
主函數(shù)里面調(diào)用函數(shù),傳通道值獲得ADC結(jié)果,但是兩個通道得到的數(shù)據(jù)是一樣的。
DZ_Data = GetADCresults(ADCch_dz);
GD_Data = GetADCresults(ADCch_gd);

這兩句之間做了500ms 的延時,結(jié)果取出來還是差不多的,有時候還一樣。
請幫忙!~
作者: whowyj    時間: 2019-7-18 10:56
echowilson 發(fā)表于 2019-7-10 21:13
樓主。怎么清零通道?我也遇到這個問題了。
我的ADC函數(shù)和你差不多的。
uint GetADCresults(uchar adcch) ...

ADC_CONTR |= ADC_START|adcch; 這里有問題
作者: weitongguo    時間: 2019-9-12 23:36
我也是做八通道順序采集,開始沒有在循環(huán)結(jié)束時候加禁用ADC指令時候,第八通道電壓不對,而且零點也有十幾個字,加了禁用后,零點只有一個字,但是第一個通道沒有數(shù)據(jù),始終是0,不知道怎么回事了?


        ADCCFG = 0x20; //設(shè)置ADC結(jié)果右對齊,轉(zhuǎn)換速度為最快
        for (i = 0; i < 8; i++)
            {
                ADC_CONTR = (0x80 | i );                       //使能ADC模塊并設(shè)置通道
                ADC_CONTR |= 0x40;                          //啟動AD轉(zhuǎn)換
                _nop_();
                _nop_();
                while (!(ADC_CONTR & 0x20));                //查詢ADC完成標(biāo)志
                ADC_CONTR &= ~0x20;                         //清完成標(biāo)志
                ADC[i] = (ADC_RES << 8) | ADC_RESL;
            }
                ADC_CONTR = 0x00;//禁用ADC模塊
            //8個AD結(jié)果顯示輸出
        for (i = 0; i < 8; i++)
            {
                UartSend(ADC[i]>>8);
                UartSend(ADC[i]);
            }            
        UartSendStr("\r\n");//輸出回車換行符

作者: linda_6000    時間: 2021-10-26 16:27
回復(fù)19#,你在選擇通道的時候要先將ADC_CONTR &=0XF0;這樣將低四位清了,再或上通道號才能真正的到你要的通道。不然一直或或的,你想想或成什么通道了?
作者: SkyEagle    時間: 2022-9-19 17:17
6726234500 發(fā)表于 2019-4-24 15:35
怎么清零原通道 我試了下 沒成功

uint ADC_GetResult(unsigned char ch)
{
   uint ADC_Value=0;
   ADC_RES=0;
   ADC_RESL=0;
   ADC_CONTR|= ch;
   ADC_CONTR|= 0x40;//啟動AD轉(zhuǎn)換
   Delay1ms(1);
   while(!(ADC_CONTR&0x20));
   ADC_CONTR&=~0x20;                  //清完成標(biāo)志
   ADC_Value=ADC_RES;                                                                //讀取ADC高八位
  ADC_Value=(ADC_Value<<8)|ADC_RESL;//讀取ADC低四位,并且數(shù)據(jù)合并
  ADC_Value>>=4;                                                                                //數(shù)據(jù)右移4位,高12位為所需要的數(shù)據(jù)
  ADC_RES=0;                           //清除ADC高8位數(shù)據(jù)
ADC_RESL=0;                           //清除ADC低4位數(shù)據(jù)
  return ADC_Value;  

  }

即轉(zhuǎn)換1次清除1次數(shù)據(jù)




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1