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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索

stc12c5a60s2單片機內部AD功能為什么電壓無法讀取?

查看數: 3590 | 評論數: 20 | 收藏 1
關燈 | 提示:支持鍵盤翻頁<-左 右->
    組圖打開中,請稍候......
發布時間: 2019-11-4 00:08

正文摘要:

stc12c5a60s2 為什么我這個電壓無法讀取 請大師看看呢    我是直接用的單片機5V供電的 #include <STC12C5A60S2.H> #include "intrins.h" //typedef unsigned char BYTE; //typedef unsigned ...

回復

ID:600631 發表于 2020-1-29 09:47
wulin 發表于 2019-11-7 10:57
給你把程序改好了,有詳細注釋。

師傅,這個程序,如果再增加一路測試電壓的話,程序應該怎么寫呢
ID:254747 發表于 2019-11-9 13:05
wulin 發表于 2019-11-7 10:57
給你把程序改好了,有詳細注釋。

非常感謝 我下載了 我需要好好去學習哈
ID:213173 發表于 2019-11-7 10:57
不將就123 發表于 2019-11-6 22:07
可以了 大哥   哎呀 我知道為什么我的高阻模式不管用了  是應為我在開發板上面弄的  這個上面有上拉電阻  ...

給你把程序改好了,有詳細注釋。
電壓表.zip (18.9 KB, 下載次數: 32)



ID:254747 發表于 2019-11-6 22:09
感謝論壇的各位朋友  問題現在已經解決了  是開發板上面的 上拉電阻導致的誤差  將I0口拿出來測試 問題得到完美的解決了      
temp=(ADC_jiancedaozuidivoltage*AD_jie_guo);
temp=(temp*6)/100;   //這里為什么要/100     這個是我參考網上大師做的     
                        
ID:254747 發表于 2019-11-6 11:11

大哥  我重新發了一次   您在給我看看
ID:254747 發表于 2019-11-6 11:10
#include <STC12C5A60S2.H>
#include "intrins.h"

//typedef unsigned char BYTE;
//typedef unsigned int WORD;

#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long
/*Define ADC operation const for ADC_CONTR*/
#define ADC_POWER   0x80            //ADC 電源控制位  10000000  0X80  /
#define ADC_FLAG    0x10            //ADC 完成標志          00010000  0x10
#define ADC_START   0x08            //ADC 啟動ADC開關 00001000        0x08  /
#define ADC_SPEEDLL 0x00            //420 轉換速度          00000000        0x00  /
#define ADC_SPEEDL  0x20            //280 轉換速度          00100000  0x20
#define ADC_SPEEDH  0x40            //140 轉換速度          01000000  0x40
#define ADC_SPEEDHH 0x60            //70  轉換速度          01100000        0x60

//float  temp;    //定義temp為浮點型參數
/*----------------------------------------------------------------------------------------------
meidangzuidivoltage:表示AD最高電壓5V對應10bit_AD轉換的最小電壓是多少 5/1024= 0.00488V 也就是AD在
//10bit下測量的最小電壓,
//那么在計算AD電壓值的時候將公式 “GetADCResult(ch)*5/1024”分兩步進行 方便后面對數據分離顯示到
//1602上面  先計算ADC_jiancedaozuidivoltage=5*10000000/1024  先將這個數放大100萬倍
//最后在算AD_jie_guo=(ADC_jiancedaozuidivoltage*GetADCResult(ch);
----------------------------------------------------------------------------------------------*/
ulong  ADC_jiancedaozuidivoltage,AD_jie_guo,temp;

uint num,i,vlue;//ADC_mV,ADC_RESX,VCC_V=5.2;

sbit    lcden = P2^7;
sbit    rs = P2^6;
sbit    rw = P2^5;
sbit    LED = P3^0;

void Delay(uint n);              //延時函數
uint GetADCResult(uchar ch);                 // ad轉換函數
void InitADC();                                         //ad初始化函數
//ulong  count(uchar ch);                     //ad計算函數
uchar code table[20]= {"     Shu Kong QuDong"};
uchar code table2[20]={"     CQDZ Alan V1.01"};
float count(uchar ch);
/*  延時函數*/
void delayms(uint xms)
{                                       
     uint i,j;                                         
         for(i=xms;i>0;i--)
           for (j=960;j>0;j--);
}
/******寫命令****/
void   lcd_write_com(uchar com)
{

         rw=0;
                 rs=0;        //寫命令狀態
                 P0=com;
                 lcden=1;
             delayms(5);
                 lcden=0;
}
/**寫數據 ***/
void  write_date_(uchar date)
{
         rw=0; //寫數據
                 rs=1; //寫數據狀態
                 P0=date;
                 delayms(5);
                 lcden=1;  //使能
             delayms(5);
                 lcden=0;   
}
/*初始化顯示屏*/
void lcd_init(void)
{

                  lcden=0;
                  lcd_write_com(0x38); //設置8位格式,2行,5*7
                  lcd_write_com(0x0c); //整體顯示,關光標,不顯示
                  lcd_write_com(0x06); // 設定輸入方式,增量不移位
                  lcd_write_com(0x01);//清屏幕
                  delayms(5);  //延?


}

