//@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,增加了显示有符号浮点数函数;