|
太棒了,我一直想制作一個(gè).下面是樓主的程序:
- /***************************************/
- /* 基于STC15W408AS的電流表設(shè)計(jì) */
- /* 測量范圍0-200mA,0-400uA */
- /* 創(chuàng)建者 :zsw */
- /* 創(chuàng)建時(shí)間:2020/12/21 */
- /***************************************/
- //2.5V基準(zhǔn)電壓接P1.0,uA采樣接P1.1,mA采樣接P1.2
- //毫安檔使用1歐(5%)檢流電阻,微安檔使用100歐(1%)檢流電阻。
- #include "STC15W408AS.H"
- #include "intrins.h"
- #define ADC_POWER 0x80 //ADC電源控制位
- #define ADC_FLAG 0x10 //ADC完成標(biāo)志位
- #define ADC_START 0x08 //ADC啟動控制位
- #define ADC_SPEED0 0x00 //ADC轉(zhuǎn)換速度,一次轉(zhuǎn)換需要540個(gè)時(shí)鐘
- #define ADC_SPEED1 0x20 //ADC轉(zhuǎn)換速度,一次轉(zhuǎn)換需要360個(gè)時(shí)鐘
- #define ADC_SPEED2 0x40 //ADC轉(zhuǎn)換速度,一次轉(zhuǎn)換需要180個(gè)時(shí)鐘
- #define ADC_SPEED3 0x60 //ADC轉(zhuǎn)換速度,一次轉(zhuǎn)換需要90個(gè)時(shí)鐘
- #define N 8 //ADC采樣使用遞推平均濾波算法,采樣次數(shù)
- sbit lcdrs=P3^2; //LCD1602指令和數(shù)據(jù)寄存器選擇,高電平時(shí)為數(shù)據(jù),低電平選擇命令
- sbit lcdrw=P3^3; //LCD1602讀寫選擇,高電平為讀,低電平為寫
- sbit lcden=P3^4; //LCD1602使能
- unsigned char Show[3]={0,0,0}; //顯示數(shù)組mA
- unsigned char Show1[3]={0,0,0}; //顯示數(shù)組uA
- unsigned int ADC_Buf[N+1]; //采樣數(shù)組mA
- unsigned int ADC_Buf2[N+1]; //采樣數(shù)值uA
- unsigned int current=0; //采樣毫安值
- unsigned int current2=0; //采樣微安值
- unsigned char num,ADCcount=0,ADCcount2=0; //ADC采樣次數(shù)變量
- unsigned char code table1[]="CURRENT1:";
- unsigned char code table2[]="CURRENT2:";
- /******************************
- 函數(shù)說明:延時(shí)函數(shù),執(zhí)行一次1毫秒,STC_ISP軟件給出 @6MHz 1T單片機(jī)
- 入口參數(shù):ms=延時(shí)毫秒數(shù)
- 出口參數(shù):無
- ******************************/
- void Delay_MS(unsigned int ms)
- {
- unsigned char i, j;
- while(ms--)
- {
- i = 6; j = 211;
- do{
- while (--j);
- } while (--i);
- }
- }
- /******************************
- 函數(shù)說明:LCD1602驅(qū)動
- ******************************/
- void write_com(unsigned char com)
- {
- lcdrs=0; //rs低電平為寫命令
- P2=com;
- Delay_MS(5);
- lcden=1; //EN先置高電平
- Delay_MS(5);
- lcden=0; //短暫延時(shí)后EN置低電平
- }
- void write_dat(unsigned char dat)
- {
- lcdrs=1; //rs高電平為寫數(shù)據(jù)
- P2=dat;
- Delay_MS(5);
- lcden=1;
- Delay_MS(5);
- lcden=0;
- }
- /******************************
- 函數(shù)說明:初始化ADC寄存器
- ******************************/
- void Init_ADC(void)
- {
- P1M1 |= 0x01;
- P1M0 &= ~1; //設(shè)P1.0為高阻輸入。因3.3V電源很精確,暫未使用2.5V基準(zhǔn)電壓源。
- P1ASF = 0x06; //打開P1.2和P1.1口的ADC功能
- ADC_RES = 0;
- ADC_RESL= 0; //清掉ADC轉(zhuǎn)換結(jié)果寄存器
- ADC_CONTR = ADC_POWER | ADC_SPEED3; //使能A/D供電,設(shè)置轉(zhuǎn)換速度90T
- }
- /******************************
- 函數(shù)說明:LCD1602初始化
- ******************************/
- void LCD1602_Init(void)
- {
- lcdrw=0;
- lcden=0;
- P2=0;
- write_com(0x38); //設(shè)置顯示模式為兩行5*8顯示
- write_com(0x0C); //初始化,開顯示
- write_com(0x06); //初始化,讀寫一個(gè)字符后地址指針自動加1
- write_com(0x01); //清屏
- write_com(0x80); //數(shù)據(jù)地址指針從0開始
- for(num=0;num<9;num++) //第1行顯示'CURRENT1:'
- write_dat(table1[num]);
- write_com(0x80+0x40); //數(shù)據(jù)地址指針從0開始
- for(num=0;num<9;num++) //第1行顯示'CURRENT2:'
- write_dat(table2[num]);
- }
- /******************************
- 函數(shù)說明:查詢方式讀取ADC轉(zhuǎn)換結(jié)果
- 入口參數(shù):ch ADC采樣通道
- 出口參數(shù):int ADC_RES ADC轉(zhuǎn)換結(jié)果
- ******************************/
- unsigned int Get_ADC_Result(unsigned char ch)
- {
- unsigned int result;
- ADC_RES = 0;
- ADC_RESL= 0; //清掉ADC轉(zhuǎn)換結(jié)果寄存器
- ADC_CONTR =ADC_POWER|ADC_SPEED3|ch|ADC_START;//配置ADC,設(shè)置轉(zhuǎn)換通道,啟動轉(zhuǎn)換
- _nop_(); _nop_();
- _nop_(); _nop_(); //等待設(shè)置ADC_POWER完畢
- while (!(ADC_CONTR & ADC_FLAG));//讀取轉(zhuǎn)換完畢標(biāo)志位ADC_FLAG
- ADC_CONTR &= ~ADC_FLAG; //清除ADC_FLAG標(biāo)志位
- result = ADC_RES<<2|ADC_RESL; //讀取10位轉(zhuǎn)換結(jié)果保存到result
- return result; //返回ADC轉(zhuǎn)換結(jié)果10位
- }
- /******************************
- 函數(shù)說明:獲取mA值
- ******************************/
- void Get_Current1(void)
- {
- unsigned char xx;
- unsigned int sum,currentvalue;
- sum = currentvalue =0;
- ADC_Buf[N]=Get_ADC_Result(2); //將ADC轉(zhuǎn)換結(jié)果放數(shù)組最高位
- if( ++ADCcount < 8) //采樣初期不使用濾波算法
- {
- for(xx=0;xx<N;xx++) //準(zhǔn)備濾波算法的數(shù)據(jù)
- {
- ADC_Buf[xx]=ADC_Buf[xx+1];//所有數(shù)據(jù)循環(huán)左移
- }
- currentvalue=ADC_Buf[N];//采樣初期使用當(dāng)前采樣值
- }
- else //只有采樣次數(shù)大于8次以后才使用濾波算法
- {
- ADCcount=8; //采樣次數(shù)超過8次后,固定設(shè)置為8
- for(xx=0;xx<N;xx++) //濾波算法
- {
- ADC_Buf[xx]=ADC_Buf[xx+1];//所有數(shù)據(jù)循環(huán)左移
- sum+=ADC_Buf[xx]; //求和
- }
- currentvalue=sum/N; //求平均值
- }
- currentvalue=currentvalue*0.3223; //ADC平均值轉(zhuǎn)化成mA電流值
- if(currentvalue>=2)
- currentvalue=currentvalue-2; //實(shí)測零點(diǎn)漂移了2~3mA
- if(currentvalue<=3) //顯示門檻
- currentvalue=0;
- current=currentvalue;
- }
-
- /******************************
- 函數(shù)說明:顯示mA值
- ******************************/
- void Display_mA(void)
- {
- if(current<=200)
- {
- Show[0]=current%1000/100; //電流值百位
- Show[1]=current%100/10; //電流值十位
- Show[2]=current%10; //電流值個(gè)位
- write_com(0x80+0x0A); //第1行第10個(gè)字符開始顯示
- if(Show[0]>0)
- write_dat(0x30+Show[0]); //寫電流值百位
- else
- write_dat(' ');
- if((Show[0]==0)&&(Show[1]==0))
- write_dat(' '); //寫電流值十位
- else
- write_dat(0x30+Show[1]);
- write_dat(0x30+Show[2]); //寫電流值個(gè)位
- write_dat(' ');
- write_dat('m');
- write_dat('A');
- }
- else //超量程顯示"999"
- {
- write_com(0x80+0x0A);
- write_dat('9');
- write_dat('9');
- write_dat('9');
- write_dat(' ');
- write_dat('m');
- write_dat('A');
- }
- }
- /******************************
- 函數(shù)說明:獲取uA值
- ******************************/
- void Get_Current2(void)
- {
- unsigned char xx;
- unsigned int sum,currentvalue;
- sum = currentvalue =0;
- ADC_Buf2[N]=Get_ADC_Result(1); //將ADC轉(zhuǎn)換結(jié)果放數(shù)組最高位
- if( ++ADCcount2 < 8) //采樣初期不使用濾波算法
- {
- for(xx=0;xx<N;xx++) //準(zhǔn)備濾波算法的數(shù)據(jù)
- {
- ADC_Buf2[xx]=ADC_Buf2[xx+1];//所有數(shù)據(jù)循環(huán)左移
- }
- currentvalue=ADC_Buf2[N];//采樣初期使用當(dāng)前采樣值
- }
- else //只有采樣次數(shù)大于8次以后才使用濾波算法
- {
- ADCcount2=8; //采樣次數(shù)超過8次后,固定設(shè)置為8
- for(xx=0;xx<N;xx++) //濾波算法
- {
- ADC_Buf2[xx]=ADC_Buf2[xx+1];//所有數(shù)據(jù)循環(huán)左移
- sum+=ADC_Buf2[xx]; //求和
- }
- currentvalue=sum/N; //求平均值
- }
- currentvalue=currentvalue*0.6445; //ADC平均值轉(zhuǎn)化成uA電流值
- if(currentvalue>=15)
- currentvalue=currentvalue-15; //實(shí)測零點(diǎn)漂移了15uA
- if(currentvalue<=3) //顯示門檻
- currentvalue=0;
- current2=currentvalue;
- }
- /******************************
- 函數(shù)說明:顯示uA值
- ******************************/
- void Display_uA(void)
- {
- if(current2<=400)
- {
- Show1[0]=current2%1000/100; //電流值百位
- Show1[1]=current2%100/10; //電流值十位
- Show1[2]=current2%10; //電流值個(gè)位
- write_com(0x80+0x40+0x0A); //第2行第10個(gè)字符開始顯示
- if(Show1[0]>0)
- write_dat(0x30+Show1[0]); //寫電流值百位
- else
- write_dat(' ');
- if((Show1[0]==0)&&(Show1[1]==0))
- write_dat(' '); //寫電流值十位
- else
- write_dat(0x30+Show1[1]);
- write_dat(0x30+Show1[2]); //寫電流值個(gè)位
- write_dat(' ');
- write_dat('u');
- write_dat('A');
- }
- else //超量程顯示"999"
- {
- write_com(0x80+0x40+0x0A);
- write_dat('9');
- write_dat('9');
- write_dat('9');
- write_dat(' ');
- write_dat('u');
- write_dat('A');
- }
- }
- void main(void)
- {
- Init_ADC(); //初始化ADC
- LCD1602_Init(); //初始化LCD1602
- while(1)
- {
- for(num=0;num<8;num++)
- {
- Get_Current1(); //獲取mA電流值
- Get_Current2(); //獲取uA電流值
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼 |
|