51单片机控制1602LCD输出整数和浮点数

51单片机控制1602LCD输出整数和浮点数

1.概述

1602LCD只能显示ASCLL码字符,如果我们给他输入整型类型或者浮点数类型数据让他输出,它在ASCLL码中是找不到对应的字符,因此什么都不会输出。
例如我们让LCD显示传感器采集到的数据就是一个整型或浮点型,LCD展示不了这个数据,需要我们将数据转换为char型的字符,LCD在内置的CGROM中查找ASCLL码找到对应的字符并输出。

2.整型数据转换为char字符

创建一个函数封装整型数据转char字符功能,下面对函数封装思路做个介绍

  • 首先判断数据是否为负数,如果为负数就取该数据的绝对值,转为正数;并且在str字符数组的第一个索引位置加上一个-符号,保证了负数转换完成后还是负数。
if(ld<0){
    
    
	ld = -ld; // 如果是负数则取绝对值
	*str++ = '-'; //字符串第一位先赋值一个负符号
	len++;
	}
  • 对正整数取余数拿到数据的最低一位,在拼接上'0',转为char型字符。例如123执行该语句得到最低位是3,转换为char型 '3'
  • 然后再处理下一位,ld /= 10等同于ld = ld / 10,就是让数据左移一位缩小10倍。例如123执行后左移一位是12,在下轮循环中就可以取2转为char型字符,如此循环直到所有数据转为char型。
do{
    
    
	buf[i++] = ld % 10 + '0'; // 取余运算获取最后一位,拼接上'0',转为ASCLL码
	ld /= 10; // 除以10向左移动1位
}while(ld > 0);
	len += i;
  • 上面将整型数据转为char字符是从最低位开始,逐位操作,因此得到的数据是反向的。例如 123,转换后是321.
  • 通过循环将数据逐个读出然后赋值给char型变量实现数据翻转。
while(i-- >0){
    
    
	*str++ = buf[i];
}
integerToStr函数代码
unsigned char integerToStr(long ld,unsigned char *str){
    
    
	unsigned char i;
	unsigned char len;
	unsigned char buf[11];
	if(ld<0){
    
    
		ld = -ld; // 如果是负数则取绝对值
		*str++ = '-'; //字符串第一位先赋值一个负符号
		len++;
	}
	do{
    
    
		buf[i++] = ld%10+'0'; // 取余运算获取最后一位,拼接上'0',转为ASCLL码
		ld /= 10; // 除以10向左移动1位
	}while(ld >0);
		len += i;
	while(i-- >0){
    
    
		*str++ = buf[i];
	}
	*str = '\0'; //字符串末尾加\0表示字符串的结尾
	return len;
}

完整代码
#include <STC12C2052AD.H>
#include <string.h> 
typedef unsigned char uint8;
// 定义引脚
#define	LCD1602_DB0_DB7	P1			// 定义LCD1602的数据总线
sbit LCD1602_RS = P3 ^ 2;					// 定义LCD1602的RS控制线
sbit LCD1602_RW = P3 ^ 3;					// 定义LCD1602的RW控制线
sbit LCD1602_E  = P3 ^ 4;					// 定义LCD1602的E控制线
sbit LCD1602_Busy = P1 ^ 7;					// 定义LCD1602的测忙线(与LCD1602_DB0_DB7关联)


// 定义指令集
/*设置显示模式*/
#define LCD_MODE_PIN8 0x38	// 8位数据线,两行显示
#define LCD_MODE_PIN4 0x28	// 4位数据线,两个显示
#define LCD_SCREEN_CLR 0x01	// 清屏
#define LCD_CURSOR_RET 0x02	// 光标复位
#define LCD_CURSOR_RIGHT 0x06	// 光标右移,显示不移动
#define LCD_CURSOR_LEFT 0x04	// 光标左移,显示不移动
#define LCD_DIS_MODE_LEFT 0x07 	// AC自增,画面左移
#define LCD_DIS_MODE_RIGHT 0X05	// AC自增,画面右移


/*光标开关控制*/
#define LCD_DIS_CUR_BLK_ON 0x0f	// 显示开,光标开,光标闪烁
#define LCD_DIS_CUR_ON 0x0e	// 显示开,光标开,光标不闪烁
#define LCD_DIS_ON 0x0c	// 显示开,光标关,光标不闪烁
#define LCD_DIS_OFF 0x08	// 显示关,光标关,光标不闪烁

/*光标、显示移动*/
#define LCD_CUR_MOVE_LEFT 0x10	// 光标左移
#define LCD_CUR_MOVE_RIGHT 0x14	// 光标右移
#define LCD_DIS_MOVE_LEFT 0x18	// 显示左移
#define LCD_DIS_MOVE_RIGHT 0x1c	// 显示右移


