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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5179|回復: 15
收起左側

使用STC15W408AS單片機自帶的AD轉換中遇到的問題,虛心求教

[復制鏈接]
ID:601478 發表于 2019-10-14 09:17 | 顯示全部樓層 |閱讀模式
說明:下面的程序是一個測溫程序,用的STC15W408AS自帶的AD轉換通道,P1.2 I/O口輸入被測變化電平,使用的NTC負溫度系數傳感器,現在遇到的問題是把程序燒錄進硬件,上電后在4段數碼管上顯示的轉換后的溫度值在人為加熱傳感器 的情況下數值只在上電后3到4秒內會發生變化,時間一長再怎么加熱數值也不會變了,傳感器溫度都7.80度了顯示的數值也是一開始的32度,沒變化,但是掉電后重新上電又有幾秒鐘可以正常顯示60多度的溫度值,之后又卡在那里怎樣加溫降溫顯示值也不變,感覺就是只有硬件上電初時的幾秒會工作,之后就莫名卡死跑飛,很是奇怪,程序自己看了好多遍感覺看不出什么問題,小弟剛接觸單片機,也不知道哪里寫的不對,求各路大佬好心指點一下,感激不盡

上程序:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int


typedef unsigned char BYTE;
typedef unsigned int WORD;

......
......
#define ADC_POWER 0x80
#define ADC_FLAG 0x10
#define ADC_START 0x08
#define ADC_SPEED 0x00

sbit STB = P3^3;
sbit CLK = P3^6;
sbit DIO = P3^7;
sbit KEY = P1^5;


uchar code zhuzhi[101] ={65,62, 59,...........3,2,1};//溫度對應的阻值表

void delay(uchar a)  // 延時
{
        uchar x;
        while(a--)
        {
                x = 200;
                while(x--);
        }
}


void init_ADC()  //初始化AD
{
        P1ASF = 0x06;
  delay(20);
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = ADC_POWER | ADC_SPEED;
}


WORD res_ADC(BYTE ch) //啟動轉換
{
        uint num;
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = ADC_POWER | ADC_SPEED | ADC_START | ch;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        while(!(ADC_CONTR & ADC_FLAG));
        ADC_CONTR &= ~ADC_FLAG;
        num = (ADC_RES<<2)|ADC_RESL;
        return num;
}


float are()  // 多次取值后求平均,再用公式轉成電阻值
{
        uchar i,u;
        uint a,b;
        float n;
        u = ch();
        for(i = 0;i<31;i++)
        {
                a = res_ADC(u);
                b += a;
        }
        b = b/31;
        n = b*0.1/(5.5-0.005*b);
        
        return n;
}

float are2()  //濾波
{
        uchar i;
        float l,k;
        for(i = 0;i<30;i++)
        {
                l = are();
                k += l;
        }
        k = k/30;
        return k;
}


void ADC_biao()  //查表找對應的溫度數值
{
        float r;
        uchar high,low,mid;
        low = 0;
        high = 100;
        mid = (low + high)/2;
        r = are2();
        if((zhuzhi[high]<=r) && (r<=zhuzhi[low]))
        {
                while((high - low) != 1)
                {
                        if(r<zhuzhi[mid])
                        {
                                low = mid+1;
                                mid = (low + high)/2;
                        }
                        else if(zhuzhi[mid]<r)
                        {
                                high = mid-1;
                                mid = (low+high)/2;
                        }
                        else
                        {
                                display(mid);
                        }
                }
                if((zhuzhi[low] - r) < (r - zhuzhi[high]))
                {
                        display(low);
                }
                else if((r - zhuzhi[high]) < (zhuzhi[low] - r))
                {
                        display(high);
                }
                else
                {
                        display(high);
                }
        }
        else
        {
                if(r<zhuzhi[high])
                {
                        display(high);
                }
                if(zhuzhi[low]<r)
                {
                        display(low);
                }
        }
}

void main()  //主循環
{
        P1M1 = 0;
        P1M0 = 0;
        KEY = 1;
        init_ADC();
        while(1)
        {
                ADC_biao();
                delay(25);
        }
}


回復

使用道具 舉報

ID:213173 發表于 2019-10-14 11:11 | 顯示全部樓層
你確認這個程序能通過編譯?硬件電路是什么樣的?
回復

使用道具 舉報

ID:601478 發表于 2019-10-14 13:30 | 顯示全部樓層
wulin 發表于 2019-10-14 11:11
你確認這個程序能通過編譯?硬件電路是什么樣的?

能通過編譯,硬件電路用的開發板,具體我也不太懂
回復

使用道具 舉報

ID:213173 發表于 2019-10-14 15:24 | 顯示全部樓層
PDDDF 發表于 2019-10-14 13:30
能通過編譯,硬件電路用的開發板,具體我也不太懂

