LCD1602显示数字,无需输入长度

//@file LCD1602.C

#include <REGX52.H>

sbit LCD_RS = P2^6;									//0输入指令,1输入数据
sbit LCD_RW = P2^5;									//0写1读
sbit LCD_EN = P2^7;									//高电平读取信号,下降沿执行指令

#define LCD_DATA_PORT	P0
#define BASE_NUM_INT	10
#define BASE_NUM_HEX	16
#define BASE_NUM_BIN	2

static uint  g_LastNum_SUN;							//用于存储显示无符号数字函数,前一次调用输入的数字的值
static int 	 g_LastNum_SN; 							//用于存储显示有符号数字函数,前一次调用输入的数字的值
static uint  g_LastNum_SHN;							//用于存储显示无符号16进制函数,前一次调用输入的数值
static uchar g_LastNum_SBN;							//用于存储显示无符号2进制函数,前一次调用输入的数值
static float g_LastNum_SFN;

/******函数声明******/
void Delay();	
void LCD_WriteCommand (uchar commandByte);
void LCD_WriteData (uchar DataByte);
void LCD_SetCursorPosition (uchar row, uchar column);
unsigned int Find_Num_Length (uint num, char functionSignal);


/**
 *@brief		LCD初始化
 *@param		无
 *@return		无
 ******************************************************************************
*/
void LCD_Init (void)
{
	LCD_WriteCommand (0x38);										//设置16*2显示,5*7点阵,8位数据接口
	LCD_WriteCommand (0x0c);										//开显示,关光标,光标不闪烁
	LCD_WriteCommand (0x06);										//读或写一个字符后地址指针加1且光标加1,写一个字符时整屏不移动
	LCD_WriteCommand (0x01);										//数据指针清零,所有显示清零
}


/**
 *@brief		LCD在指定位置显示一个字符
 *@param		row :在哪一行
				column:在那一列
				charByte :要显示的字符ASCLL码,可以直接用'A'代替码值
 *@return		无
 ******************************************************************************
*/
void LCD_ShowChar (uchar row, uchar column, uchar charByte)
{
	LCD_SetCursorPosition (row, column);
	LCD_WriteData (charByte);
}


/**
 *@brief		在指定位置起显示字符串
 *@param		row :在哪一行
				column:在那一列
				*string :字符串数组地址,也可以写string[]
 *@return		无
 ******************************************************************************
*/
void LCD_ShowString (uchar row, uchar column, uchar *string)
{
	uchar i;
	LCD_SetCursorPosition (row, column);						
	for (i = 0; string[i] != '\0'; i++)
	{
		LCD_WriteData ( string[i] );
	}
}


/**
 *@brief		在指定位置显示无符号数字
 *@param		row :在哪一行
				column:在那一列
				num:要显示的无符号数字,范围:0-65535
 *@return		无
 ***************************************************************************************
*/
void LCD_ShowUnsignedNum (uchar row, uchar column, uint num)
{
	uint nowNumLength;			
	uint lastNumLength;		
	
	/******把上一次调用此函数显示的数字先用空格顶掉******/												
	lastNumLength = Find_Num_Length (g_LastNum_SUN, 'D');								//找的是上一次调用此函数传入的num长度
	LCD_SetCursorPosition (row, column);
	for (lastNumLength; lastNumLength > 0; lastNumLength /= 10)
	{
		LCD_WriteData (' ');
	}
	g_LastNum_SUN = num;																//存储本次输入的num值到全局变量中						
											
	/******输出本次要显示的数据******/
	LCD_SetCursorPosition (row, column);
	nowNumLength = Find_Num_Length (num, 'D');											//找的是本次输入的num的长度
	for (nowNumLength; nowNumLength > 0; nowNumLength /= 10)
	{
		LCD_WriteData ('0' + (num / nowNumLength) % 10);
	}
}


/**
 *@brief		在指定位置显示有符号数字
 *@param		row :在哪一行
				column:在那一列
				num:要显示的无符号数字,范围:-32768~32767
 *@return		无
 ***************************************************************************************
*/
void LCD_ShowSignedNum (uchar row, uchar column, int num)
{
	uint nowNumLength;		
	uint lastNumLength;	
	uint storeTransNum;																	//接收前一个输入数字的绝对值,用于取长度
	
	/******把上一次调用此函数显示的数字先用空格顶掉******/
	storeTransNum = g_LastNum_SN >=0 ? g_LastNum_SN : g_LastNum_SN * (-1);
	lastNumLength = Find_Num_Length (storeTransNum, 'D');//找的是前一个数字变绝对值后的长度
	if (g_LastNum_SN >= 0)
	{
		LCD_SetCursorPosition (row, column);
		for (lastNumLength; lastNumLength > 0; lastNumLength /= 10)
		{
			LCD_WriteData (' ');
		}
	}
	else
	{
		LCD_SetCursorPosition (row, column);
		for (lastNumLength; lastNumLength > 0; lastNumLength /= 10)
		{
			LCD_WriteData (' ');
		}
		LCD_WriteData (' ');														//假如是-356,上个函数空格覆盖-35,这条语句覆盖6
	}
	g_LastNum_SN = num;																//存前一个数字,带正负
	
	/******输出本次要显示的数据******/
	if (num >= 0)
	{
		nowNumLength = Find_Num_Length (num, 'D');									//找的是本次输入的数字的长度
		LCD_SetCursorPosition (row, column);
		for (nowNumLength; nowNumLength > 0; nowNumLength /= 10)
		{
			LCD_WriteData ('0' + (num / nowNumLength) % 10);
		}
	}
	else
	{
		num *= -1;
		nowNumLength = Find_Num_Length (num, 'D');
		LCD_SetCursorPosition (row, column);
		LCD_WriteData ('-');
		for (nowNumLength; nowNumLength > 0; nowNumLength /= 10)
		{
			LCD_WriteData ('0' + (num / nowNumLength) % 10);
		}
	}
}


