久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2620|回復(fù): 22
打印 上一主題 下一主題
收起左側(cè)

STC15單片機多通道ADC采集疑問

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1071654 發(fā)表于 2024-4-7 15:50 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
30黑幣
各位大神,如下代碼可實現(xiàn)ADC單通道采集,已驗證OK,想要實現(xiàn)雙通道或者多通道采集應(yīng)該如何修改代碼?

如果需要在中斷中修改代碼,應(yīng)該如何做到切換,以雙通道為例子,感謝大家,謝謝!


#include "STC15.h"
#include <stdio.h>
#include "intrins.h"

#define ADC_POWER 0x80 // ADC電源控制位
#define ADC_FLAG 0x10  // ADC完成標(biāo)志
#define ADC_START 0x08 // ADC起始控制位

#define ADC_SPEEDLL 0x00 // 540個時鐘
#define ADC_SPEEDL 0x20  // 360個時鐘
#define ADC_SPEEDH 0x40  // 180個時鐘
#define ADC_SPEEDHH 0x60 // 90個時鐘
#define VCC 5000         // set ADC_REF_VCC 設(shè)置ADC基準(zhǔn)電壓為5V

typedef unsigned char BYTE;
typedef unsigned int WORD;

BYTE ch = 0;   // ADC通道號
BYTE flag = 0; // 設(shè)置轉(zhuǎn)換完成標(biāo)志位
BYTE H8bit = 0, L2bit = 0;
WORD AD10bit = 0, temp = 0, dat = 0, dat1 = 0;
unsigned long result = 0;

void InitADC();
void UartInit(void);
char putchar(char c);
void Delay(WORD n);
void DisplayData(unsigned int iData);

void main()
{
    InitADC(); //初始化ADC
    while (1)
    {
        if (flag)
        {
            flag = 0;
            AD10bit = (AD10bit | H8bit) & 0x00ff;
            AD10bit = (AD10bit << 2) | (L2bit & 0X03); //合并成10位二進制數(shù)
            temp = AD10bit;
            AD10bit = 0;
            ADC_RES = 0;
            ADC_RESL = 0;
            printf("value_X=%d", temp);
            printf("              ");
            //注意:先把temp強制轉(zhuǎn)換成long型,再進行電壓轉(zhuǎn)換才可獲得正確的電壓值
            result = ((long)temp * VCC / 1024);
            DisplayData(result);                                            printf("\r\n");
        }
    }
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0x03;   //設(shè)置P1.0/P1.1口為AD口
    P1M1 = 0x03;    // set 1# chanel to AD        高阻
    P1M0 = 0x00;    // set 1# chanel to AD        高阻
    CLK_DIV = 0x00; //結(jié)果右對齊
    ADC_RES = 0;    //清除結(jié)果寄存器
    ADC_RESL = 0;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START|ch ;
    Delay(10); // ADC上電并延時

    AUXR |= 0x10; // set EADCI
    IE = 0xa0;    // Enable ADC interrupt and Open master interrupt switch
}

/*----------------------------
軟件延時
----------------------------*/
void Delay(WORD n)
{
    WORD x;

    while (n--)
    {
        x = 5000;
        while (x--);
    }
}

void DisplayData(unsigned int iData)
{
    char NumStr[4] = {0, 0, 0, 0}, i = 0;
    NumStr[0] = iData / 1000;         // 千位
    NumStr[1] = (iData % 1000) / 100; // 百位
    NumStr[2] = iData % 100 / 10;     // 十位
    NumStr[3] = iData % 10;           // 個位
    printf("ADC1=");
    printf("%c", NumStr[0] + 0x30);
    printf("%c", NumStr[1] + 0x30);
    printf(".");
    printf("%c", NumStr[2] + 0x30);
    printf("%c", NumStr[3] + 0x30);
}

/*----------------------------
ADC中斷服務(wù)程序
----------------------------*/
void adc_isr() interrupt 5
{
    H8bit = ADC_RES;
    L2bit = ADC_RESL;
    ADC_CONTR &= !ADC_FLAG; //清除ADC中斷標(biāo)志
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
    flag = 1;
}