我可以負責任的對你說,你發的這個程序根本就不完整,不可能通過編譯。使用STC15W408AS芯片可以用51頭文件,但必須聲明51頭文件中不包含的特殊寄存器的地址。如:
sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
sfr ADC_RES     =   0xBD;           //ADC高8位結果
sfr ADC_LOW2    =   0xBE;           //ADC低2位結果
sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器
sfr P1M0        =   0x92;   /端口1模式寄存器0
sfr P1M1        =   0x91;   /端口1模式寄存器1
ADC轉換結果是12位,你的溫度對應的阻值表是8位數組,并且數組成員不完整。
你的數碼管顯示函數在哪里?
P1M1 = 0;P1M0 = 0;表示P1口全部是弱上拉準雙向口,應該把ADC輸入設為高阻口,如果是用P1.0口作ADC輸入應設為P1M1 = 0x01;P1M0 = 0x00;
設置P1的第0通道端口作為模擬輸入P1ASF=0x01;

回復

使用道具 舉報

ID:47286 發表于 2019-10-14 20:46 | 顯示全部樓層
用P1M0和P1M1把P1.2端口置成高阻狀態

然后 在AD的采集端 用萬用表測量電壓 如果電壓持續隨溫度變化則檢查端口配置和程序 否則檢查硬件
回復

使用道具 舉報

ID:401564 發表于 2019-10-15 11:58 | 顯示全部樓層
我用的時匯編的,看不明白你這明白
但編程的原理是一樣的,你一下子搞那么多代碼放這,哪里出了問題都可能找不到
你可以先寫一個單獨的ADC程序,也不用查表顯示什么的,不用濾波處理
簡單的:一直進行ADC再把結果輸出到一個帶LED的端口就可以了,要保證用手摸一下NTC,端口的LED就跟著變化就可以,用來驗證ADC代碼是否正確,其它功能也是這樣一步一步的來就可以了
匯編的思維就是這樣的,保證一個一個小功能正確了再去搞別的功能
順便說一下,取平均值那一段,盡可能的用整形,不要用浮點型,能用位移就不要用除法運算,在C上面它是可以正確計算的,但編譯器編譯之后就不一定是正確的算法了,你可以對比一下官方的手冊,它取平均值也是用位移的方法來計算的
回復

使用道具 舉報

ID:601478 發表于 2019-10-16 09:47 | 顯示全部樓層
Y_G_G 發表于 2019-10-15 11:58
我用的時匯編的,看不明白你這明白
但編程的原理是一樣的,你一下子搞那么多代碼放這,哪里出了問題都可能找 ...

我現在就是試著實現這塊芯片的AD轉換功能,程序的思路就是簡單的一直循環檢測輸入電平和顯示溫度值,取平均值那里我也換成整形變量了,移位求商這個真的頭一次知道,現在細節還在弄,謝謝大佬的回復
回復

使用道具 舉報

ID:601478 發表于 2019-10-16 10:13 | 顯示全部樓層
wulin 發表于 2019-10-14 15:24
我可以負責任的對你說,你發的這個程序根本就不完整,不可能通過編譯。使用STC15W408AS芯片可以用51頭文 ...

來了個大佬666
是這樣的程序的確不是完整的,我上面只發了有關AD轉換的部分,數碼管顯示部分我想著關系不大就省略沒發出來,那個阻值表是我用的NTC熱敏電阻的溫度—阻值對應表,1到100度對應的阻值,是問廠家那里拿的;p1口的狀態我改了高阻態但是還是不行;還有測溫的電路圖我不太會分析,AD轉換得到的Vout和Rt熱敏間的關系怎樣求,能麻煩大佬幫忙看下嗎,謝謝大佬回復
完整程序:
#include<reg51.h>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int

typedef unsigned char BYTE;
typedef unsigned int WORD;


#define FOSC    11059200L

sfr P1M1 = 0x91;
sfr P1M0 = 0x92;

sfr ADC_CONTR = 0xBC;
sfr ADC_RES = 0xBD;
sfr ADC_RESL = 0xBE;
sfr P1ASF = 0x9D;
sfr CLK_DIV = 0x97;

sbit STB = P3^3;
sbit CLK = P3^6;
sbit DIO = P3^7;
sbit KEY = P1^5;

#define ADC_POWER   0x80
#define ADC_FLAG    0x10
#define ADC_START   0x08
#define ADC_SPEED   0x60

WORD num;
float n;
uchar u = 1;