/**
 *@brief		在指定位置显示16进制数
 *@param		row :在哪一行
				column:在那一列
				num:要显示的16进制数,范围:0~0xffff
 *@return		无
 ***************************************************************************************
 **/
void LCD_ShowHexNum (uchar row, uchar column, uint num)
{
	uint nowNumLength;			
	uint lastNumLength;	
	
	/******把上一次调用此函数显示的数字先用空格顶掉******/	
	LCD_SetCursorPosition (row, column);	
	lastNumLength = Find_Num_Length (g_LastNum_SHN, 'H');
	for (lastNumLength; lastNumLength > 0; lastNumLength /= 16)
	{
		LCD_WriteData (' ');
	}
	g_LastNum_SHN = num;
	
	/******显示本次的数据******/
	LCD_SetCursorPosition (row, column);
	nowNumLength = Find_Num_Length (num, 'H');
	for (nowNumLength; nowNumLength > 0; nowNumLength /= 16)
	{
		if ((num / nowNumLength) % 16 < 10)											//区分16进制数字显示和字母显示
		{
			LCD_WriteData ('0' + (num / nowNumLength) % 16);
		}
		else
		{
			LCD_WriteData ('A' + (num / nowNumLength) % 16 - 10);
		}
	}	
}


/**
 *@brief		在指定位置开始显示二进制数据
 *@param		row :在哪一行
				column:在那一列
				num:要显示的二进制数,范围:0~0xff
 *@return		无
 ***************************************************************************************
*/
void LCD_ShowBinNum (uchar row, uchar column, uchar num)
{
	uint nowNumLength;			
	uint lastNumLength;	
	
	/******把上一次调用此函数显示的数字先用空格顶掉******/	
	LCD_SetCursorPosition (row, column);
	/*	
	lastNumLength = Find_Num_Length (g_LastNum_SBN, 'B');
	for (lastNumLength; lastNumLength > 0; lastNumLength /= 2)
	{
		LCD_WriteData (' ');
	}
	*/
	for (lastNumLength = 128; lastNumLength > 0; lastNumLength /= 2)					//这样2进制全显示
	{
		LCD_WriteData (' ');
	}	
	
	/******显示本次的数据******/
	LCD_SetCursorPosition (row, column);
	/*
	nowNumLength = Find_Num_Length (num, 'B');
	for (nowNumLength; nowNumLength > 0; nowNumLength /= 2)
	{
		LCD_WriteData ('0' + (num / nowNumLength) % 2);
	}
	*/
	for (nowNumLength = 128; nowNumLength > 0; nowNumLength /= 2)
	{
		LCD_WriteData ('0' + (num / nowNumLength) % 2);
	}
}

/**
 *@brief		显示有符号float类型数据
 *@param		row :在哪一行
				column:在那一列
				num:要显示浮点数,范围:-65535f = +65535f
 *@return		无
 ***************************************************************************************
 **/
void LCD_ShowFloatNum (uchar row, uchar column, float num)
{
	char i;	
	uint nowNumLength_I;												//整数部分位数
	uint nowNumLength_F = 10000;			   							//默认4位小数,例如0.0625*10000 == 0625
	uint lastNumLength;	
	uint interPart;														//整数部分
	uint floatPart;														//小数部分

	/******把上一次调用此函数显示的数字先用空格顶掉******/	
	i = g_LastNum_SFN < 0 ? 7 : 6;										//负数多循环一次覆盖符号-
	g_LastNum_SBN = i == 6 ? g_LastNum_SBN : (g_LastNum_SBN * -1);		//负数取绝对值
	lastNumLength =  Find_Num_Length ( (uint)(g_LastNum_SBN), 'D' );	
	LCD_SetCursorPosition (row, column);
	for (lastNumLength; lastNumLength > 0; lastNumLength /= 10)
	{
		LCD_WriteData (' ');
	}
	for (i; i > 1; i--)
	{
		LCD_WriteData (' ');
	}
	g_LastNum_SFN = num;
	
	/******显示本次的数据******/
	if (num < 0)
	{
		num *= -1;
		LCD_SetCursorPosition (row, column);
		LCD_WriteData ('-');	
	}
	else
	{
		LCD_SetCursorPosition (row, column);
	}
	interPart = (uint)num ;
	nowNumLength_I = Find_Num_Length (interPart, 'D');
	for (nowNumLength_I; nowNumLength_I > 0; nowNumLength_I /= 10)
	{
		LCD_WriteData ('0' + (interPart / nowNumLength_I) % 10);
	}
	LCD_WriteData ('.');
	floatPart = (uint) ( (num - interPart) * nowNumLength_F );
	for (nowNumLength_F = 1000; nowNumLength_F > 0; nowNumLength_F /= 10)
	{
		LCD_WriteData ('0' + (floatPart / nowNumLength_F) % 10);
	}	
}