void UartInit(void)        //9600bps@11.0592MHz
{
        SCON = 0x50;                //8位數(shù)據(jù),可變波特率
        AUXR |= 0x01;                //串口1選擇定時器2為波特率發(fā)生器
        AUXR &= 0xFB;                //定時器時鐘12T模式
        T2L = 0xE8;                        //設(shè)置定時初始值
        T2H = 0xFF;                        //設(shè)置定時初始值
        AUXR |= 0x10;                //定時器2開始計時
        ES=1;                                                //允許串行口中斷
        EA=1;                                                //允許總中斷
}


char putchar(char c)
{
    UartInit();
    ES = 0;
    SBUF = c;
    while (TI == 0);
    TI = 0;
    ES = 1;
    return 0;
}



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:1071654 發(fā)表于 2024-4-7 17:35 | 只看該作者
先自頂下,有好的答案就采納了
回復(fù)

使用道具 舉報

板凳
ID:226055 發(fā)表于 2024-4-7 20:13 | 只看該作者
    1、你好,不知道你單片機的具體型號。我手頭正好有艾克姆的STC15開發(fā)板,單片機是STC15W4K56S4,用這個硬件我調(diào)通了多路ADC。


    2、你的如果是STC15F應(yīng)該也是可以的,具體你可以參考附件程序。


多路ADC.rar

246.18 KB, 下載次數(shù): 10

回復(fù)

使用道具 舉報

地板
ID:213173 發(fā)表于 2024-4-7 20:41 | 只看該作者
wen1989jun 發(fā)表于 2024-4-7 17:35
先自頂下,有好的答案就采納了

STC有現(xiàn)成的示例

回復(fù)

使用道具 舉報

5#
ID:1034262 發(fā)表于 2024-4-7 23:27 | 只看該作者
改通道數(shù)就可以了啊,ADC_CONTR低3位。可以直接參考STC官方的例子。
回復(fù)

使用道具 舉報

6#
ID:1071654 發(fā)表于 2024-4-8 10:56 | 只看該作者
wulin 發(fā)表于 2024-4-7 20:41
STC有現(xiàn)成的示例

嗨,就是這個官方例程看得有點懵啊
回復(fù)

使用道具 舉報

7#
ID:1071654 發(fā)表于 2024-4-8 10:58 | 只看該作者
coody_sz 發(fā)表于 2024-4-7 23:27
改通道數(shù)就可以了啊,ADC_CONTR低3位。可以直接參考STC官方的例子。

這個寄存器ADC_CONTR我只會修改其中一路,想要如:ADC0,ADC1通道分時用就不會了
回復(fù)

使用道具 舉報

8#
ID:1071654 發(fā)表于 2024-4-8 10:58 | 只看該作者
cocolala 發(fā)表于 2024-4-7 20:13
1、你好,不知道你單片機的具體型號。我手頭正好有艾克姆的STC15開發(fā)板,單片機是STC15W4K56S4,用這個 ...

感謝大神,我先用附件程序試試
回復(fù)

使用道具 舉報

9#
ID:213173 發(fā)表于 2024-4-8 22:08 | 只看該作者
wen1989jun 發(fā)表于 2024-4-8 10:56
嗨,就是這個官方例程看得有點懵啊

你定義了變量  BYTE ch = 0;   // ADC通道號  ,在ADC轉(zhuǎn)換程序中使用ch時沒有改變ch值,那就只能重復(fù)采樣0通道,要想多通道采集就得改變ch值,取值范圍0-7。
回復(fù)

使用道具 舉報

10#
ID:1109793 發(fā)表于 2024-4-9 09:36 | 只看該作者
搞個計數(shù)器,每次讀完了就++嘛
回復(fù)

使用道具 舉報

11#
ID:1071654 發(fā)表于 2024-4-9 14:42 | 只看該作者
wulin 發(fā)表于 2024-4-8 22:08
你定義了變量  BYTE ch = 0;   // ADC通道號  ,在ADC轉(zhuǎn)換程序中使用ch時沒有改變ch值,那就只能重復(fù)采樣 ...

