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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2704|回復: 22
打印 上一主題 下一主題
收起左側

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

[復制鏈接]
跳轉到指定樓層
樓主
30黑幣
各位大神,如下代碼可實現ADC單通道采集,已驗證OK,想要實現雙通道或者多通道采集應該如何修改代碼?

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


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

#define ADC_POWER 0x80 // ADC電源控制位
#define ADC_FLAG 0x10  // ADC完成標志
#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 設置ADC基準電壓為5V

typedef unsigned char BYTE;
typedef unsigned int WORD;

BYTE ch = 0;   // ADC通道號
BYTE flag = 0; // 設置轉換完成標志位
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位二進制數
            temp = AD10bit;
            AD10bit = 0;
            ADC_RES = 0;
            ADC_RESL = 0;
            printf("value_X=%d", temp);
            printf("              ");
            //注意:先把temp強制轉換成long型,再進行電壓轉換才可獲得正確的電壓值
            result = ((long)temp * VCC / 1024);
            DisplayData(result);                                            printf("\r\n");
        }
    }
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0x03;   //設置P1.0/P1.1口為AD口
    P1M1 = 0x03;    // set 1# chanel to AD        高阻
    P1M0 = 0x00;    // set 1# chanel to AD        高阻
    CLK_DIV = 0x00; //結果右對齊
    ADC_RES = 0;    //清除結果寄存器
    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中斷服務程序
----------------------------*/
void adc_isr() interrupt 5
{
    H8bit = ADC_RES;
    L2bit = ADC_RESL;
    ADC_CONTR &= !ADC_FLAG; //清除ADC中斷標志
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
    flag = 1;
}

void UartInit(void)        //9600bps@11.0592MHz
{
        SCON = 0x50;                //8位數據,可變波特率
        AUXR |= 0x01;                //串口1選擇定時器2為波特率發生器
        AUXR &= 0xFB;                //定時器時鐘12T模式
        T2L = 0xE8;                        //設置定時初始值
        T2H = 0xFF;                        //設置定時初始值
        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 分享淘帖 頂 踩
回復

使用道具 舉報

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

使用道具 舉報

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


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


多路ADC.rar

246.18 KB, 下載次數: 10

回復

使用道具 舉報

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

STC有現成的示例

回復

使用道具 舉報

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

使用道具 舉報

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

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

使用道具 舉報

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

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

使用道具 舉報

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

感謝大神,我先用附件程序試試
回復

使用道具 舉報

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

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

使用道具 舉報

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

使用道具 舉報

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

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

使用道具 舉報

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

能稍微詳細一點說說么,大哥
回復

使用道具 舉報

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

使用道具 舉報

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

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

使用道具 舉報

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

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

使用道具 舉報

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

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

使用道具 舉報

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

使用道具 舉報

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

那我好好想想,挺懵的
回復

使用道具 舉報

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

我現在是用中斷做的獲取ADC的值,掃描方式還不太會
回復

使用道具 舉報

20#
ID:1071654 發表于 2024-4-10 15:00 | 只看該作者
xiaobendan001 發表于 2024-4-9 15:37
比如
弄個ad[8],i
i=0;

我試試,謝謝哥
回復

使用道具 舉報

21#
ID:1071654 發表于 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完成標志
#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 設置ADC基準電壓為5V

typedef unsigned char BYTE;
typedef unsigned int WORD;

BYTE ch ;   // ADC通道號
BYTE flag = 0; // 設置轉換完成標志位
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位二進制數
            temp = AD10bit;
            AD10bit = 0;
            ADC_RES = 0;
            ADC_RESL = 0;
//            printf("value_X=%d", temp);
//            printf("              ");
            //注意:先把temp強制轉換成long型,再進行電壓轉換才可獲得正確的電壓值
            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位二進制數
            dat = AD10bit;
            AD10bit = 0;
            ADC_RES = 0;
            ADC_RESL = 0;
//            printf("value_Y=%d", dat);
//            printf("              ");
            //注意:先把dat強制轉換成long型,再進行電壓轉換才可獲得正確的電壓值
            result1 = ((long)dat * VCC / 1024);
//            DisplayData(result);
//            printf("\r\n");

                                        }
        }
    }
}

/*----------------------------
初始化ADC
----------------------------*/
void InitADC()
{
    P1ASF = 0x03;   //設置P1.0/P1.1口為AD口
    P1M1 = 0x03;    // set 1# chanel to AD        高阻
    P1M0 = 0x00;    // set 1# chanel to AD        高阻
    CLK_DIV = 0x00; //結果右對齊
    ADC_RES = 0;    //清除結果寄存器
    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中斷服務程序
----------------------------*/
void adc_isr() interrupt 5
{
    H8bit = ADC_RES;
    L2bit = ADC_RESL;
    ADC_CONTR &= !ADC_FLAG; //清除ADC中斷標志
                ch++;
                ch%=2;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
    flag = 1;
}

void UartInit(void)        //9600bps@11.0592MHz
{
        SCON = 0x50;                //8位數據,可變波特率
        AUXR |= 0x01;                //串口1選擇定時器2為波特率發生器
        AUXR &= 0xFB;                //定時器時鐘12T模式
        T2L = 0xE8;                        //設置定時初始值
        T2H = 0xFF;                        //設置定時初始值
        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;
}

回復

使用道具 舉報

22#
ID:1092316 發表于 2024-4-10 21:22 來自手機 | 只看該作者
wen1989jun 發表于 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;      //設置 ADC 內部時序,ADC采樣時間建議設
    ADCCFG = 0x2f;      //設置 ADC 時鐘為系統時鐘/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 轉換
    _nop_();
    _nop_();
    _nop_();
    _nop_();

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

使用道具 舉報

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

謝謝哥,我先去試試。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日本三级日产三级国产三级 | 色综合天天综合网国产成人网 | av播播| 欧美成人一级视频 | 一级毛片,一级毛片 | 亚洲精品二区 | 欧美精品在线看 | 在线中文视频 | 欧美一级大片 | 操到爽| 麻豆久久久久久久久久 | 精品视频在线一区 | 亚洲成人一区二区 | 99pao成人国产永久免费视频 | 国产1区| 亚洲性综合网 | 欧美一级大片免费看 | 国产在线精品一区 | 欧美日韩三级在线观看 | 欧美一区2区三区4区公司二百 | 热re99久久精品国产99热 | 一区二区蜜桃 | 欧美久久一区二区三区 | 成人依人| 国产精品精品视频一区二区三区 | 狠狠干天天干 | 超碰97人人人人人蜜桃 | 精品二区| 欧美一区免费 | caoporn免费在线视频 | 男人的天堂在线视频 | 网址黄| av网站观看 | 亚洲天堂网站 | 国产精品揄拍一区二区 | 国产在线麻豆精品入口 | 国产精品一区二区三区四区 | 精精精精xxxx免费视频 | 国产精品视频二区三区 | 免费成人在线网站 | hitomi一区二区三区精品 |