/**************************************************文件内调用的函数***************************************************************************************/
/**
 *@brief		LCD独有的延迟函数
 *@param		无
 *@return		无
 ******************************************************************************
*/
void Delay()										//@11.0592MHz,1ms
{
	unsigned char i, j;
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}


/**
 *@brief		写指令的时序结构
 *@param		commandByte :指令字节数据
 *@return		无
 ******************************************************************************
*/
void LCD_WriteCommand (uchar commandByte)
{
	LCD_RS = 0;
	LCD_RW = 0;
	LCD_DATA_PORT = commandByte;
	LCD_EN = 1;
	Delay();
	LCD_EN = 0;
	Delay();
}


/**
 *@brief		写数据的时序结构
 *@param		DataByte :数据字节
 *@return		无
 ******************************************************************************
*/
void LCD_WriteData (uchar DataByte)
{
	LCD_RS = 1;
	LCD_RW = 0;
	LCD_DATA_PORT = DataByte;
	LCD_EN = 1;
	Delay();
	LCD_EN = 0;
	Delay();
}


/**
 *@brief		设置光标位置(设置AC)
 *@param		row :在哪一行
				column:在那一列
				charByte :要显示的字符ASCLL码,可以直接用'A'代替码值	
 *@return		无
 ******************************************************************************
*/
void LCD_SetCursorPosition (uchar row, uchar column)
{
	if (row == 1)
	{
		LCD_WriteCommand ( 0x80 | (column - 1) );
	}
	else
	{
		LCD_WriteCommand ( ( 0x80 | (column - 1) ) + 0x40 );
	}
}


/**
 *@brief		判断{10进制int类型数,16进制unsigned int类型数,2进制unsigend char类型数}的长度
				比如4596 / 1000 % 10 = 4,它的长度就是1000
				比如0XF2B2 / 4096 % 16 = F,它的长度就是4096,占4位LCD
				比如1111_1011B / 256 % 16 = 1,它的长度用256表示,占8位
 *@param		uint num:要判断的数据,范围:0~65535
 *@return		length:得到的长度
 ******************************************************************************
 **/
unsigned int Find_Num_Length (uint num, char functionSignal)
{
	uint length;
	uint base;

	if (functionSignal == 'D')												//判断那个函数调用此函数
	{ 
		length = 10000;
		base = BASE_NUM_INT;
	}
	else if (functionSignal == 'H')
	{
		length = 4096;
		base = BASE_NUM_HEX;
	}
	else if (functionSignal == 'B')
	{
		length = 128;
		base = BASE_NUM_BIN;
	}

	for (length; length > 0; length /= base)								//取长度
	{
		if (num == 0)
		{
			length = 1;
			break;
		}
		else if (num / length != 0)
		{
			break;
		}
	}
	return length;
}
//@file LCD1602.H

#ifndef _LCD1602_H_
#define _LCD1602_H_

//用户调用函数
void LCD_Init (void);
void LCD_WriteCommand (uchar commandByte);
void LCD_ShowChar (uchar row, uchar column, uchar charByte);						//如果要显示°(0xdf)等特殊符号,需要查手册上CGROM的ASCLL表
void LCD_ShowString (uchar row, uchar column, uchar *string);
void LCD_ShowUnsignedNum (uchar row, uchar column, uint num);
void LCD_ShowSignedNum (uchar row, uchar column, int num);
void LCD_ShowHexNum (uchar row, uchar column, uint num);							//使用方法:num直接输入16进制数,例如0xaa,或者输入存储16进制的变量
void LCD_ShowBinNum (uchar row, uchar column, uchar num);							//使用方法:num直接输入16进制数,例如0xaa,或者输入存储16进制的变量
void LCD_ShowFloatNum (uchar row, uchar column, float num);
	
#endif

1,,改了一下B站UP主江科技的LCD1602功能函数代码,主要改了显示有符号/无符号数字、显示16进制数、显示2进制数,只需要给3个参(行,列,数据),而不需要再给数字长度;

2,增加了显示有符号浮点数函数;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值