那這個要在程序上實現(xiàn)應(yīng)該怎么寫呢?
讓ch在中斷程序中自+,比如兩通道>2就回到0?
不是太懂,望大神解惑,感謝!
回復(fù)

使用道具 舉報

12#
ID:1071654 發(fā)表于 2024-4-9 14:43 | 只看該作者
xiaobendan001 發(fā)表于 2024-4-9 09:36
搞個計數(shù)器,每次讀完了就++嘛

能稍微詳細(xì)一點說說么,大哥
回復(fù)

使用道具 舉報

13#
ID:1115937 發(fā)表于 2024-4-9 14:52 | 只看該作者
你查手冊,把通道數(shù)對應(yīng)就行了
回復(fù)

使用道具 舉報

14#
ID:1071654 發(fā)表于 2024-4-9 15:03 | 只看該作者
目前在中斷里面把ch++后,可以抓取P1.0,P1.1的ADC數(shù)據(jù)了,帶來了新的問題應(yīng)該怎么區(qū)分這兩個數(shù)據(jù)呢?頭大

void adc_isr() interrupt 5
{
    H8bit = ADC_RES;
    L2bit = ADC_RESL;
    ADC_CONTR &= !ADC_FLAG; //清除ADC中斷標(biāo)志
                ch++;
                ch%=2;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
    flag = 1;
}
回復(fù)

使用道具 舉報

15#
ID:192020 發(fā)表于 2024-4-9 15:20 | 只看該作者
wen1989jun 發(fā)表于 2024-4-9 15:03
目前在中斷里面把ch++后,可以抓取P1.0,P1.1的ADC數(shù)據(jù)了,帶來了新的問題應(yīng)該怎么區(qū)分這兩個數(shù)據(jù)呢?頭大
...

你都知道改ch換通道了,怎么就不能判斷ch是哪個通道呢
回復(fù)

使用道具 舉報

16#
ID:1109793 發(fā)表于 2024-4-9 15:37 | 只看該作者
wen1989jun 發(fā)表于 2024-4-9 14:43
能稍微詳細(xì)一點說說么,大哥

比如
弄個ad[8],i
i=0;
讀出結(jié)果放ad[i ][ i];然后i++,啟動第i通道
下次中斷再讀出還放ad[ i],然后再i++直到i>7則i=0;
回復(fù)

使用道具 舉報

17#
ID:1115852 發(fā)表于 2024-4-9 16:32 | 只看該作者
ADC數(shù)模轉(zhuǎn)化配合dmA數(shù)據(jù)搬運 可以配置一些單多通道,掃描模式來完成效果
回復(fù)

使用道具 舉報

18#
ID:1071654 發(fā)表于 2024-4-9 18:35 | 只看該作者
qq475878026 發(fā)表于 2024-4-9 15:20
你都知道改ch換通道了,怎么就不能判斷ch是哪個通道呢

那我好好想想,挺懵的
回復(fù)

使用道具 舉報

19#
ID:1071654 發(fā)表于 2024-4-10 15:00 | 只看該作者
felicityocihjwe 發(fā)表于 2024-4-9 16:32
ADC數(shù)模轉(zhuǎn)化配合dmA數(shù)據(jù)搬運 可以配置一些單多通道,掃描模式來完成效果

我現(xiàn)在是用中斷做的獲取ADC的值,掃描方式還不太會
回復(fù)

使用道具 舉報

20#
ID:1071654 發(fā)表于 2024-4-10 15:00 | 只看該作者

我試試,謝謝哥
回復(fù)

使用道具 舉報

21#
ID:1071654 發(fā)表于 2024-4-10 15:03 | 只看該作者
目前按照下面代碼方式能獲取到兩個通道的ADC值了,各位大哥幫忙看看有沒有其他問題,感謝感謝!

#include "STC15.h"
#include <stdio.h>
#include "intrins.h"

#define ADC_POWER 0x80 // ADC電源控制位
#define ADC_FLAG 0x10  // ADC完成標(biāo)志
#define ADC_START 0x08 // ADC起始控制位