void display(uchar K);
void delay(WORD n);
uchar code Duanma[10]={0xfa,0x82,0xb9,0xab,0xc3,0x6b,0x7b,0xa2,0xfb,0xe3};
uchar code zhuzhi[101]={65.83,62.54,59.43,56.49,53.72,51.10,48.62,46.28,
                              44.06,41.96,39.97,38.09,36.31,34.63,33.03,31.51,
                              30.07,28.71,27.41,26.18,25.02,23.91,22.86,21.86,
                              20.90,20.00,19.14,18.32,17.54,16.80,16.10,15.42,
                              14.78,14.17,13.59,13.04,12.51,12.00,11.52,11.06,
                              10.62,10.20,9.80,9.42,9.05,8.70,8.37,8.05,7.74,
                              7.45,7.17,6.90,6.65,6.40,6.17,5.94,5.73,5.52,5.32,5.13,
                        4.95,4.77,4.61,4.45,4.29,4.14,4.00,3.86,3.73,3.61,
                        3.48,3.37,3.25,3.15,3.04,2.94,2.85,2.75,2.67,2.58,
                        2.50,2.42,2.34,2.27,2.20,2.13,2.06,2.00,1.94,1.88,
                        1.82,1.77,1.71,1.66,1.61,1.56,1.52,1.47,1.43,1.39,
                        1.35};

void send_8bit(uchar dat)
{
        uchar i;
        for(i=0;i<8;i++)
        {
                if(dat&0x01)
                {
                        DIO = 1;
                }
                else
                {
                        DIO = 0;
                }
               
                CLK = 0;
                CLK = 1;
               
                dat=dat>>1;
        }
}

void command(uchar com)
{
        STB = 1;
        STB = 0;
        send_8bit(com);
}

void display(uchar K)
{
         uchar ge,shi,bai;
   ge = K%10;
         shi = (K/10)%10;
         bai = (K/100)%10;
       
         command(0x03);
         command(0x40);
         command(0xc6);
       
        send_8bit(Duanma[bai]);              
        send_8bit(0x00);

        send_8bit(0x00);            
        send_8bit(0x00);

  send_8bit(Duanma[shi]);
        send_8bit(0x00);

        send_8bit(Duanma[ge]);
        send_8bit(0x00);

        command(0x8f);
        STB = 1;
}

void init_ADC()
{
        P1ASF = 0x06;
        delay(2);
        ADC_RES = 0;
        ADC_RESL = 0;
}

void resetADC(BYTE ch)
{
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = ADC_SPEED | ADC_START | ADC_POWER | ch;
}

void delay(WORD n)
{
        uint x;
        while(n--)
        {
                x = 500;
                while(x--);
        }
}

void get_result()
{
  while (!(ADC_CONTR & ADC_FLAG));
        ADC_CONTR &= ~ADC_FLAG;
  num = (ADC_RES<<2)|ADC_RESL;
}

WORD lvbo()
{
        WORD count;
        uchar i = 0;
        for(i = 0;i<32;i++)
        {
          resetADC(u);
    delay(2);
          get_result();
                count += num;
        }
        count = count>>5;
        return count;
}

void chselect()
{
        if(KEY == 0)
        {
                delay(5);
                if(KEY == 0)
                {
                        while(KEY == 0);
      if(2<++u) u = 1;
                }
        }
}

void data_change()
{
        WORD i;
        i = lvbo();
  n = i/(55-0.05*i);
}

void cha_biao()
{
        uint low,high,middle;
        low = 0;
        high = 100;
        middle = (high + low)/2;
        if((n<=zhuzhi[low])&&(zhuzhi[high]<=n))
        {
           while((high - low) != 1)
           {
                   if(n < zhuzhi[middle])
                   {
                           low = middle+1;
                                 middle = (high + low)/2;
                         }
                         else if(zhuzhi[middle] < n)
                   {
                                 high = middle-1;
                                 middle = (high + low)/2;
                   }
                         else
                         {
                                 if(n == zhuzhi[middle])
                                 {
                                         display(middle);
                                         return;
                                 }
                         }
                 }
                 if((zhuzhi[low]-n)<(n-zhuzhi[high]))
                 {
                         display(low);
                         return;
                 }
                 if((n-zhuzhi[high])<(zhuzhi[low]-n))
                 {
                         display(high);
                         return;
                 }
         }
        else
        {
                if(n<zhuzhi[high])
                {
                        display(high);
                        return;
                }
                if(zhuzhi[low]<n)
                {
                        display(low);
                        return;
                }
        }
}

void main()
{
        P1M1 = 0x06;
        P1M0 = 0x00;
        KEY = 1;
       
        init_ADC();
        while(1)
        {
                chselect();
    lvbo();
                resetADC(u);
    delay(2);
          get_result();
                data_change();
                cha_biao();
                delay(6);
        }
}C:\Users\Administrator\Desktop\01
回復

使用道具 舉報

