LCD1602显示字符、字符串、十进制、十六进制、二进制

LCD1602显示函数

LCD1602相关介绍可看这篇文章:http://t.csdn.cn/1UFRL

LCD1602.c

1.先定义端口,因为整个P0端口都是要传输的数据,这里用宏定义标识一下

#include 

sbit LCD_WR = P2^5;		//读或写
sbit LCD_RS = P2^6;		//数据或者指令
sbit LCD_EN = P2^7;		//使能

#define LCD_DATAPORT P0	

2.LCD1602写指令,按照时序结构编写

/**
  * @brief LCD1602写指令
  * @param 要写入的指令
  * @retval无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS = 0;
	LCD_WR = 0;
	LCD_DATAPORT = Command;
	LCD_EN = 1;
	Delay1ms(100);	//加延时保证EN使能正常,避免关闭使能太快而导致数据传输出问题
	LCD_EN = 0;
	Delay1ms(100);	//延时长一点的话字符会逐个显示出来,延时短的话一下子就显示出来
}

3.LCD1602写数据,将字符显示在屏幕上

/**
  * @brief LCD1602写数据
  * @param 要写入的数据
  * @retval无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS = 1;		//就这里与写指令的不同,写数据时RS是置1
	LCD_WR = 0;
	LCD_DATAPORT = Data;
	LCD_EN = 1;
	Delay1ms(100);
	LCD_EN = 0;
	Delay1ms(100);
}

4.LCD1602初始化,在main函数中使用LCD时要先调用初始化函数

/**
  * @brief LCD1602初始化
  * @param 无
  * @retval无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);		//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0C);		//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);		//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);		//清屏
}

5.检测忙信号

/**
  * @brief LCD1602检测忙信号,使用到读时序
  * @param 无
  * @retval无
  */
void Check_Busy()
{
	unsigned char temp = 0x80;
	LCD_DATAPORT = 0x80;
	/*变量初始化时让其处于忙状态,进入while循环,如果一直忙,
	则BF位一直为1,while成死循环,如果BF=0,则不忙,退出while循环,执行后续程序*/
	while(temp & 0x80)	//0x1000 0000	检测BF位
	{
		LCD_RS = 0;		//根据指令9,RS = 0
		LCD_WR = 1;		//根据指令9,RW = 1
		LCD_EN = 0;
		Delay1ms(10);
		LCD_EN = 1;
		Delay1ms(10);
		temp = LCD_DATAPORT;		//根据读数据时序图,在EN为高电平时读取数据
		LCD_EN = 0;
		Delay1ms(10);
	}
}

6.LCD1602设置光标位置函数,因为每次要显示字符都要设置在屏幕的哪个位置显示,所以写成一个函数,供其他函数调用,先检测忙信号

/**
  * @brief LCD1602设置光标位置
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @retval无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
    /*先检测忙信号,然后再设置光标位置,因为下面显示数据函数都用到设置光标函数,
	所以把检测忙信号放在这里*/
	Check_Busy();
	if(Line == 1)
	{
		LCD_WriteCommand(0x80|(Column - 1));//根据DDRAM地址表可知,第一行地址是列数减1
	}
	if(Line == 2)
	{
		LCD_WriteCommand(0x80|(Column - 1)+0x40);//第二行地址在列数减1的基础上再加上0x40
	}
}

6.LCD1602在指定的位置显示一个字符

/**
  * @brief LCD1602在指定位置上显示一个字符
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @param Data 要显示的字符
  * @retval无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Data)
{
	LCD_SetCursor(Line,Column);		//先设置显示位置
	LCD_WriteData(Data);			//再写入数据
}

7.LCD1602在指定位置上显示字符串

/**
  * @brief LCD1602在指定位置上显示字符串
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @param string 要显示的字符串
  * @retval无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *string)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i = 0;string[i] != '\0';i++)
	{
		LCD_WriteData(string[i]);
	}
}

8.LCD1602在指定位置显示十进制数字,要将数字的每一位都提取出来,然后转换为字符,才能在屏幕上显示

/**
  * @brief 求x的y次方
  * @param x 底数
  * @param y 次方数
  * @retval返回次方后的结果
  */