/*-----------------------
函數名稱    格式定義
函數的介紹  在某個屏幕位置上顯示一個字符,X(0-16),y(1-2)
X:表示字的格式 一共16個  Y:表示行 一共2行
-------------------------*/
//格式定義

void lcd_disp_char(uchar y,uchar x, uint dat)
{
         uint  address;
             if(y==1)                   //y為1  在第一行
                   address=0x80+0x10+4+x;          //整屏左移動以后 從新定義新的起始位置 但是要加上之前移動后的地址
             else
               address=0xc0+0x10+x;           //y為2 在第二行  X顯示字的位置   0XC0是 0x80+0x40的結果

           lcd_write_com(address);          //寫入要寫的位置
                   write_date_( dat);       //寫入你要寫的數據         
}        


/*顯示函數2*********/
void  disp()
{
         temp=(ADC_jiancedaozuidivoltage*AD_jie_guo);
         temp=(temp*6)/100;            //擴大電壓   我的量程是0-30V  分壓電阻是 10k 2k 電阻比的5  反推 當測試電壓為5v
                            //的時候 最高電壓為25V 測量后調試  

        //0x30是顯示數字 0-9 30表示第一個數0  int是將count轉換為整數
        lcd_disp_char(1,0, temp%10000000/1000000+0x30 );   //十位
        lcd_disp_char(1,1, temp%1000000/100000+0x30);   //個位       
        lcd_disp_char(1,2,'.' );                                 // 小數點
        lcd_disp_char(1,3, temp%100000/10000+0x30 ); //個分位
        lcd_disp_char(1,4, temp%10000/1000+0x30 ); //百分位
        lcd_disp_char(1,5,'V' );
}
                                          //count(0)
/*-----------------------------------                  
功能 開機的時候顯示一下銘牌
for來完成 屏幕左移動
----------------------------------*/
void init()

{       



//        lcd_write_com(0x80+0x10);  //定義顯示的位置 起始地址       
        lcd_write_com(0x80);           //定義顯示的位置 起始地址

        for(num=0;num<20;num++)
         {       
               
                        write_date_(table[num]);               //初始化屏幕的初始數字“0000”
                        delayms(5);                         
     }
                 
//        lcd_write_com(0x80+0x40+0x10);   //定義第二排,顯示的地址 0x80是顯示屏寄存器第一排起始地址
        lcd_write_com(0xc0);                  //定義顯示的位置 起始地址
    for(num=0;num<20;num++)                         //0x40是第二排起始地址
      {
                   write_date_(table2[num]);
                   delayms(5);                  
          }

          for(num=0;num<20;num++)        //整屏左移動 這里的21就是指可以移動多少格  可以是100可以是1000 相當于是電子屏幕一樣
          {
              lcd_write_com(0x18);        //0x18是整屏左移 指令
                  delayms(50);
          }       
          

}



void main()

{       

       
    lcd_init();
        init();
    InitADC();                      //Init ADC sfr

        ADC_jiancedaozuidivoltage=49700000/1024;  //5V參考電壓,計算分度值的時候,數值過小會出現很大偏差
                                                          //所以放大1000萬倍 這樣精度會高一些

    while (1)
    {
          /*
          if(temp > 3)
                   {
                  LED = 0;
                                                 //  調試的時候用的   通過判斷temp來判斷是否過壓 如果過壓就啟動保護  
                 }
           if(temp < 3)
                   {
                  LED = 1;
                 
                 }*/

           AD_jie_guo = count(0);   //經過上面的計算求出來100次的平均值存放在AD_jie_guo里面
       disp();
          
    }
}

/*************************
*  功能        ADC轉換函數
*  帶結果返回  帶結果返回
**************************/

