13.电压采集器

13.1 电压采集器

示例

四舍五入方法

a=1246 (a+5)/1000=1251/1000

float显示在数码管

a=2.78

(int )a=2

(int)(a*100)/10%10=7

(int)(a*100)%10=8

9999mV进位为10.0V

Seg_Point[3+(int)VAIN3/10]=1;

如果实际电压为10V,10/10=1,小数点后移一位,显示10.0

如果实际电压<10V,8.99/10=0;显示8.99

Seg_Buf[3] = (int)VAIN3/10?1:(unsigned char)VAIN3 % 10;

为10V显示1,不为时显示数据首位

高位熄灭(计数统计)

unsigned char j = 1;//用于While循环

Seg_Buf[1] = Count / 10000 % 10;
Seg_Buf[2] = Count / 1000 % 10;
Seg_Buf[3] = Count / 100 % 10;
Seg_Buf[4] = Count / 10 % 10;
Seg_Buf[5] = Count % 10;
//值为0时熄灭,Count=0跳过最后一位熄灭,显示0
while(Seg_Buf[j] == 0)
{
	Seg_Buf[j] = 10;
	if(++j == 5) break;
}

计数值增加

if(Voltage > Voltage_Parameter_Ctrol)//当实际电压大于参考电压时
		Voltage_Flag = 1;//拉高标志位
	else if(Voltage_Flag == 1)
	{
		Voltage_Flag = 0;//标志位复位
		Count++;//计数值+1
	}

Led

Led.c

#include <Led.h>

void Led_Disp(unsigned char addr,enable)
{
	static unsigned char temp = 0x00;
	static unsigned char temp_old = 0xff;
	if(enable)
		temp |= 0x01 << addr;
	else
		temp &= ~(0x01 << addr);
	if(temp != temp_old)
	{
		P1 = ~temp;
		temp_old = temp;
	}
}

main

unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//Led显示数据存放数组
unsigned char Led_Pos;

void Timer0Server() interrupt 1
{
	...
	if(++Led_Pos == 8) Led_Pos = 0;
	Led_Disp(Led_Pos,ucLed[Led_Pos]);
	...
}

实现

ucLed[0]=1;//第1个Led亮
ucLed[0]=0;//第1个Led灭
//流水灯
for(int i=0,i<8,i++)
{
	ucLed[i]=1;
}

总代码

1.自写

#include <REGX52.H>
#include <Key.h>
#include <Seg.h>

unsigned char Key_Slow_Down;
unsigned int Seg_Slow_Down;
unsigned char Key_Val,Key_Old,Key_Up,Key_Down;
unsigned char Seg_Buf[6]={10,10,10,10,10,10};
unsigned char Seg_Pos;
unsigned char Seg_Point[6]={0,0,0,0,0,0};
unsigned int Seg_Mode=1;//1-电压采集 2-数据显示 3-参数设置 4-计数统计
unsigned int U_mV=0;//单位为mV的输入电压数据
unsigned char U_mV_New[4]={14,14,14,14};
int U_mV_New_Flag=1;
int Seg_Mode_1_Flag=1;//闪烁标志位
int Timer_500ms;
int Timer_5s;
unsigned int VAIN3=0;//单位为V的实际电压数据
unsigned int VAIN3_Old=0;//上一次的实际电压数据
int Vp=300;//设置电压参数
unsigned char Num=0;//计数值数据
int wrong_count=0;

