太棒了,我一直想制作一个.下面是楼主的程序:
- /***************************************/
- /* 基于STC15W408AS的电流表设计 */
- /* 测量范围0-200mA,0-400uA */
- /* 创建者 :zsw */
- /* 创建时间:2020/12/21 */
- /***************************************/
- //2.5V基准电压接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完成标志位
- #define ADC_START 0x08 //ADC启动控制位
- #define ADC_SPEED0 0x00 //ADC转换速度,一次转换需要540个时钟
- #define ADC_SPEED1 0x20 //ADC转换速度,一次转换需要360个时钟
- #define ADC_SPEED2 0x40 //ADC转换速度,一次转换需要180个时钟
- #define ADC_SPEED3 0x60 //ADC转换速度,一次转换需要90个时钟
- #define N 8 //ADC采样使用递推平均滤波算法,采样次数
- sbit lcdrs=P3^2; //LCD1602指令和数据寄存器选择,高电平时为数据,低电平选择命令
- sbit lcdrw=P3^3; //LCD1602读写选择,高电平为读,低电平为写
- sbit lcden=P3^4; //LCD1602使能
- unsigned char Show[3]={0,0,0}; //显示数组mA
- unsigned char Show1[3]={0,0,0}; //显示数组uA
- unsigned int ADC_Buf[N+1]; //采样数组mA
- unsigned int ADC_Buf2[N+1]; //采样数值uA
- unsigned int current=0; //采样毫安值
- unsigned int current2=0; //采样微安值
- unsigned char num,ADCcount=0,ADCcount2=0; //ADC采样次数变量
- unsigned char code table1[]="CURRENT1:";
- unsigned char code table2[]="CURRENT2:";
- /******************************
- 函数说明:延时函数,执行一次1毫秒,STC_ISP软件给出 @6MHz 1T单片机
- 入口参数:ms=延时毫秒数
- 出口参数:无
- ******************************/
- void Delay_MS(unsigned int ms)
- {
- unsigned char i, j;
- while(ms--)
- {
- i = 6; j = 211;
- do{
- while (--j);
- } while (--i);
- }
- }
- /******************************
- 函数说明:LCD1602驱动
- ******************************/
- void write_com(unsigned char com)
- {
- lcdrs=0; //rs低电平为写命令
- P2=com;
- Delay_MS(5);
- lcden=1; //EN先置高电平
- Delay_MS(5);
- lcden=0; //短暂延时后EN置低电平
- }
- void write_dat(unsigned char dat)
- {
- lcdrs=1; //rs高电平为写数据
- P2=dat;
- Delay_MS(5);
- lcden=1;
- Delay_MS(5);
- lcden=0;
- }
- /******************************
- 函数说明:初始化ADC寄存器
- ******************************/
- void Init_ADC(void)
- {
- P1M1 |= 0x01;
- P1M0 &= ~1; //设P1.0为高阻输入。因3.3V电源很精确,暂未使用2.5V基准电压源。
- P1ASF = 0x06; //打开P1.2和P1.1口的ADC功能
- ADC_RES = 0;
- ADC_RESL= 0; //清掉ADC转换结果寄存器
- ADC_CONTR = ADC_POWER | ADC_SPEED3; //使能A/D供电,设置转换速度90T
- }
- /******************************
- 函数说明:LCD1602初始化
- ******************************/
- void LCD1602_Init(void)
- {
- lcdrw=0;
- lcden=0;
- P2=0;
- write_com(0x38); //设置显示模式为两行5*8显示
- write_com(0x0C); //初始化,开显示
- write_com(0x06); //初始化,读写一个字符后地址指针自动加1
- write_com(0x01); //清屏
- write_com(0x80); //数据地址指针从0开始
- for(num=0;num<9;num++) //第1行显示'CURRENT1:'
- write_dat(table1[num]);
- write_com(0x80+0x40); //数据地址指针从0开始
- for(num=0;num<9;num++) //第1行显示'CURRENT2:'
- write_dat(table2[num]);
- }
- /******************************
- 函数说明:查询方式读取ADC转换结果
- 入口参数:ch ADC采样通道
- 出口参数:int ADC_RES ADC转换结果
- ******************************/
- unsigned int Get_ADC_Result(unsigned char ch)
- {
- unsigned int result;
- ADC_RES = 0;
- ADC_RESL= 0; //清掉ADC转换结果寄存器
- ADC_CONTR =ADC_POWER|ADC_SPEED3|ch|ADC_START;//配置ADC,设置转换通道,启动转换
- _nop_(); _nop_();
- _nop_(); _nop_(); //等待设置ADC_POWER完毕
- while (!(ADC_CONTR & ADC_FLAG));//读取转换完毕标志位ADC_FLAG
- ADC_CONTR &= ~ADC_FLAG; //清除ADC_FLAG标志位
- result = ADC_RES<<2|ADC_RESL; //读取10位转换结果保存到result
- return result; //返回ADC转换结果10位
- }
- /******************************
- 函数说明:获取mA值
- ******************************/
- void Get_Current1(void)
- {
- unsigned char xx;
- unsigned int sum,currentvalue;
- sum = currentvalue =0;
- ADC_Buf[N]=Get_ADC_Result(2); //将ADC转换结果放数组最高位
- if( ++ADCcount < 8) //采样初期不使用滤波算法
- {
- for(xx=0;xx<N;xx++) //准备滤波算法的数据
- {
- ADC_Buf[xx]=ADC_Buf[xx+1];//所有数据循环左移
- }
- currentvalue=ADC_Buf[N];//采样初期使用当前采样值
- }
- else //只有采样次数大于8次以后才使用滤波算法
- {
- ADCcount=8; //采样次数超过8次后,固定设置为8
- for(xx=0;xx<N;xx++) //滤波算法
- {
- ADC_Buf[xx]=ADC_Buf[xx+1];//所有数据循环左移
- sum+=ADC_Buf[xx]; //求和
- }
- currentvalue=sum/N; //求平均值
- }
- currentvalue=currentvalue*0.3223; //ADC平均值转化成mA电流值
- if(currentvalue>=2)
- currentvalue=currentvalue-2; //实测零点漂移了2~3mA
- if(currentvalue<=3) //显示门槛
- currentvalue=0;
- current=currentvalue;
- }
-
- /******************************
- 函数说明:显示mA值
- ******************************/
- void Display_mA(void)
- {
- if(current<=200)
- {
- Show[0]=current%1000/100; //电流值百位
- Show[1]=current%100/10; //电流值十位
- Show[2]=current%10; //电流值个位
- write_com(0x80+0x0A); //第1行第10个字符开始显示
- 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]); //写电流值个位
- 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');
- }
- }
- /******************************
- 函数说明:获取uA值
- ******************************/
- void Get_Current2(void)
- {
- unsigned char xx;
- unsigned int sum,currentvalue;
- sum = currentvalue =0;
- ADC_Buf2[N]=Get_ADC_Result(1); //将ADC转换结果放数组最高位
- if( ++ADCcount2 < 8) //采样初期不使用滤波算法
- {
- for(xx=0;xx<N;xx++) //准备滤波算法的数据
- {
- ADC_Buf2[xx]=ADC_Buf2[xx+1];//所有数据循环左移
- }
- currentvalue=ADC_Buf2[N];//采样初期使用当前采样值
- }
- else //只有采样次数大于8次以后才使用滤波算法
- {
- ADCcount2=8; //采样次数超过8次后,固定设置为8
- for(xx=0;xx<N;xx++) //滤波算法
- {
- ADC_Buf2[xx]=ADC_Buf2[xx+1];//所有数据循环左移
- sum+=ADC_Buf2[xx]; //求和
- }
- currentvalue=sum/N; //求平均值
- }
- currentvalue=currentvalue*0.6445; //ADC平均值转化成uA电流值
- if(currentvalue>=15)
- currentvalue=currentvalue-15; //实测零点漂移了15uA
- if(currentvalue<=3) //显示门槛
- currentvalue=0;
- current2=currentvalue;
- }
- /******************************
- 函数说明:显示uA值
- ******************************/
- void Display_uA(void)
- {
- if(current2<=400)
- {
- Show1[0]=current2%1000/100; //电流值百位
- Show1[1]=current2%100/10; //电流值十位
- Show1[2]=current2%10; //电流值个位
- write_com(0x80+0x40+0x0A); //第2行第10个字符开始显示
- 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]); //写电流值个位
- 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黑下载附件…………
复制代码 |