/**
LCD1602忙碌状态不会接收新指令,因此在发送新指令前先检测是否忙碌。
判断LCD1602_Busy变量的值为低电平则为不忙。
*/
void LCD1602_TestBusy(void){
    
    
	LCD1602_DB0_DB7 = 0xff;	//将数据引脚置为高电平
	LCD1602_RS = 0; // 指令状态
	LCD1602_RW = 1;	// 读状态
	LCD1602_E = 1;	// 打开LCD显示器读指令
	while(LCD1602_Busy);	//读取LCD1602_Busy(P1.7)为低电平则结束循环
	LCD1602_E = 0;	// 关闭LCD显示器读指令
}


/********************************************************************************************
// 写指令程序 //
// 向LCD1602写命令 本函数需要1个指令集的入口参数 //
/********************************************************************************************/
void LCD1602_WriteCMD(uint8 LCD1602_command) {
    
     
	LCD1602_TestBusy();
	//输入的命令赋值给LCD1602_DB0_DB7
	LCD1602_DB0_DB7 = LCD1602_command;
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_E = 1;
	LCD1602_E = 0;
}
/********************************************************************************************
// 写数据程序 //
// 向LCD1602写数据 //
/********************************************************************************************/
void LCD1602_WriteData(uint8 LCD1602_data){
    
     
	LCD1602_TestBusy();
	LCD1602_DB0_DB7 = LCD1602_data;
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_E = 1;
	LCD1602_E = 0;
}


// LCD1602初始化
void LCD1602_Init(void){
    
    
	LCD1602_WriteCMD(LCD_MODE_PIN8);	// 显示模式设置:显示2行,每个字符为5*7个像素
	LCD1602_WriteCMD(LCD_DIS_ON); 	// 显示开及光标设置:显示开,光标关
	LCD1602_WriteCMD(LCD_CURSOR_RIGHT);		//显示光标移动设置:文字不动,光标右移
	LCD1602_WriteCMD(LCD_SCREEN_CLR);	// 显示清屏
}


/*
输出字符串
x:数据地址
y:输出的行位置,第一行和第二行
str:输入字符串
*/
void print(uint8 x, uint8 y, uint8 *str){
    
    
	if(0 == y){
    
    
		LCD1602_WriteCMD(0x80 | x);
	}
	else{
    
    
		// 第二行起始位置是0x40
		LCD1602_WriteCMD(0x80 | (0x40+x));
	}
	while(*str != '\0'){
    
    
		LCD1602_WriteData(*str++);
	}

}

//整数转换为ASCLL码
unsigned char integerToStr(long ld,unsigned char *str){
    
    
	unsigned char i;
	unsigned char len;
	unsigned char buf[11];
	if(ld<0){
    
    
		ld = -ld; // 如果是负数则取绝对值
		*str++ = '-'; //字符串第一位先赋值一个负符号
		len++;
	}
	do{
    
    
		buf[i++] = ld%10+'0'; // 取余运算获取最后一位,拼接上'0',转为ASCLL码
		ld /= 10; // 除以10向左移动1位
	}while(ld >0);
		len += i;
	while(i-- >0){
    
    
		*str++ = buf[i];
	}
	*str = '\0'; //字符串末尾加\0表示字符串的结尾
	return len;
}
void main(){
    
    
	long ld = 12345678;
	unsigned char i;
	unsigned char str[11];
	LCD1602_Init();
	// 整型数据转为char字符函数
	integerToStr(ld,str);
	// ld长整型转为ASCLL码存入到str数组,输出结果
	print(0,0,str);
		
	while(1){
    
    
	}
	
}

3.浮点数转为char型字符

浮点数分为小数点位数固定和不固定两种情况,例如采集到的温度我们只取小数点后两位这就是一个小数点固定的需求。例如采集到的数据希望精度最高,那么采集到的数据小数点后面的位数每次都不一样。针对这两个场景需要分别处理。

3.1.小数点位数固定转char型字符

数据位数固定的情况下将数据按位拆分,逐位转为char型字符。

void main(){
    
    
	float fdata = 1.234;
	int temp;
	unsigned char str[11];
	LCD1602_Init();
	// 浮点数变为整数后必须先赋值给int类型,不能用float类型进行取模运算
	temp = fdata * 1000;
	
	str[0] = temp /1000 + '0';	// 获取千位数据,转为char型字符
	str[1] = '.';
	str[2] = temp/100 %10 + '0';	// 除以100得到12,然后取模运算获取到最低一位就是2,转为char型字符
	str[3] = temp /10 % 10 + '0';	// 除以10得到123,然后取模运算获取到最低一位就是3,转为char型字符
	str[4] = temp % 10 + '0';	// 取模运算获取到最低一位就是4,转为char型字符
	
	print(0,0,str);
		
	while(1){
    
    
	}
	
}

3.2.小数点位数不固定转char型字符

通过C语言自带的sprintf函数自动将字符格式化,并且可以设置不同位数的精度。

#include <stdio.h>

void main()
{
    
    
    float num = 1.234;
    unsigned char charbuf[10];
    // 将num格式化为char型字符,精度是小数点后3位
    sprintf(charbuf, "%0.3f",num);
    print(0,0,charbuf);
		
	while(1){
    
    
	}
}

猜你喜欢

转载自blog.csdn.net/m0_38039437/article/details/135017241