uint GetADCResult(uchar ch)  //參數的定義“ch”初始化就是為0  所以這里的“ch”應該是用來設置用哪個端口     
{                                                   //來設置AD的 這個“ADC_POWER|ADC_SPEEDLL|ch|ADC_START”;或出來的結果是
                          //10001000   后面三個0對應的是 CHS2 CHS1 CHS0 查表格 剛好是P1.0口
                                             //作為AD模擬輸入的。如果要改變端口就要給ch賦值 假如要P1.2 就需要賦值為ch=0x02;
        ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ch|ADC_START;    //配置相關項目打開  
        _nop_();
        _nop_();
        _nop_();                                            //4個機器時間的延時 以保障轉換完成
        _nop_();       
        while(!(ADC_CONTR&ADC_FLAG));   //判斷是否轉換完成
        ADC_CONTR &= ~ADC_FLAG;                //關閉ADC
    vlue = (ADC_RES*4+ADC_RESL);            //返回結果10bit  也就是電壓值
        Delay(2);                                                  //延時一下不然電壓的后2位變化的太快
        return vlue;

}
/******************************
*  功能:計算1結果函數 將10bit的結果計算為對應電壓值MV
*  函數類型    float 型  浮點型
*  帶結果返回  帶結果返回
******************************/
/*
ulong count(uchar ch)
{      
        ADC_RESX=GetADCResult(ch);
        ADC_mV=(VCC_V*(long)ADC_RESX*10000/1024+5)/10;//強制轉換長整型運算,得到結果mV(4舍5入)
        return ADC_mV;
}*/




/******************************
*  功能:計算2結果函數 將10bit的結果計算為對應電壓值MV
*  函數類型    float 型  浮點型
*  帶結果返回  帶結果返回
******************************/

float count(uchar ch)
{
    float AD_val;     //定義處理后的數值AD_val為浮點數
        uchar n;
        for(n=0;n<100;n++)
        AD_val+=GetADCResult(ch); //轉換100次求平均值(提高精度)
        AD_val/=100;                          //意思是GetADCResult(ch)經過了100次轉換后的值保存到了AD_val里面 然后在
                                  //除以100 就是求平均值 這樣的精度高一點
//        AD_val=(AD_val*5)/1024; //AD的參考電壓是單片機上的5v,所以乘5即為實際電壓值,應為分段計算這個就
                            //暫時不用  如果測量0-5v就可以這樣計算
        return AD_val;






  // temp = (float)GetADCResult(ch)*5/1024;  //5表示單片機的供電 這個公式在手冊上可以看到

   //temp = (float) temp*5;

  // return  temp;       
                        //這里的temp值就是最終的電壓值MV 轉換成V就在乘以1000
}                                                                          //在顯示屏函Dispy數里面已經做了倍率乘法









/*----------------------------
功能   ADC初始化函數
----------------------------*/
void InitADC()                                //adc初始化函數
{         
    P1M1=0x01;       //設置P1.0高阻模式                  
    P1M0=0x00;       //設置P1.0高阻模式
       
    P1ASF = 0x01;                   //開放P1.0通道ADC功能  就是8個I/O口全部開放
    ADC_RES = 0;                    //清除之前的結果
        ADC_RESL = 0;
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;   //打開AD電壓  轉換速度540
    Delay(2);                       //ADC 延時一下
}