int Pow(int x,int y)
{
	unsigned char i;
	int result = 1;
	for(i = 0; i < y; i++)
	{
		result *= x;
	}
	return result;
}

/**
  * @brief LCD1602在指定位置上显示十进制数字
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @param number 要显示的整型数字	范围:0~65535
  * @param length 要显示的数字长度	范围:1~5
  * @retval无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int number,unsigned char length)
{
	unsigned char i;
	unsigned char temp;
	LCD_SetCursor(Line,Column);
	for(i = length ; i > 0 ; i--)
	{
		temp = number/Pow(10,i-1)%10 + '0';	//循环将每一位都提取出来并转换为字符
		LCD_WriteData(temp);
	}
}

分析一下上面LCD_ShowNum函数是如何取出十进制数的每一位并转为字符的

假如要显示的十进制数是5678,则number = 5678,length = 4,那这四位数的每一位要如何取出来呢?可用下面的方法

5:5678/1000%10

6:5678/100%10

7:5678/10%10

8:5678/1%10

可看到,变化的数是除数,第一次取数字5时是除以1000,取数字6时是除以100,取数字7时是除以10,取数字8时是除以1,那就把这个除数与 i 值联系起来找出规律就行了

除数 i值 关系
1000 4 10(4-1)
100 3 10(3-1)
10 2 10(2-1)
1 1 10(1-1)

所以这就是为什么要提前写好x的y次方的Pow函数,是为了得到上表中关系的结果,而且下面的函数也可以使用Pow函数

9.LCD1602显示有符号的十进制数字

/**
  * @brief LCD1602在指定位置上显示有符号十进制数字
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @param number 要显示的整型数字	范围:-32768~32767
  * @param length 要显示的数字长度	范围:1~5
  * @retval无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int number,unsigned char length)
{
	unsigned char i,temp;
	unsigned int numbertemp;
	LCD_SetCursor(Line,Column);
	if(number >= 0)
	{
		LCD_WriteData('+');
		numbertemp = number;
	}
	else
	{
		LCD_WriteData('-');
		numbertemp = -number;	//如果负数太大,转为正数后int型可能装不下,所以用unsigned int	
	}
	for(i = length ; i > 0 ; i--)
	{
		temp = numbertemp/Pow(10,i-1)%10 + '0';
		LCD_WriteData(temp);
	}
}

10.LCD1602显示十六进制数字

/**
  * @brief LCD1602在指定位置上显示十六进制数字
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @param number 要显示的整型数字	范围:0~0xFFFF
  * @param length 要显示的数字长度	范围:1~4
  * @retval无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int number,unsigned char length)
{
	unsigned char i;
	unsigned char temp;
	LCD_SetCursor(Line,Column);
	for(i = length ; i > 0 ; i--)
	{
		temp = number/Pow(16,i-1)%16;	//十六进制
		if(temp > 9)
		{
			LCD_WriteData(temp + 'A'-10);//当temp等于10时,而'A'本身就表示10,10+10就等于20了,所以要减去10
		}
		else
		{
			LCD_WriteData(temp + '0');
		}
	}
}

11.LCD1602显示二进制数字

/**
  * @brief LCD1602在指定位置上显示二进制数字
  * @param Line 行位置,范围:1~2
  * @param Column 列位置,范围:1~16
  * @param number 要显示的整型数字	范围:0~1111 1111 1111 1111
  * @param length 要显示的数字长度	范围:1~16
  * @retval无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int number,unsigned char length)
{
	unsigned char i;
	unsigned char temp;
	LCD_SetCursor(Line,Column);
	for(i = length ; i > 0 ; i--)
	{
		temp = number/Pow(2,i-1)%2;		//二进制
		LCD_WriteData(temp + '0');
	}
}

12.滚动效果

void main()
{
	LCD_ShowString(1,17,"hello world!");	//在屏幕外写入数据,并不在屏幕上显示
	while(1)
	{
		LCD_WriteCommand(0x18);		//写入移屏指令
		Delay1ms(500);			    //延时500m
	}
}

你可能感兴趣的:(51单片机,单片机,c语言,嵌入式硬件,学习)