#define ADC_SPEEDLL 0x00 // 540個時鐘
#define ADC_SPEEDL 0x20  // 360個時鐘
#define ADC_SPEEDH 0x40  // 180個時鐘
#define ADC_SPEEDHH 0x60 // 90個時鐘
#define VCC 5000         // set ADC_REF_VCC 設(shè)置ADC基準(zhǔn)電壓為5V

typedef unsigned char BYTE;
typedef unsigned int WORD;

BYTE ch ;   // ADC通道號
BYTE flag = 0; // 設(shè)置轉(zhuǎn)換完成標(biāo)志位
BYTE H8bit = 0, L2bit = 0;
WORD AD10bit = 0, temp = 0, dat = 0, dat1 = 0;
unsigned long result = 0;result1 = 0;

void InitADC();
void UartInit(void);
char putchar(char c);
void Delayms(unsigned xms);
void DisplayData(unsigned int iData);

void main()
{
    InitADC(); //初始化ADC
    while (1)
    {
        if (flag)
        {
                                        if(ch==1)
                                        {
            flag = 0;
            AD10bit = (AD10bit | H8bit) & 0x00ff;
            AD10bit = (AD10bit << 2) | (L2bit & 0X03); //合并成10位二進制數(shù)
            temp = AD10bit;
            AD10bit = 0;
            ADC_RES = 0;
            ADC_RESL = 0;
//            printf("value_X=%d", temp);
//            printf("              ");
            //注意:先把temp強制轉(zhuǎn)換成long型,再進行電壓轉(zhuǎn)換才可獲得正確的電壓值
            result = ((long)temp * VCC / 1024);
//            DisplayData(result);
//            printf("\r\n");
                                               
                                        }
                                        if(ch==0)
                                        {
                                                flag = 0;
            AD10bit = (AD10bit | H8bit) & 0x00ff;
            AD10bit = (AD10bit << 2) | (L2bit & 0X03); //合并成10位二進制數(shù)
            dat = AD10bit;
            AD10bit = 0;
            ADC_RES = 0;
            ADC_RESL = 0;
//            printf("value_Y=%d", dat);
//            printf("              ");
            //注意:先把dat強制轉(zhuǎn)換成long型,再進行電壓轉(zhuǎn)換才可獲得正確的電壓值
            result1 = ((long)dat * VCC / 1024);
//            DisplayData(result);
//            printf("\r\n");

                                        }
        }
    }
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0x03;   //設(shè)置P1.0/P1.1口為AD口
    P1M1 = 0x03;    // set 1# chanel to AD        高阻
    P1M0 = 0x00;    // set 1# chanel to AD        高阻
    CLK_DIV = 0x00; //結(jié)果右對齊
    ADC_RES = 0;    //清除結(jié)果寄存器
    ADC_RESL = 0;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START|ch ;
    Delayms(1); // ADC上電并延時1ms
    AUXR |= 0x10; // set EADCI
    IE = 0xa0;    // Enable ADC interrupt and Open master interrupt switch
}

/*----------------------------
軟件延時
----------------------------*/

void Delayms(unsigned xms)        //@11.0592MHz
{
        unsigned char data i, j;

        while(xms--)
        {
        _nop_();
        _nop_();
        _nop_();
        i = 11;
        j = 190;
        do
        {
                while (--j);
        } while (--i);
               
        }
}


void DisplayData(unsigned int iData)
{
    char NumStr[4] = {0, 0, 0, 0}, i = 0;
    NumStr[0] = iData / 1000;         // 千位
    NumStr[1] = (iData % 1000) / 100; // 百位
    NumStr[2] = iData % 100 / 10;     // 十位
    NumStr[3] = iData % 10;           // 個位
    printf("ADC1=");
    printf("%c", NumStr[0] + 0x30);
    printf("%c", NumStr[1] + 0x30);
    printf(".");
    printf("%c", NumStr[2] + 0x30);
    printf("%c", NumStr[3] + 0x30);
}

/*----------------------------
ADC中斷服務(wù)程序
----------------------------*/
void adc_isr() interrupt 5
{
    H8bit = ADC_RES;
    L2bit = ADC_RESL;
    ADC_CONTR &= !ADC_FLAG; //清除ADC中斷標(biāo)志
                ch++;
                ch%=2;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
    flag = 1;
}

