OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 一款采用51单片机的电压电流表制作

共4条 1/1 1 跳转至

一款采用51单片机的电压电流表制作

工程师
2020-11-20 20:41:22    评分

单片机学久了,就想动动手,实战一番 

以下的这款这款电压电流表的制作文件,希望对大家有参考意义和帮助~


先看一下实际运行效果图:

image.png


PCB图:

原理图:

image.png

image.png

源码如下:

//stc12c5a60                        

#include<STC12C5A60S2.h>

#include<stdio.h>

#include<intrins.h>//头文件


#define uchar unsigned char//宏定义

#define uint unsigned int//宏定义

#define ulint unsigned long int//宏定义

#define N 21//ADC中值滤波次数,必须为基数

#define ISP_TRIG() ISP_TRIG=0x5A,ISP_TRIG=0xA5//ISP触发命令


sbit rs=P3^5;//液晶RS

sbit rw=P3^6;//液晶RW

sbit e=P3^4;//液晶E


void AD_init(void);//ADC初始化

void delay(uint z);//延时函数

uint AD_get(uchar haha );//读ADC的数值

void LCD_data(uchar shuju);//写数据

void zhiling(uchar zhilin);//写指令

void LCD_init(void);//初始化LCD

void tablex(uint tab);//数据分解

uint filter(uchar dat);//中值滤波

void timer_init(void);//定时器初始化


uchar h1,h2,h3,h4;//LCD显示变量

ulint mas,maz;//容量计算


uchar table[]="0123456789";//显示数组

uchar table1[]=".VAWa";


void main()

{

        ulint tempv,tempa;//存放电压电流值

        AD_init();//ADC初始化

        timer_init();//定时器初始化

        LCD_init();//LCD初始化

        while(1)

        {

                tempv=filter(0x88);//设置ADC通道0、开始转换

                tablex(tempv*3);//分解数据

                zhiling(0x80);//LCD地址

                LCD_data(table[h1]);//

                LCD_data(table[h2]);//

                LCD_data(table1[0]);//

                LCD_data(table[h3]);//

                LCD_data(table[h4]);//

                LCD_data(table1[1]);//显示

                

                tempa=filter(0x8f);//设置ADC通道7、开始转换

                if(tempa<=10)//防止数据成负数

                        tempa=10;

                mas=tempa*3-30;//计算容量取样赋值

                tablex(tempa*3-30);//减去LM358失调的数值

                zhiling(0x88);//LCD地址

                LCD_data(table[h1]);

                LCD_data(table1[0]);

                LCD_data(table[h2]);

                LCD_data(table[h3]);

                LCD_data(table[h4]);

                LCD_data(table1[2]);

                

                tablex((tempv*3/10)*((tempa*3-30)/10)/10);//计算功率

                zhiling(0x80+0x40);

                LCD_data(table[h1]);

                LCD_data(table[h2]);

                LCD_data(table1[0]);

                LCD_data(table[h3]);

                LCD_data(table[h4]);

                LCD_data(table1[3]);

                

                tablex(maz/1000);//显示MAH

                zhiling(0x88+0x40);

                LCD_data(table[h1]);

                LCD_data(table1[0]);

                LCD_data(table[h2]);

                LCD_data(table[h3]);

                LCD_data(table[h4]);

                LCD_data(table1[4]);

                

        }

}

//-------------------------------------------------------------

void delay(uint z)///////////////延时程序

{

   uint x,y;

   for(x=z;x>0;x--)

   for(y=19;y>0;y--);

}

void AD_init(void)/////////////////////初始化ADC

{

P1ASF=0xff;//P1口全部作为模拟功能AD使用

ADC_RES=0;//清零转换结果寄存器高8位

ADC_RESL=0;//清零转换结果寄存器低2位

ADC_CONTR=0x80;//开启AD电源

delay(5);//等待1ms,让AD电源稳定

}


uint AD_get(uchar haha )//ADC读数

{

        uint rew;

        ADC_CONTR=haha;//开启AD转换

        _nop_(); _nop_(); _nop_(); _nop_();//要经过4个CPU时钟的延时

        while(!(ADC_CONTR&0x10));//等待转换完成

        ADC_CONTR&=0xe7;//关闭AD转换,ADC_FLAG位由软件清0 

        rew=ADC_RES*4+ADC_RESL;//组合成10位

        delay(1);//等待

        return rew;//返回ADC值

}

void zhiling(uchar zhilin)//写指令

{

        e=0;

        rs=0;

        rw=0;

        P0=zhilin;

        delay(20);

        e=1;

        delay(20);

        e=0;

}

void LCD_data(uchar shuju)//写数据

{

        e=0;

        rs=1;

        rw=0;

        P0=shuju;

        delay(20);

        e=1;

        delay(20);

        e=0;

}

void LCD_init(void)//初始化LCD

{

delay(300);

zhiling(0x38);

delay(100);

zhiling(0x38);

delay(100);

zhiling(0x38);

delay(100);

zhiling(0x38);

zhiling(0x38);

zhiling(0x08);

zhiling(0x01);

zhiling(0x06);

zhiling(0x0c);

}

void tablex(uint tab1)//数据分解

{

        h1=tab1/1000;//1023//1

        h2=tab1%1000/100;//023//0

        h3=tab1%100/10;//23//2

        h4=tab1%10;//3

}

uint filter(uchar dat)//中位值滤波

{

   uint value_buf[N];

   uint count,i,j,temp;

   for(count=0;count<N;count++)

   {

                         AD_init();//初始化ADC

      value_buf[count] = AD_get(dat);//读ADC数值

      delay(1);

   }

   for (j=0;j<N-1;j++)

   {

      for (i=0;i<N-j;i++)

      {

         if ( value_buf[i]>value_buf[i+1] )

         {

            temp = value_buf[i];

            value_buf[i] = value_buf[i+1];

            value_buf[i+1] = temp;

         }

      }

   }

   return value_buf[(N-1)/2];

}

void timer_init(void)//定时器初始化

{

        TMOD=0x01;/////////设置工作方式1

        TH0=(65536-50000)/256;///////赋值

        TL0=(65536-50000)%256;

        EA=1;ET0=1;//开总中断;开定时器中断

        TR0=1;////////启动计数器

}






关键词: 电流表     电压表     LCD1602    

工程师
2020-11-20 20:56:45    评分
2楼

资料很全嘛! 可以好好参考一下咯~


工程师
2020-11-20 21:08:32    评分
3楼

学习学习,好好看看。


工程师
2020-11-20 21:24:45    评分
4楼

动手能力还是蛮强的


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]