void Key_Proc()
{
	if(Key_Slow_Down)return;
	Key_Slow_Down=1;
	
	Key_Val=Key_Read();
	Key_Down=Key_Val&(Key_Old^Key_Val);
	Key_Up=~Key_Val&(Key_Old^Key_Val);
	Key_Old=Key_Val;
//	if(Key_Down<11 &&Seg_Mode==1)
//	{
//		U_mV_New[U_mV_New_Flag-1]=Key_Down-1;
//		U_mV_New_Flag++;
//		if(U_mV_New_Flag==5)U_mV_New_Flag=1;
//	}
	switch(Key_Down)
	{
		case 1:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=0;
				U_mV_New_Flag++;
				//if(U_mV_New_Flag==5)U_mV_New_Flag=1;
			}
		break;
		case 2:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=1;
				U_mV_New_Flag++;
			}
		break;
		case 3:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=2;
				U_mV_New_Flag++;
			}
		break;
		case 4:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=3;
				U_mV_New_Flag++;
			}
		break;
		case 5:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=4;
				U_mV_New_Flag++;
			}
		break;
		case 6:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=5;
				U_mV_New_Flag++;
			}
		break;
		case 7:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=6;
				U_mV_New_Flag++;
			}
		break;
		case 8:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=7;
				U_mV_New_Flag++;
			}
		break;
		case 9:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=8;
				U_mV_New_Flag++;
			}
		break;
		case 10:
			if(Seg_Mode==1)
			{
				U_mV_New[U_mV_New_Flag-1]=9;
				U_mV_New_Flag++;
			}
		break;
		//电压采集按键
		case 11:
			if(Seg_Mode!=1)
			{
				Seg_Mode=1;
				U_mV_New[0]=0;
				U_mV_New[1]=0;
				U_mV_New[2]=0;
				U_mV_New[3]=0;
				U_mV_New_Flag=1;
			}
			if(Seg_Mode==1)
			{
				if(U_mV_New>0 && U_mV_New_Flag==5)
				{
					U_mV=U_mV_New[0]*1000+U_mV_New[1]*100+U_mV_New[2]*10+U_mV_New[3];
					Seg_Mode=2;
					wrong_count=0;
					Timer_5s=0;
				}
				else
				{
					U_mV_New[0]=0;
					U_mV_New[1]=0;
					U_mV_New[2]=0;
					U_mV_New[3]=0;
					U_mV_New_Flag=1;
					wrong_count++;
				}
			}
		break;
		//界面切换按键
		case 12:
			if(Seg_Mode!=1)
			{
				Seg_Mode++;
				if(Seg_Mode==5)
				{
					Seg_Mode=2;
				}
			}
		break;
		//清零参数按键
		case 14:
			if(Seg_Mode==1)
			{
				U_mV_New[0]=0;
				U_mV_New[1]=0;
				U_mV_New[2]=0;
				U_mV_New[3]=0;
				U_mV_New_Flag=1;
			}
			if(Seg_Mode==4)
			{
				Num=0;
			}
		break;
		//参数+按键
		case 15:
			if(Seg_Mode==3)
			{
				Vp+=50;
				if(Vp==650)
				{
					Vp=100;
				}
			}
		break;
		//参数—按键
		case 16:
			if(Seg_Mode==3)
			{
				Vp-=50;
				if(Vp==50)
				{
					Vp=600;
				}
			}
		break;
	}
}

void Seg_Proc()
{
	unsigned char i;
	if(Seg_Slow_Down)return;
	Seg_Slow_Down=1;
	if(Seg_Mode==1)
	{
		Seg_Buf[0]=10;
		Seg_Buf[1]=10;
		Seg_Point[3]=0;
		if(U_mV_New_Flag==1)
		{
			Seg_Buf[2]=Seg_Mode_1_Flag?U_mV_New[0]:10;
			Seg_Buf[3]=U_mV_New[1];
			Seg_Buf[4]=U_mV_New[2];
			Seg_Buf[5]=U_mV_New[3];
		}
		if(U_mV_New_Flag==2)
		{
			Seg_Buf[2]=U_mV_New[0];
			Seg_Buf[3]=Seg_Mode_1_Flag?U_mV_New[1]:10;
			Seg_Buf[4]=U_mV_New[2];
			Seg_Buf[5]=U_mV_New[3];
		}
		if(U_mV_New_Flag==3)
		{
			Seg_Buf[2]=U_mV_New[0];
			Seg_Buf[3]=U_mV_New[1];
			Seg_Buf[4]=Seg_Mode_1_Flag?U_mV_New[2]:10;
			Seg_Buf[5]=U_mV_New[3];
		}
		if(U_mV_New_Flag==4)
		{
			Seg_Buf[2]=U_mV_New[0];
			Seg_Buf[3]=U_mV_New[1];
			Seg_Buf[4]=U_mV_New[2];
			Seg_Buf[5]=Seg_Mode_1_Flag?U_mV_New[3]:10;
		}
		if(U_mV_New_Flag==5)
		{
			Seg_Buf[2]=U_mV_New[0];
			Seg_Buf[3]=U_mV_New[1];
			Seg_Buf[4]=U_mV_New[2];
			Seg_Buf[5]=U_mV_New[3];
		}
	}
	if(Seg_Mode==2)
	{
		VAIN3_Old=VAIN3;
		VAIN3=U_mV/10;
		if(VAIN3_Old>Vp &&VAIN3<Vp)Num++;
		Seg_Buf[0]=11;//U
		Seg_Buf[1]=10;
		Seg_Buf[2]=10;
		Seg_Buf[3]=VAIN3/100;
		Seg_Point[3]=1;
		Seg_Buf[4]=(VAIN3/10)%10;
		Seg_Buf[5]=VAIN3%10;
	}
	if(Seg_Mode==3)
	{
		Seg_Buf[0]=12;//P
		Seg_Buf[1]=10;
		Seg_Buf[2]=10;
		Seg_Buf[3]=Vp/100;
		Seg_Point[3]=1;
		Seg_Buf[4]=(Vp/10)%10;
		Seg_Buf[5]=Vp%10;
	}
	if(Seg_Mode==4)
	{
		Seg_Buf[0]=13;//N
		if(Num<10)
		{
			Seg_Buf[1]=10;
			Seg_Buf[2]=10;
			Seg_Buf[3]=10;
			Seg_Point[3]=0;
			Seg_Buf[4]=10;
			Seg_Buf[5]=Num;
		}
		if(Num>10 &&Num<100)
		{
			Seg_Buf[1]=10;
			Seg_Buf[2]=10;
			Seg_Buf[3]=10;
			Seg_Point[3]=0;
			Seg_Buf[4]=Num/10;
			Seg_Buf[5]=Num%10;
		}
		if(Num>100 &&Num<1000)
		{
			Seg_Buf[1]=10;
			Seg_Buf[2]=10;
			Seg_Buf[3]=Num/100;
			Seg_Point[3]=0;
			Seg_Buf[4]=Num/10%10;
			Seg_Buf[5]=Num%10;
		}
		if(Num>1000 &&Num<10000)
		{
			Seg_Buf[1]=10;
			Seg_Buf[2]=Num/1000;
			Seg_Buf[3]=Num/100%10;
			Seg_Point[3]=0;
			Seg_Buf[4]=Num%100/10;
			Seg_Buf[5]=Num%10;
		}
		if(Num>10000)
		{
			Seg_Buf[1]=Num/10000;
			Seg_Buf[2]=Num/1000%10;
			Seg_Buf[3]=Num/100%10;
			Seg_Point[3]=0;
			Seg_Buf[4]=Num/10%10;
			Seg_Buf[5]=Num%10;
		}
	}
}

void Led_Proc()
{
	if(Num%2==1)
	{
		P1_1=0;
	}
	else
	{
		P1_1=1;
	}
	if(wrong_count>=3)
	{
		P1_2=0;
	}
	else
	{
		P1_2=1;
	}
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;
	EA = 1;
}

void Timer0Server() interrupt 1
{
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	if(++Key_Slow_Down ==10) Key_Slow_Down=0;
	if(++Seg_Slow_Down ==500) Seg_Slow_Down=0;
	if(++Seg_Pos==6)Seg_Pos=0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
	if(++Timer_500ms ==500)
	{
		Seg_Mode_1_Flag^=1;
		Timer_500ms=0;
	}
	if(VAIN3<Vp)
	{
		Timer_5s++;
	}
	if(Timer_5s >=5000)
	{
		P1_0=0;
	}
	else
	{
		P1_0=1;
	}
}

