⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1602lcd-2.c

📁 一个使用adc0809进行数据采集,采用1602液晶显示模拟电压的源程序,已经调试通过.
💻 C
字号:
#include <REG51.H>
#include <INTRINS.H>				//为调用nop空指令需要


#define 	DS_NOP()		_nop_();_nop_();_nop_();_nop_()
#define 	REF_Voltage  	5.25  //ADC0809基准电压
#define 	PLUS_CH0		1	  //各个通道增益
#define 	PLUS_CH1		1
#define 	PLUS_CH2		1
#define 	PLUS_CH3		5
#define 	PLUS_CH4		1
#define 	PLUS_CH5		1
#define 	PLUS_CH6		1
#define 	PLUS_CH7		1


	       
/**************ADC0809引脚定义**********/
sbit   		ST  		= P2^5;
sbit   		OE  		= P2^4;
sbit   		EOC 		= P2^3;
sbit		ADC0809_C 	= P2^2;
sbit		ADC0809_B 	= P2^1;
sbit		ADC0809_A	= P2^0;

/**************LCD引脚定义*************/
sbit 		LCM_RW  	= 	P3^6; 			//定义LCD引脚
sbit 		LCM_RS  	= 	P3^7;
sbit 		LCM_E   	= 	P3^5;
#define 	LCM_Data 		P1
#define 	Busy 			0x80 			//用于检测LCM状态字中的Busy标识

/************函数声明*******************/
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void DisplayNumberFloat(unsigned char X, unsigned char Y,float Number,unsigned char point_number);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(unsigned char ScanCode);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);

unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
unsigned char code cdle_net[] = {"   welcome...   "};
unsigned char code email[] = {"VoltageTestDemo!"};
unsigned char code Cls[] = {" "};

float VoltageSurvey(unsigned char AD_ChannelNumber);

void main(void)
{
	float CHa_voltage;			//显示在第一行上的测量电压
	float CHb_voltage;			//显示在第二行上的测量电压
			
	Delay400Ms();				//启动等待,等LCM讲入工作状态
	LCMInit(); 					//LCM初始化
	Delay400Ms(); 
	DisplayListChar(0, 0, cdle_net);
 	DisplayListChar(0, 1, email);
	Delay400Ms(); 
	Delay400Ms(); 
	Delay400Ms();
	Delay400Ms();
	WriteCommandLCM(0x01,1); //显示清屏,光标归位,地址归位
	
	DisplayListChar(15, 0, "V");	//显示单位
 	DisplayListChar(15, 1, "V");
	WriteCommandLCM(0x0c,1); //关光标,关闪烁

	while(1)
	{
		CHa_voltage = VoltageSurvey(0);		  					//测量通道0电压
		DisplayListChar(0, 0, "CH0:");							
		DisplayNumberFloat(7,0,CHa_voltage,2);					//在LCD中部显示通道0电压
		Delay5Ms();
		CHb_voltage = VoltageSurvey(1);							//测量通道1电压
		DisplayListChar(0, 1, "CH1:");
		DisplayNumberFloat(7,1,CHb_voltage,2);					//在LCD中部显示通道1电压
		Delay5Ms();
		Delay400Ms();											//延时1.6s,即停留显示1.6s
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();

		CHa_voltage = VoltageSurvey(2);
		DisplayListChar(0, 0, "CH2:");
		DisplayNumberFloat(7,0,CHa_voltage,2);
		Delay5Ms();
		CHb_voltage = VoltageSurvey(3);
		DisplayListChar(0, 1, "CH3:");
		DisplayNumberFloat(7,1,CHb_voltage,2);
		Delay5Ms();
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();

		CHa_voltage = VoltageSurvey(4);
		DisplayListChar(0, 0, "CH4:");
		DisplayNumberFloat(7,0,CHa_voltage,2);
		Delay5Ms();
		CHb_voltage = VoltageSurvey(5);
		DisplayListChar(0, 1, "CH5:");
		DisplayNumberFloat(7,1,CHb_voltage,2);
		Delay5Ms();
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();

		
		CHa_voltage = VoltageSurvey(6);
		DisplayListChar(0, 0, "CH6:");
		DisplayNumberFloat(7,0,CHa_voltage,2);
		Delay5Ms();
		CHb_voltage = VoltageSurvey(7);
		DisplayListChar(0, 1, "CH7:");
		DisplayNumberFloat(7,1,CHb_voltage,2);
		Delay5Ms();
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();
		Delay400Ms();

		

	}
}
/*
//#######################################################################################################################################
//#######################################################################################################################################
													ADC0809驱动部分
*/

	
/*****************************************************
ADC0809转换函数
输入: 通道号(0-7)
返回: 测量到的模拟电压所对应的数字量
*****************************************************/
unsigned char ADC0809test(unsigned char ch0)
{
	unsigned char ADCdata;	   		//AD转换后得到的数字量

	ST  = 0;
	EOC = 1;
	OE  = 0;
	
	switch(ch0)
	{
		case 0:
		{
			ADC0809_A = 0;
			ADC0809_B = 0;
			ADC0809_C = 0;
			break;	
		}
		case 1:
		{
			ADC0809_A = 1;
			ADC0809_B = 0;
			ADC0809_C = 0;
			break;	
		}
		case 2:
		{
			ADC0809_A = 0;
			ADC0809_B = 1;
			ADC0809_C = 0;
			break;	
		}
		case 3:
		{
			ADC0809_A = 1;
			ADC0809_B = 1;
			ADC0809_C = 0;
			break;	
		}
		case 4:
		{
			ADC0809_A = 0;
			ADC0809_B = 0;
			ADC0809_C = 1;
			break;	
		}
		case 5:
		{
			ADC0809_A = 1;
			ADC0809_B = 0;
			ADC0809_C = 1;
			break;	
		}

		case 6:
		{
			ADC0809_A = 0;
			ADC0809_B = 1;
			ADC0809_C = 1;
			break;	
		}
		case 7:
		{
			ADC0809_A = 1;
			ADC0809_B = 1;
			ADC0809_C = 1;
			break;	
		}
		default:break;
	}
	ST = 1;
	ST = 0;
	DS_NOP();

	while(EOC == 0)
	{
	  ;
	}
	if(EOC == 1)
	{
		OE = 1;
		ADCdata  = P0;
		return (ADCdata); 
	}
}