/*----------------------------
Software delay function
----------------------------*/
void Delay(uint n)
{
   uint x;

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




ID:254747 發表于 2019-11-6 11:10
我發了  但是沒有顯示出來 我重新給您發一下
ID:213173 發表于 2019-11-6 06:57
不將就123 發表于 2019-11-5 22:34
大哥呀  我被這個東西折磨壞了    我設置了高阻態模式  同時 也設置了 P1ASF = 0x01;   
但是現在出現的 ...

代碼在哪?
ID:254747 發表于 2019-11-5 22:34
wulin 發表于 2019-11-5 12:45
STC12C5A60S2單片機的P1上電默認高電平為準雙向口,用作ADC輸入的端口必須設置為高阻模式,否則端口 ...
  1. <blockquote>#include <STC12C5A60S2.H>
復制代碼
大哥呀  我被這個東西折磨壞了    我設置了高阻態模式  同時 也設置了 P1ASF = 0x01;   
但是現在出現的問題是   測量誤差相當的大  
我測量的是30V的電壓   通過  10k 2k 分壓后為5v  然后比例是6   結果當被測電壓為3.0V的時候   單片機測量出來的就是6.78V  麻煩大哥看一下  是哪里出問題了  給我指導一下  非常感謝!!!

代碼有些亂   費心了
ID:213173 發表于 2019-11-5 12:45
不將就123 發表于 2019-11-4 20:52
可以說一下為什么嗎?   謝謝你 大師    我現在要測量0-30V的電壓    然后電阻分壓是 10k  2k     5/30=0 ...

    STC12C5A60S2單片機的P1上電默認高電平為準雙向口,用作ADC輸入的端口必須設置為高阻模式,否則端口內部上拉電阻會影響測量精度,其它口保持準雙向口模式可以另作它用。設置P1ASF寄存器的目的是開通MCU內部ADC模擬輸入通道。其它口保持TTL模式可以另作它用。
    ADC測量范圍0~VCC,被測電壓高于VCC需要通過分壓電阻降到VCC以內,測量結果按降壓比例放大還原。如果分壓是電阻是 10K和2K,取樣電壓是實際電壓的1/6,等測量結果換算成電壓后*6就是實際電壓值。
ID:254747 發表于 2019-11-4 20:53
hhh402 發表于 2019-11-4 10:34
主函數沒有調用到:uchar GetADCResult(uchar ch),
return (ADC_RES*4+ADC_RESL);//會發生數據溢出錯誤
...

謝謝師傅
ID:254747 發表于 2019-11-4 20:52
wulin 發表于 2019-11-4 16:49
只一個P1.0口用作ADC
P1ASF = 0x01;//設置P1.0做模擬輸入
P1M1=0x01;//設置P1.0高阻模式

可以說一下為什么嗎?   謝謝你 大師    我現在要測量0-30V的電壓    然后電阻分壓是 10k  2k     5/30=0.167比率   然后我 用temp=temp/0.167   以后測量不出來啦    是不是我分離有問題
ID:213173 發表于 2019-11-4 16:49
不將就123 發表于 2019-11-4 16:08
這是為什么啊  我只用一個p1.0口

只一個P1.0口用作ADC
P1ASF = 0x01;//設置P1.0做模擬輸入
P1M1=0x01;//設置P1.0高阻模式
P1M0=0x00;//設置P1.0高阻模式
ID:254747 發表于 2019-11-4 16:08
wulin 發表于 2019-11-4 11:34
還要把P1端口設置為高阻模式。
P1M1=0xff;
P1M0=0x00;

這是為什么啊  我只用一個p1.0口
ID:213173 發表于 2019-11-4 11:34
還要把P1端口設置為高阻模式。
P1M1=0xff;
P1M0=0x00;
ID:254747 發表于 2019-11-4 11:06
wulin 發表于 2019-11-4 06:58
//函數類型unsigned int
uint GetADCResult(uchar ch)
{

可以了 可以了  我沒有給VCC_V賦值
ID:254747 發表于 2019-11-4 10:48
wulin 發表于 2019-11-4 06:58
//函數類型unsigned int
uint GetADCResult(uchar ch)
{

用了你這段還是不可以啊
ID:491577 發表于 2019-11-4 10:34
主函數沒有調用到:uchar GetADCResult(uchar ch),
return (ADC_RES*4+ADC_RESL);//會發生數據溢出錯誤
改成:return ((uint)ADC_RES*4+ADC_RESL);
ID:213173 發表于 2019-11-4 06:58
//函數類型unsigned int
uint GetADCResult(uchar ch)
{
        ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ch|ADC_START;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        while(!(ADC_CONTR&ADC_FLAG));
        ADC_CONTR&=~ADC_FLAG;   
        return (ADC_RES*4+ADC_RESL);//返回10位結果
}
//函數類型unsigned int
uint count(uchar ch)
{      
        ADC_RESX=GetADCResult(ch);
        ADC_mV=(VCC_V*(long)ADC_RESX*10000/1024+5)/10;//強制轉換長整型運算,得到結果mV(4舍5入)
        return ADC_mV;
}

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人免费淫片aa视频免费 | 亚洲成人毛片 | 自拍偷拍第一页 | 亚洲高清在线 | 国产一区2区 | 国产精品高清一区二区 | 久久久久久99 | www.中文字幕av | 在线一区二区三区 | 国产亚洲精品精品国产亚洲综合 | 久久出精品 | 久视频在线观看 | 日本精品一区二区三区在线观看 | 亚洲 一区| 成人免费小视频 | 天堂网avav | 精品久久久久久久久久久院品网 | 91在线成人| 久久久精品久久 | 五月综合激情在线 | 成人免费毛片在线观看 | 亚洲高清视频在线观看 | 色一级 | 一区二区精品 | 欧美日韩高清在线一区 | 日本一区视频在线观看 | 日本免费在线 | 国产黄色在线 | 成人在线视频一区 | 国产成人精品网站 | 亚洲免费视频一区 | 欧美国产一区二区三区 | av 一区二区三区 | 黄色片免费看 | 亚洲成人一区 | 最近中文字幕免费 | 午夜视频一区 | www.一区二区三区 | 久久亚洲一区二区三区四区 | www.一区二区三区 | 欧美精品二区 |