void UartInit(void)        //9600bps@11.0592MHz
{
        SCON = 0x50;                //8位數(shù)據(jù),可變波特率
        AUXR |= 0x01;                //串口1選擇定時器2為波特率發(fā)生器
        AUXR &= 0xFB;                //定時器時鐘12T模式
        T2L = 0xE8;                        //設(shè)置定時初始值
        T2H = 0xFF;                        //設(shè)置定時初始值
        AUXR |= 0x10;                //定時器2開始計時
        ES=1;                                                //允許串行口中斷
        EA=1;                                                //允許總中斷
}


char putchar(char c)
{
    UartInit();
    ES = 0;
    SBUF = c;
    while (TI == 0);
    TI = 0;
    ES = 1;
    return 0;
}

回復(fù)

使用道具 舉報

22#
ID:1092316 發(fā)表于 2024-4-10 21:22 來自手機 | 只看該作者
wen1989jun 發(fā)表于 2024-4-10 15:00
我試試,謝謝哥

這個可以用,你改一下。
#include "stc8g.h"     //讀多通道ADC
#include "intrins.h"

typedef     unsigned char   u8;
typedef     unsigned int    u16;

#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)

u16 Get(u8 channel); //channel = 0~15

void maindd(void)
  {          if(Get(3)>150)       
                {  P55=0;}
        else{P55=1;}}
         
void main(void)
{  P_SW2 |= 0x80;  //擴展寄存器(XFR)訪問使能

    P3M0 &= ~0x0f; P3M1 |= 0x0f; //高阻
    P5M0 &= ~0x30; P5M1 &= ~0x30;

     ADCTIM = 0x3f;      //設(shè)置 ADC 內(nèi)部時序,ADC采樣時間建議設(shè)
    ADCCFG = 0x2f;      //設(shè)置 ADC 時鐘為系統(tǒng)時鐘/2/16
    ADC_CONTR = 0x80; //使能 ADC 模塊
       
   while(1)
   {
        maindd();
                            }}

u16 Get(u8 channel)  //channel = 0~15
{
    ADC_RES = 0;
    ADC_RESL = 0;

    ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | channel;    //啟動 AD 轉(zhuǎn)換
    _nop_();
    _nop_();
    _nop_();
    _nop_();

    while((ADC_CONTR & 0x20) == 0)  ;   //wait for ADC finish
    ADC_CONTR &= ~0x20;     //清除ADC結(jié)束標(biāo)志
    return  (((u16)ADC_RES << 8) | ADC_RESL);
}
回復(fù)

使用道具 舉報

23#
ID:1071654 發(fā)表于 2024-4-11 10:12 | 只看該作者
jch352122 發(fā)表于 2024-4-10 21:22
這個可以用,你改一下。
#include "stc8g.h"     //讀多通道ADC
#include "intrins.h"

謝謝哥,我先去試試。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 在线观看视频亚洲 | av黄色国产 | 日日干夜夜操 | 国产一二区免费视频 | 精品国产久 | 天天看天天操 | 免费看国产精品视频 | 国产高清一区二区三区 | 欧美性受xxxx | 日韩中文在线视频 | 久久夜视频 | 另类在线 | 99精品福利视频 | 国产在线一区二区 | 久久精品一 | 免费的黄色片子 | 91国产精品 | 国产9 9在线 | 中文 | 欧美久久天堂 | 精品久久久久久久久久久久久久 | 超碰综合 | 91视频在线观看免费 | 成年人精品视频在线观看 | 免费观看毛片 | 中文字幕黄色大片 | 精品中文字幕一区 | 久久免费香蕉视频 | 中文无吗 | 国产精品日日夜夜 | 国产一区二区三区欧美 | 亚洲国产一区二区在线 | 天天干天天草 | www97影院 | 日韩毛片中文字幕 | 精品国产乱码久久久久久闺蜜 | 日韩欧美在线一区 | 日韩精品成人 | 精品一区二区三区在线观看国产 | 中文字幕一区二区三区不卡 | 国产精品区二区三区日本 | 97超碰站|