/*******************************************************
 电压测量并装换成实际的电压值
入口参数: AD_ChannelNumber 输入通道号:在0-7之间选择 
出口参数: 转换后的电压值,实际的值
********************************************************/
float VoltageSurvey(unsigned char AD_ChannelNumber)
{
	float  SurveyVoltage;										//测量到的电压值
	float  plus_ch;												//通道增益
	
	switch(AD_ChannelNumber)
	{
		case 0:	plus_ch = PLUS_CH0;break;
		case 1:	plus_ch = PLUS_CH1;break;
		case 2:	plus_ch = PLUS_CH2;break;
		case 3:	plus_ch = PLUS_CH3;break;
		case 4:	plus_ch = PLUS_CH4;break;
		case 5:	plus_ch = PLUS_CH5;break;
		case 6:	plus_ch = PLUS_CH6;break;
		case 7:	plus_ch = PLUS_CH7;break;
		default:break;
	}

	SurveyVoltage = ADC0809test(AD_ChannelNumber);
	SurveyVoltage = (SurveyVoltage / 256) * REF_Voltage * plus_ch;
	return(SurveyVoltage);
}   
   







/*
//#######################################################################################################################################
//#######################################################################################################################################
													LCD驱动部分
*/



//写数据
void WriteDataLCM(unsigned char WDLCM)
{
	ReadStatusLCM(); //检测忙
	LCM_Data = WDLCM;
	LCM_RS = 1;
	LCM_RW = 0;
	LCM_E = 0; //若晶振速度太高可以在这后加小的延时
	LCM_E = 0; //延时
	LCM_E = 1;
}

//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
	if (BuysC) ReadStatusLCM(); //根据需要检测忙
	LCM_Data = WCLCM;
	LCM_RS = 0;
	LCM_RW = 0;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
}

//读数据
unsigned char ReadDataLCM(void)
{
	LCM_RS = 1;
	LCM_RW = 1;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
	return(LCM_Data);
}

//读状态
unsigned char ReadStatusLCM(void)
{
	LCM_Data = 0xFF;
	LCM_RS = 0;
	LCM_RW = 1;
	LCM_E = 0;
	LCM_E = 0;
	LCM_E = 1;
	while (LCM_Data & Busy); //检测忙信号
	return(LCM_Data);
}