void main()
{
	Timer0_Init();
	while(1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}

2.示例代码

/* 头文件声明区 */
#include <REGX52.H>//单片机寄存器专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件

/* 变量声明区 */
unsigned char Key_Val,Key_Down,Key_Old;//按键专用变量
unsigned char Key_Slow_Down;//按键减速专用变量
unsigned char Seg_Buf[6] = {10,10,10,10,10,10};//数码管显示数据存放数组
unsigned char Seg_Pos;//数码管扫描专用变量
unsigned int Seg_Slow_Down;//数码管减速专用变量
unsigned char Seg_Disp_Mode;//数码管显示模式标志位 0-电压采集 1-数据显示 2-参数设置 3-计数统计
unsigned char Seg_Input[4] = {11,11,11,11};//数码管输入数据储存数组
unsigned char Seg_Input_Index;//数码管输入数据储存数组指针
unsigned int Timer_500Ms;//五百毫秒计时变量
unsigned char Seg_Point[6] = {0,0,0,0,0,0};//数码管小数点显示数组
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//Led显示数据存放数组
unsigned char Led_Pos;
unsigned int Count;// 计数值专用变量
unsigned int Sys_Tick;//系统计时器
unsigned char Key_Error_Count;//无效按键统计变量
float Voltage;//实际电压变量
float Voltage_Parameter = 3.0;//电压设置参数
float Voltage_Parameter_Ctrol = 3.0;//实际电压设置参数  默认值3.0V
bit Seg_Flag;//数码管闪烁标志位
bit Voltage_Flag ;//电压参考标志位

/* 键盘处理函数 */
void Key_Proc()
{
	unsigned char i;//用于For循环
	if(Key_Slow_Down) return;
	Key_Slow_Down = 1;//键盘减速程序

	Key_Val = Key_Read();//实时读取键码值
	Key_Down = Key_Val & (Key_Old ^ Key_Val);//捕捉按键下降沿
	Key_Old = Key_Val;//辅助扫描变量
	
	if(Key_Down >= 1 && Key_Down <= 10)//键盘使能条件
	{
		if(Seg_Disp_Mode == 0 && Seg_Input_Index < 4)
		{
			Seg_Input[Seg_Input_Index] = Key_Down - 1;
			Seg_Input_Index++;
			Key_Error_Count = 0;
		}
		else
			Key_Error_Count++;
	}
	
	switch(Key_Down)
	{
		case 11:
			Key_Error_Count = 0;
			if(Seg_Disp_Mode == 0)//处于电压采集界面
			{
				if(Seg_Input_Index >= 4)//判断数据有效性
				{
					Voltage = (Seg_Input[0] * 1000 + Seg_Input[1] * 100 + Seg_Input[2] * 10 + Seg_Input[3] + 5) / 1000.0;
					if(Voltage >= 0.01)
						Seg_Disp_Mode = 1;//跳转到数据显示界面
					else
					{
						Seg_Input_Index = 0;//输入指针复位
						for(i = 0;i < 4;i++)//输入数组复位
							Seg_Input[i] = 11;
					}
				}
				else
				{
					Seg_Input_Index = 0;//输入指针复位
					for(i = 0;i < 4;i++)//输入数组复位
						Seg_Input[i] = 11;
				}
			}
			else//处于非电压采集界面
			{
				Seg_Disp_Mode = 0;//跳转到电压采集界面
				Seg_Input_Index = 0;//输入指针复位
				for(i = 0;i < 4;i++)//输入数组复位
					Seg_Input[i] = 11;
			}
		break;
		case 12:
			if(Seg_Disp_Mode != 0)//处于非电压采集界面
			{
				Key_Error_Count = 0;
				if(Seg_Disp_Mode == 2)
					Voltage_Parameter = Voltage_Parameter_Ctrol;//保存当前设置参数
				if(++Seg_Disp_Mode == 4)
					Seg_Disp_Mode = 1;
			}
			else
				Key_Error_Count++;
		break;
		case 15:
			if(Seg_Disp_Mode == 2)//处于参数设置界面
			{
				Key_Error_Count = 0;
				Voltage_Parameter += 0.5;
				if(Voltage_Parameter > 6)
					Voltage_Parameter = 1;
			}
			else
				Key_Error_Count++;
		break;
		case 16:
			if(Seg_Disp_Mode == 2)//处于参数设置界面
			{
				Key_Error_Count = 0;
				Voltage_Parameter -=0.5;
				if(Voltage_Parameter < 1)
					Voltage_Parameter = 6;
			}
			else
				Key_Error_Count++;
		break;
		case 14:
			if(Seg_Disp_Mode == 0)
			{
				Key_Error_Count = 0;
				Seg_Input_Index = 0;//输入指针复位
				for(i = 0;i < 4;i++)//输入数组复位
					Seg_Input[i] = 11;
			}
			else if(Seg_Disp_Mode == 3)
			{
				Key_Error_Count = 0;
				Count = 0;
			}
			else
				Key_Error_Count++;
		break;
	}
}

/* 信息处理函数 */
void Seg_Proc()
{
	unsigned char i;//用于For循环
	unsigned char j = 1;//用于While循环
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;//数码管减速程序
	
	if(Voltage > Voltage_Parameter_Ctrol)//当实际电压大于参考电压时
		Voltage_Flag = 1;//拉高标志位
	else if(Voltage_Flag == 1)
	{
		Voltage_Flag = 0;//标志位复位
		Count++;//计数值+1
	}
	switch(Seg_Disp_Mode)
	{
		case 0://电压采集界面
			Seg_Point[3+(int)Voltage/10] = 0;
			Seg_Buf[0] = Seg_Buf[1] = 10;
			for(i = 0;i< 4;i++)
				Seg_Buf[2+i] = Seg_Input[i];
			if(Seg_Buf[5] == 11)//只有当最后一位为-时 才实现数码管闪烁功能
				Seg_Buf[2+Seg_Input_Index] = Seg_Flag?Seg_Input[Seg_Input_Index]:10;
		break;
		case 1://数据显示界面
			Seg_Point[3+(int)Voltage/10] = 1;
			Seg_Buf[0] = 12;
			Seg_Buf[1] = Seg_Buf[2] = 10;
			Seg_Buf[3] = (int)Voltage/10?1:(unsigned char)Voltage % 10;
			Seg_Buf[4] = (unsigned int)(Voltage * 100) / 10 % 10;
			Seg_Buf[5] = (unsigned int)(Voltage * 100) % 10;
		break;
		case 2://参数设置界面
			Seg_Point[3+(int)Voltage/10] = 1;
			Seg_Buf[0] = 13;
			Seg_Buf[1] = Seg_Buf[2] = 10;
			Seg_Buf[3] = (unsigned char)Voltage_Parameter % 10;
			Seg_Buf[4] = (unsigned int)(Voltage_Parameter * 100) / 10 % 10;
			Seg_Buf[5] = (unsigned int)(Voltage_Parameter * 100) % 10;			
		break;
		case 3://计数统计界面
			Seg_Point[3+(int)Voltage/10] = 0;
			Seg_Buf[0] = 14;
			Seg_Buf[1] = Count / 10000 % 10;
		  Seg_Buf[2] = Count / 1000 % 10;
			Seg_Buf[3] = Count / 100 % 10;
			Seg_Buf[4] = Count / 10 % 10;
			Seg_Buf[5] = Count % 10;
			while(Seg_Buf[j] == 0)
			{
				Seg_Buf[j] = 10;
				if(++j == 5) break;
			}
		break;
	}
}

/* 其他显示函数 */
void Led_Proc()
{
	if(Voltage < Voltage_Parameter_Ctrol)
	{
		if(Sys_Tick >= 5000)
			ucLed[0] = 1;
	}
	else
	{
		Sys_Tick = ucLed[0] = 0;
	}
	ucLed[1] = Count % 2;
	ucLed[2] = Key_Error_Count / 3;
}

/* 定时器0中断初始化函数 */
void Timer0Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初始值
	TH0 = 0xFC;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;    //定时器0中断打开
	EA = 1;     //总中断打开
}

/* 定时器0中断服务函数 */
void Timer0Server() interrupt 1
{
 	TL0 = 0x18;		//设置定时初始值
	TH0 = 0xFC;		//设置定时初始值   
	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//键盘减速专用
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;//数码管减速专用
	if(++Seg_Pos == 6) Seg_Pos = 0;//数码管显示专用
	if(++Led_Pos == 8) Led_Pos = 0;
	Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
	Led_Disp(Led_Pos,ucLed[Led_Pos]);
	if(Voltage < Voltage_Parameter_Ctrol)
		Sys_Tick++;
	if(++Timer_500Ms == 500)
	{
		Timer_500Ms = 0;
		Seg_Flag ^= 1;
	}
}

/* Main */
void main()
{
	Timer0Init();
	while (1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}