ID:601478 發表于 2019-10-16 10:19 | 顯示全部樓層
dzbj 發表于 2019-10-14 20:46
用P1M0和P1M1把P1.2端口置成高阻狀態

然后 在AD的采集端 用萬用表測量電壓 如果電壓持續隨溫度變化則檢 ...

硬件應該不會有問題吧,開發板買了才不到兩個月,我還是懷疑自己的程序問題(其實在考慮要不要買個萬用表),但是又看不出是哪里出錯,哎,難搞
回復

使用道具 舉報

ID:213173 發表于 2019-10-16 13:13 | 顯示全部樓層
PDDDF 發表于 2019-10-16 10:13
來了個大佬666
是這樣的程序的確不是完整的,我上面只發了有關AD轉換的部分,數碼管顯示部分我想 ...

軟件都是基于硬件條件編寫的,把你的開發板原理圖或實物照片發上來,幫你改程序。NTC熱敏電阻的溫阻表不可以直接使用,要根據分壓電阻值計算出溫度電壓關系制作數組表格。不要追求一步完成完美的代碼,應該循序漸進,先完成基本的AD轉換,逐漸學習濾波、換算等功能。
回復

使用道具 舉報

ID:10947 發表于 2019-10-16 14:27 | 顯示全部樓層
最簡單的,你得保證P1.2腳的電壓是對的,在顯示不正常的時候,有測量過P1.2的電壓嗎
回復

使用道具 舉報

ID:601478 發表于 2019-10-19 13:48 | 顯示全部樓層
wulin 發表于 2019-10-16 13:13
軟件都是基于硬件條件編寫的,把你的開發板原理圖或實物照片發上來,幫你改程序。NTC熱敏電阻的溫阻表不 ...

方便加個QQ交流學習一下嗎,我上個回復的圖片發不出來,可以的話QQ截圖比較快
回復

使用道具 舉報

ID:601478 發表于 2019-10-19 13:56 | 顯示全部樓層
lfc315 發表于 2019-10-16 14:27
最簡單的,你得保證P1.2腳的電壓是對的,在顯示不正常的時候,有測量過P1.2的電壓嗎

萬用表剛到手,我測測看
回復

使用道具 舉報

ID:491577 發表于 2019-10-20 00:58 | 顯示全部樓層
WORD res_ADC(BYTE ch) //啟動轉換
{
        uint num;
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = ADC_POWER | ADC_SPEED | ADC_START | ch;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        while(!(ADC_CONTR & ADC_FLAG));
        ADC_CONTR &= ~ADC_FLAG;
        num = (ADC_RES<<2)|ADC_RESL;
        return num;
}
這個函數中:num = (ADC_RES<<2)|ADC_RESL;這個不對,數據溢出了。改成:num = ((uint)ADC_RES<<2)|ADC_RESL;或者num = (uint)ADC_RES*4+ADC_RESL;
回復

使用道具 舉報

ID:601478 發表于 2019-10-21 14:30 | 顯示全部樓層
hhh402 發表于 2019-10-20 00:58
WORD res_ADC(BYTE ch) //啟動轉換
{
        uint num;

是數據溢出,不過不是這里,是另外的濾波函數,謝謝你給我的提示,問題解決了
回復

使用道具 舉報

ID:601478 發表于 2019-10-21 14:32 | 顯示全部樓層
原因找到了,濾波時數據溢出,換了變量類型就沒事了,謝謝樓上幾位老哥的回復,先結貼了
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久精品一区二区三区四区 | 亚洲精品久久久久久宅男 | 国产精品久久久久久久久 | 精品视频国产 | 精品不卡 | 日韩精品一区二区三区视频播放 | 国产区一区二区三区 | 久久久av | 91久久北条麻妃一区二区三区 | 欧美中文字幕一区二区三区亚洲 | 国产高清久久久 | 欧美黄色小视频 | 视频一区二区在线观看 | 黄色片网站在线观看 | 综合色婷婷 | 免费看色| 国产精品小视频在线观看 | www.日韩免费 | 久久精品亚洲精品国产欧美 | 亚洲国产一区二区三区在线观看 | 国精日本亚洲欧州国产中文久久 | 国产日韩欧美 | 欧美福利视频 | 国产精品久久片 | 日韩免费成人av | av日韩一区| 精品国产91久久久久久 | 久草新在线 | 亚洲日韩中文字幕一区 | 美日韩中文字幕 | 狠狠做深爱婷婷综合一区 | 在线免费观看a级片 | 特级做a爰片毛片免费看108 | 精品欧美一区二区在线观看 | 大象一区| 性一交一乱一透一a级 | 第一福利社区1024 | 精品91久久久 | 91tv在线观看 | 91免费观看 | 亚洲欧洲成人 |