void LCMInit(void) //LCM初始化
{
	LCM_Data = 0;
	WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
	Delay5Ms();
	WriteCommandLCM(0x38,0);
	Delay5Ms();
	WriteCommandLCM(0x38,0);
	Delay5Ms();
	
	WriteCommandLCM(0x38,1); 		//显示模式设置,8位数据,2行显示,5*7点阵,开始要求每次检测忙信号
	WriteCommandLCM(0x08,1); 		//关闭显示,关屏幕,关光标,关闪烁
	WriteCommandLCM(0x01,1); 		//显示清屏,光标归位,地址归位
	WriteCommandLCM(0x06,1); 		// 显示光标移动设置,每显示一个地址加1,不整体移位.
	WriteCommandLCM(0x0c,1); 		// 显示开及光标设置,开屏幕,关光标,关闪烁.
}

//按指定位置显示一个字符
//送入该字符所对应的ASCII码
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
	Y &= 0x1;
	X &= 0xF; 						//限制X不能大于15,Y不能大于1
	if (Y) X |= 0x40; 				//当要显示第二行时地址码+0x40;
	X |= 0x80;					 	//算出指令码
	WriteCommandLCM(X, 1); 			//发命令字
	WriteDataLCM(DData); 			//发数据
}

//按指定位置显示一串字符
//由于*DData是字符型指针变量,所以在提取该指针变量所指向的字符时得到的就是该字符的ASCII码.
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
	unsigned char ListLength;
	
	ListLength = 0;
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	while (DData[ListLength]>0x19) //若到达字串尾则退出
	{
		if (X <= 0xF) //X坐标应小于0xF
		{
			DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
			ListLength++;
			X++;
		}
	}
}

/**********************************************************
在送入地址上显示一个浮点数.
输入:地址,浮点数,小数点位数.
函数设计允许最大不超过100的浮点数,小数位数选择:0,1,2
**********************************************************/
void DisplayNumberFloat(unsigned char X, unsigned char Y,float Number,unsigned char point_number)
{
	unsigned char number_10bit;				 //用于暂存10位数据的变量
	unsigned char number_1bit;				 //用于暂存个位数据的变量
	unsigned char number_point_1;			 //用于保存第一位小数
	unsigned char number_point_2;			 //用于保存第二位小数
	unsigned int  int_number;				 //用于将输入的浮点型数字转换为整形
	

	if((Number < 100) && (point_number <= 2))
	{
		Y &= 0x1;
		X &= 0xF; 							//限制X不能大于15,Y不能大于1
		if (Y) X |= 0x40;					//当要显示第二行时地址码+0x40;
		X |= 0x80; 							//算出指令码
		WriteCommandLCM(X, 1); 				//写入地址

		switch(point_number)
		{
			case 0:
			{
				int_number = (unsigned int)Number;			//取整
				number_10bit = (int_number / 10);		   	//取商,取出第一位数字
				number_1bit  = (int_number % 10);  			//取出第二位数字
				break;
			}
			case 1:
			{
				int_number = (unsigned int)(Number * 10); 	//取整,化掉小数后一位小数
				number_10bit = (int_number / 100);		   	//取商,取出第一位数字
				number_1bit  = (int_number % 100 / 10);  	//取出第二位数字
				number_point_1 = (int_number % 10);			//取出第三位数字
				break;
			}
			case 2:
			{
				int_number = (unsigned int)(Number * 100);	//取整,化掉小数后两位小数
				number_10bit = (int_number / 1000);		   	//取商,取出第一位数字
				number_1bit  = (int_number % 1000 / 100);  	//取出第二位数字
				number_point_1  = (int_number % 100 / 10);  //取出第二位数字
				number_point_2 = (int_number % 10);			//取出第三位数字
				break;
			}
			default:break;
		}

		if(number_10bit != 0)
		{
			WriteDataLCM(number_10bit + 0x30);				//写入第一个字符
		}
		WriteDataLCM(number_1bit + 0x30);	   				//写入第二个字符
		if(point_number > 0)
		{
			WriteDataLCM(0x2E);								//写入小数点
			WriteDataLCM(number_point_1 + 0x30);	   		//写入第一位小数
		}
		if(point_number > 1)
		{
			WriteDataLCM(number_point_2 + 0x30);	   		//写入第二位小数
		}

	} 
}



//5ms延时
void Delay5Ms(void)
{
	unsigned int TempCyc = 5552;
	while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
	unsigned char TempCycA = 5;
	unsigned int TempCycB;
	while(TempCycA--)
	{
		TempCycB=7269;
		while(TempCycB--);
	};
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -