![]() |
發(fā)布時間: 2016-10-20 15:32
正文摘要:開源基于STC單片機內(nèi)部基準(Bandgap voltage reference)mini電壓表—極簡設(shè)計創(chuàng)新制作 1.hello-壇友們大家好!今天開源制作一款9.99v量程的電壓表(改變一下電阻和程序可以改為更大量程),只需要單片機數(shù)碼管電 ... |
@樓主,過來幫忙看一下,為什么我用的共陽極的,改了程序還是沒有顯示: 一、原理圖: 二、STC15ADC.c /********************************************/ //2016.10.20日 1:01編寫完成 //作者:劉海龍 (讀單片機內(nèi)部BandGap基準電壓值參考的STC官網(wǎng)程序) //硬件:STC15W408AS+3位共陰數(shù)碼管+2個10K的電阻(1/4w) //晶振無說明的情況選12M //測量口P1.3 #include <STC15W.h> #include <intrins.h> #include<4LED_YIN.H>//數(shù)碼管驅(qū)動顯示程序 #include <BandGap.H>//包含讀單片機內(nèi)部BandGap基準電壓值 /********************************/ void main (void) { Delay20ms();//待系統(tǒng)穩(wěn)定 InitADC();//初始化ADC P1M1=0X08;//P1.3高阻輸入 init();//IO口設(shè)置初始化 while (1) { ShowResult(3);//顯示通道P1.3的測量值、單位為毫伏 disp(); //數(shù)碼管顯示電壓值 } } 三、4LED_YIN.H /***********四位共陰數(shù)碼管驅(qū)動程序************/ //stc15w單片機 //1在主程序前加上初始化init();程序 //2硬件連接變動時需修改下面的參數(shù) sbit H1 = P1^0;//設(shè)置第1位數(shù)碼管陽極連接的I/O口 sbit H2 = P1^1;//設(shè)置第2位數(shù)碼管陽極連接的I/O口 sbit H3 = P1^2;//設(shè)置第3位數(shù)碼管陽極連接的I/O口 //sbit H4 = P1^7;//設(shè)置第4位數(shù)碼管陽極連接的I/O口 sbit a = P3^7; sbit b = P3^6; sbit c = P3^5; sbit d = P3^4; sbit e = P3^3; sbit f = P3^2; sbit g = P3^1; sbit dp = P3^0; unsigned char PWM;//顯示亮度 unsigned int v;//定義測量電壓變量 #define P1M0SET 0x00 //設(shè)置I/O口工作方式//00000000(左到右,高到低位) #define P1M1SET 0x00 //設(shè)置I/O口工作方式//00000000 #define P3M0SET 0xFF //設(shè)置I/O口工作方式//11111111 #define P3M1SET 0x00 //設(shè)置I/O口工作方式//00000000 /*****以上定義需要根據(jù)實際硬件情況更改******/ #define light 9 //設(shè)置LED顯示的亮度(值域:1~9) #define DELAY_L 12 //設(shè)置每一個點顯示的時間長度(1~20) /********* 延時函數(shù) ***************/ void delay (unsigned int a){ // 用于點掃描的延時 unsigned int i; while( a-- != 0){ for(i = 0; i < DELAY_L; i++); } } /*********************************************************************************************/ unsigned char code disdata[]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09}; //顯示0~9的段碼 //數(shù)碼管:負向位置;共陽極;負向連接 void dis_off (void){ P3 = P3M0SET; //關(guān)所有顯示 P1 = ~P1M0SET; delay(10-PWM); } /*********************************************************************************************/ void displayHH1 (unsigned char q){ //第1位數(shù)碼管顯示程序 unsigned char i; i = q & 0x7F; if(i == 0x7F){ H1 = 0;a = 0;}delay(PWM);dis_off(); i = q & 0xBF; if(i == 0xBF){ H1 = 0;b = 0;}delay(PWM);dis_off(); i = q & 0xDF; if(i == 0xDF){ H1 = 0;c = 0;}delay(PWM);dis_off(); i = q & 0xEF; if(i == 0xEF){ H1 = 0;d = 0;}delay(PWM);dis_off(); i = q & 0xF7; if(i == 0xF7){ H1 = 0;e = 0;}delay(PWM);dis_off(); i = q & 0xFB; if(i == 0xFB){ H1 = 0;f = 0;}delay(PWM);dis_off(); i = q & 0xFD; if(i == 0xFD){ H1 = 0;g = 0;}delay(PWM);dis_off(); i = q & 0xFE; if(i == 0xFE){ H1 = 0;dp = 0;}delay(PWM);dis_off(); } /*********************************************************************************************/ void displayHH2 (unsigned char q){ //第2位數(shù)碼管顯示程序 unsigned char i; i = q & 0x7F; if(i == 0x7F){ H2 = 0;a = 0;}delay(PWM);dis_off(); i = q & 0xBF; if(i == 0xBF){ H2 = 0;b = 0;}delay(PWM);dis_off(); i = q & 0xDF; if(i == 0xDF){ H2 = 0;c = 0;}delay(PWM);dis_off(); i = q & 0xEF; if(i == 0xEF){ H2 = 0;d = 0;}delay(PWM);dis_off(); i = q & 0xF7; if(i == 0xF7){ H2 = 0;e = 0;}delay(PWM);dis_off(); i = q & 0xFB; if(i == 0xFB){ H2 = 0;f = 0;}delay(PWM);dis_off(); i = q & 0xFD; if(i == 0xFD){ H2 = 0;g = 0;}delay(PWM);dis_off(); i = q & 0xFE; if(i == 0xFE){ H2 = 0;dp = 0;}delay(PWM);dis_off(); } /*********************************************************************************************/ void displayHH3 (unsigned char q){ //第3位數(shù)碼管顯示程序 unsigned char i; i = q & 0x7F; if(i == 0x7F){ H3 = 0;a = 0;}delay(PWM);dis_off(); i = q & 0xBF; if(i == 0xBF){ H3 = 0;b = 0;}delay(PWM);dis_off(); i = q & 0xDF; if(i == 0xDF){ H3 = 0;c = 0;}delay(PWM);dis_off(); i = q & 0xEF; if(i == 0xEF){ H3 = 0;d = 0;}delay(PWM);dis_off(); i = q & 0xF7; if(i == 0xF7){ H3 = 0;e = 0;}delay(PWM);dis_off(); i = q & 0xFB; if(i == 0xFB){ H3 = 0;f = 0;}delay(PWM);dis_off(); i = q & 0xFD; if(i == 0xFD){ H3 = 0;g = 0;}delay(PWM);dis_off(); i = q & 0xFE; if(i == 0xFE){ H3 = 0;dp = 0;}delay(PWM);dis_off(); } void diplay_data (unsigned char l,unsigned char q){ switch (l){//顯示的數(shù)碼管位置 case 1:// displayHH1(q); //將顯示數(shù)據(jù)送入 break;// case 2:// displayHH2(q); //將顯示數(shù)據(jù)送入 break;// case 3:// displayHH3(q); //將顯示數(shù)據(jù)送入 break;// // case 4:// // displayHH4(q); //將顯示數(shù)據(jù)送入 // break;// } } /*****************IO口初始化**************************/ void init (void){ P3M1=P3M1SET; P3M0=P3M0SET; P1M0=P1M0SET; P1M1=P1M1SET; dis_off(); PWM = light;} /*******************************************/ /******************顯示程序*************************/ void disp(){ unsigned int i; for(i=0;i<50;i++){ diplay_data (1,disdata[v/1000]+0x80); diplay_data (2,disdata[v%1000/100]); diplay_data (3,disdata[v%100/10]); } } 四、BandGap.H //內(nèi)部BandGap為基準測電壓 //----------------------------------------- #define uchar unsigned char #define uint unsigned int unsigned int v; //ADC相關(guān)設(shè)定參數(shù) #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個時鐘 //----------------------------------------- //BandGap相關(guān)參數(shù) //注意:需要在下載代碼時選擇"在ID號前添加重要測試參數(shù)"選項,才可在程序中獲取此參數(shù) //#define ID_ADDR_ROM 0x03f7 //1K程序空間的MCU //#define ID_ADDR_ROM 0x07f7 //2K程序空間的MCU //#define ID_ADDR_ROM 0x0bf7 //3K程序空間的MCU //#define ID_ADDR_ROM 0x0ff7 //4K程序空間的MCU //#define ID_ADDR_ROM 0x13f7 //5K程序空間的MCU #define ID_ADDR_ROM 0x1ff7 //8K程序空間的MCU //#define ID_ADDR_ROM 0x27f7 //10K程序空間的MCU //#define ID_ADDR_ROM 0x2ff7 //12K程序空間的MCU //#define ID_ADDR_ROM 0x3ff7 //16K程序空間的MCU //#define ID_ADDR_ROM 0x4ff7 //20K程序空間的MCU //#define ID_ADDR_ROM 0x5ff7 //24K程序空間的MCU //#define ID_ADDR_ROM 0x6ff7 //28K程序空間的MCU //#define ID_ADDR_ROM 0x7ff7 //32K程序空間的MCU //#define ID_ADDR_ROM 0x9ff7 //40K程序空間的MCU //#define ID_ADDR_ROM 0xbff7 //48K程序空間的MCU //#define ID_ADDR_ROM 0xcff7 //52K程序空間的MCU //#define ID_ADDR_ROM 0xdff7 //56K程序空間的MCU //#define ID_ADDR_ROM 0xeff7 //60K程序空間的MCU //----------------------------------------- //聲明 void Delay20ms() //@12.000MHz { unsigned char i, j, k; _nop_(); _nop_(); i = 1; j = 234; k = 113; do { do { while (--k); } while (--j); } while (--i); } /*---------------------------- 初始化ADC ----------------------------*/ void InitADC() { P1ASF = 0x00; //不設(shè)置P1口為AD口 ADC_RES = 0; //清除結(jié)果寄存器 ADC_CONTR = ADC_POWER | ADC_SPEEDLL; Delay20ms(); } /*---------------------------- 讀取ADC結(jié)果 ----------------------------*/ uint GetADCResult(uchar ch) { uint ADC_10BIT_RES; ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START; _nop_(); //等待4個NOP _nop_(); _nop_(); _nop_(); while (!(ADC_CONTR & ADC_FLAG));//等待ADC轉(zhuǎn)換完成 ADC_CONTR &= ~ADC_FLAG; //關(guān)閉 ADC ADC_10BIT_RES=ADC_RES; //得到高8位 ADC_10BIT_RES<<=2; ADC_10BIT_RES+=ADC_RESL; //得到低2位 return ADC_10BIT_RES; //返回ADC結(jié)果 } /*---------------------------- 發(fā)送ADC結(jié)果 ----------------------------*/ void ShowResult(uchar ch) { uint adc_res10,//測量設(shè)定通道adc值 bandgap, //bandgap預(yù)儲存校準值,單位毫伏 adc_9gallery_res; //測量第九通道(bandgap)值 float power_voltage, //系統(tǒng)供電電壓,單位毫伏 ADC_voltage; //設(shè)定通道電壓值,單位毫伏 uchar code *cptr; //定義ROM(代碼)區(qū)指針 //uchar idata *iptr;//定義RAM(內(nèi)存)區(qū)指針 cptr = ID_ADDR_ROM; //從程序區(qū)讀取BandGap電壓值(單位:毫伏mV) bandgap=*cptr++; bandgap<<=8; bandgap+=*cptr; /*iptr = ID_ADDR_RAM; //從內(nèi)存區(qū)讀取BandGap電壓值(單位:毫伏mV) bandgap=*iptr++; //兩種方法結(jié)果一樣,上面的方法需要在下載式勾選"在ID號前添加重要測試參數(shù)"選項,才可在程序中獲取此參數(shù) bandgap<<=8; //下面的方法不需要 bandgap+=*iptr; */ //測量設(shè)定通道adc值 ADC_RES = 0; //清除結(jié)果寄存器 P1ASF = 0x08; //設(shè)置P1.3口為AD口 GetADCResult(ch); GetADCResult(ch); //讀三次獲得穩(wěn)定 adc_res10= GetADCResult(ch); //測量第九通道(bandgap)值 ADC_RES = 0; //清除結(jié)果寄存器 P1ASF = 0x00; //設(shè)置讀第九通道 GetADCResult(0); //測bandgap時,調(diào)用此函數(shù)時通道數(shù)只能填0 GetADCResult(0); //讀三次獲得穩(wěn)定 adc_9gallery_res=GetADCResult(0); //計算系統(tǒng)供電電壓 power_voltage=(float)bandgap*1024/adc_9gallery_res; //計算ADC通道測得電壓值 ADC_voltage=(float)bandgap*adc_res10/adc_9gallery_res; v=ADC_voltage; v=v*2; } |
原理圖.jpg (185.98 KB, 下載次數(shù): 998)
原理圖
你發(fā)帖子,我點贊,鼓勵繼續(xù)做貢獻 |
新手入門,學習中,感謝分享! |
好文章,我現(xiàn)在才看到![]() |
謝謝分享! |
單片機學習中,向無私分享的大神們致敬! |
好文章,學習了,收益很大! |
越快樂越墮落 發(fā)表于 2017-5-4 11:11 雖然我來的晚,但是我看見樓主說了,這個表量程9.9V,你要測量30.5V那肯定出問題, |
a185980800 發(fā)表于 2024-2-23 22:34 探討程序校準,硬件校準沒有意義 |
gpdt3209 發(fā)表于 2022-11-15 13:48 把R1換成多圈可調(diào)電阻,就可以校準了 |
taoran 發(fā)表于 2016-10-20 19:52 應(yīng)該是AD |
樓主分享的很有用,辛苦樓主了,這個改4位也好改吧![]() |
手頭剛好友幾個stc15w408as,有空拿來做電壓電流表似乎有不錯,謝樓主。 |
支持努力實踐并分享成果的人 |
很好的資料,收藏學習!謝謝分享 |
數(shù)碼管不亮,測了位選高電平4.6V,段選也是高電平4.48V |
都是牛人啊,下去用protues仿真測試一下下 |
很好的東西,值得學習,準備試試。 |
很好,值得分享,建議單片機多IO口都沒用,可以做成雙路現(xiàn)實的,實現(xiàn)電壓、電流同時測試、顯示。 |
簡單實用,新意構(gòu)思,值得學習。 |
fmdpj 發(fā)表于 2022-6-24 14:13 我沒分,下不了。應(yīng)該還有H文件 |
樓主的設(shè)計簡單、實用,適合初學仿制。 |
增加標定校準功能就準了,哪位大師可以改改 |
很好,值得點贊和學習 |
就喜歡這簡潔的設(shè)計,內(nèi)部基準精度應(yīng)該夠用,現(xiàn)在影響精度的是外部電阻, |
程序中 //計算系統(tǒng)供電電壓 power_voltage=(float)bandgap*1024/adc_9gallery_res; 多余了,沒用到,浪費算力 |
樓主還會來看嗎?我下載了附件,源代碼就怎么就這么一點點 ********************************************/ //2016.10.20日 1:01編寫完成 //作者:劉海龍 (讀單片機內(nèi)部BandGap基準電壓值參考的STC官網(wǎng)程序) //硬件:STC15W408AS+3位共陰數(shù)碼管+2個10K的電阻(1/4w) //晶振無說明的情況選12M //測量口P1.7 #include <STC15W.h> #include <intrins.h> #include<4LED_YIN.H>//數(shù)碼管驅(qū)動顯示程序 #include <BandGap.H>//包含讀單片機內(nèi)部BandGap基準電壓值 /********************************/ void main (void) { Delay20ms();//待系統(tǒng)穩(wěn)定 InitADC();//初始化ADC P1M1=0X80;//P1.7高阻輸入 init();//IO口設(shè)置初始化 while (1) { ShowResult(7);//顯示通道P1.7的測量值、單位為毫伏 disp(); //數(shù)碼管顯示電壓值 } } |
wjqzywmm 發(fā)表于 2021-7-19 18:43 你好!能否把完整的源代碼分享給我,先謝謝了 |
要是能移植到儲能點焊機控制板里面,用于監(jiān)視儲能電容電壓,這樣就不用另外配個電壓表,不會玩單片機只能看看 |
大神:LED沒有限流電阻,這個方案是如何控制電流,避免LED和MCU過流損壞的呢? |
原理很好,但有不理解的地方:一般而言,用限流電阻控制各LED的電流,目前的方案是以什么方式控制LED電流,以減少LED及MCU的過電流損壞?? |
hewe_001 發(fā)表于 2021-7-13 01:21 我驅(qū)動4為共陽的方法,電路圖相同,供參考: unsigned char code disdata[]={ 0x01,0x4F,0x12,0x06,0x4C, 0x24,0x20,0x0D,0x00,0x04};//0-9 void dis_off (){ P3 = 0xFF; //P3對應(yīng)筆畫,關(guān)所有顯示 H2=1;H4=1; H1=1;H3=1; delay(10-light); } void dispNum (unsigned char q,unsigned char dot){ //dot=1為顯示小數(shù)點; unsigned char x; x=disdata[q]; dp=1-dot; a=x>>6 & 0x01; b=x>>5 & 0x01; c=x>>4 & 0x01; d=x>>3 & 0x01; e=x>>2 & 0x01; f=x>>1 & 0x01; g=x & 0x01; } /******************顯示程序*************************/ void disp(){ unsigned int ii; unsigned int vv; unsigned char i; for(ii=0;ii<50;ii++){ i=v%10; //我用的是四位led,所以這里的v=原始v/10 vv=v-i; H1=0;dispNum(i,0);delay(light);dis_off(); i=(vv/10)%10; vv=vv-10*i; H2=0;dispNum(i,0);delay(light);dis_off(); i=(vv/100)%10; vv=vv-100*i; H3=0;dispNum(i,1);delay(light);dis_off(); //第三位顯示小數(shù)點 i=(vv/1000)%10; if(i>0){ H4=0;dispNum(i,0);delay(light);dis_off(); //第四位是0,不顯示 } } } |
真夠簡單的,正好想做一個,感謝樓主分享。! |
你發(fā)帖子,我點贊,鼓勵繼續(xù)做貢獻! |
劉海龍 發(fā)表于 2016-10-20 16:39 下載時已經(jīng)勾選了! |
留個記號 有時間了來學習一下,謝謝大神們。 |
電路簡潔,先收藏一下 |
樓主能不能改個共陽的程序? 或者在4LED_YIN.h中指明一下,怎樣修改? |
Powered by 單片機教程網(wǎng)