IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于51单片机的简易计算器LCD显示 -> 正文阅读

[嵌入式]基于51单片机的简易计算器LCD显示

????????分享一个小作品,是根据普中单片机给的简易计算器的代码的思路自己改写的,IO口的话也能对应的上开发板的引脚,他原来给的程序是只能实现两位数差十倍的加减乘除,特别是除法的话A/B? A<B在十倍以内是准确的,我自己把它改到了100倍之内是可以实现的,并且键值进行了重新排序。?

?????????他这个实验矩阵键盘他是用逐行扫描(一位一位的赋值)的方法做的,我采用的是行列扫描(自行百度下原理),一次全部扫描完毕后再进行键值的判断。(下图)

????????键值是 (1,2,3,+,4,5,6,-,7,8,9,*,0,CLR,=,/)


proteus仿真图

?


? ? ? ? 说一下简单的原理!! 我们按下按键的第一个肯定是一个数字,接下来就是按下特殊符号了此时按下的特殊符号我们可以给他一个标志位确定按下的是哪一个符号;接下来按下的是第二个数字,如何判断是第二个数字呢,只需要判断此时特殊符号标志位是多少就可以,然后就是按下等于号,按下等于号的时候我们就可以在这个时候进行键值的整合,加减乘除带进去ok。

?????????下面介绍一下代码,也算采用的是模块化编程吧,LCD显示模块单独一个C文件,键盘和主程序放在了给main.c文件里?

? ? ? ? LCD显示模块基本就和普中实验里头的代码差不多(自己敲的)没啥注释,可以取看看普中的视频了解一下LCD驱动的编写。下面大概解释一下开始的一段代码 包括头文件

#include "reg52.h"
#include "lcd.h"
#define Key_Net ?P1uchar code number[ ]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2f-0x30 };? ? ? ?//对应的键值排列出来,因为是LCD显示等会进行处理? 自己也可以修改按键位置,就在这里,当然后面也要进行相对的修改。
uchar value;?? ??? ??? ??? ??? ??? ??? ? ?
uchar fuhao,TABE;? ? ? //fuhao 是? +,-,*,/,clr,=? ?的标识 ;TABE=?1是符?=0是数字,
float Table_A,Table_B; //Table_A,Table_B 储存输入的两个数字

LCD.H文件里面包括了宏定义什么的自己看看

?#ifndef _LCD_H
#define _LCD_H

typedef unsigned char uchar;
typedef unsigned int uint;

#define IO P0
sbit RW=P2^5;
sbit RS=P2^6;
sbit EN=P2^7;

void Lcd1602_Write_com(uchar com);
void Lcd1602_Write_dat(uchar dat);
void Lcd_Init();

#endif

下来就是完整的代码 首先是main.c文件的代码注释很全 应该能看的懂 基本都在里头说清楚了

#include "reg52.h"
#include "lcd.h"
#define Key_Net  P1
uchar code number[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2f-0x30 };
uchar value;							  
uchar fuhao,TABE;	 //fuhao 储存+,-,*,/,clr,=	;TABE 标识 1是符0是数字,Table_A,Table_B 储存输入的两个数字
float Table_A,Table_B;
long SUM,YU;
void delay10ms()   //误差 0us
{
    unsigned char a,b,c;
    for(c=5;c>0;c--)
        for(b=4;b>0;b--)
            for(a=248;a>0;a--);
}

void Init()	      //main中用到的初始化
{ 
	fuhao=0;
	TABE=0;
	Table_A=0;
	Table_B=0;

}
void Keydown()
{								  
	char a,i;
	i=0;
	Key_Net=0x0f;
	if(Key_Net!=0x0f)
	{
		delay10ms();
		if(Key_Net!= 0x0f)
		{
			Key_Net=0x0f;		  // 行列扫描 先进行列扫描,确定是那一列按下
			switch(Key_Net)
			{
				case(0x07) : value = 0 ;break; 		 //第一列 
				case(0x0b) : value = 1 ;break;		 //第二列
				case(0x0d) : value = 2 ;break;		 //第三列
				case(0x0e) : value = 3 ;break;		 //第四列
			}	
		
			Key_Net = 0xf0;
			delay10ms();
			switch(Key_Net)		   // 行列扫描 再进行行扫描,确定是那一行按下
			{
				case(0x70) : value = value+0 ;break;  //第一行 就是0 1 2 3个按键按下
				case(0xb0) : value = value+4 ;break;  //第二行
				case(0xd0) : value = value+8 ;break;  //第三行
				case(0xe0) : value = value+12 ;break; //第四行 这里确定的是哪一个按键按下,还没对按键赋值
			}
			while((a<100)&&(Key_Net!=0xf0))
			{
				delay10ms();
				a++;
			}
				a=0;
		}					
		    if((0<=value)&&(value<=2)||(4<=value)&&(value<=6)||(8<=value)&&(value<=10)||value==12)	//根据自己的键盘设计的数据这一条语句 对应的是0-9这几个数子对应的按键
			{
				TABE=0;
				if(fuhao==0)
				{
					Table_A=Table_A*10+number[value];	 //按下一位储存在个位,再按下一位原来的数*10加上刚按下的值

				}
				if((fuhao>0))
				{
					Table_B=Table_B*10+number[value];	 //当有符号位按下后面的值储存在Table_B中 

				}
					Lcd1602_Write_dat(0x30+number[value]);	//显示0-9中按下的值
			}
			
			if(value==3)  //  也就是数组number中的第三位	键盘按下+ 都可以写成SWITCH语句
			{
			  	TABE=1;
				fuhao=1;  // +号标志
				Lcd1602_Write_dat(0x30+number[value]);	  //显示+号 value==3 就是数组中的 0x2b-0x30 在LCD中0x2b就是+号
			}

			if(value==7)  //  也就是数组number中的第7位     键盘按下-	
			{
			  	TABE=1;
				fuhao=2;  // -号标志
				Lcd1602_Write_dat(0x30+number[value]);	   //同理显示-号		
			}

			if(value==11)  // 也就是数组number中的第11位   键盘按下*
			{
			  	TABE=1;
				fuhao=3;   //  *号标志
				Lcd1602_Write_dat(0x30+number[value]);	   //同理显示*号	
			}

			if(value==15)  //  键盘按下/
			{
			  	TABE=1;
				fuhao=4;   //  /号标志
				Lcd1602_Write_dat(0x30+number[value]);		//同理显示/号	
			}

			if(value==13)  //  键盘按下CLR
			{
			  	TABE=1;
				fuhao=5;   // CLR标志
				Lcd1602_Write_com(0x30+number[value]);
				fuhao=0;
				TABE=0;
				Table_A=0;
				Table_B=0;			
			}

			if(value==14) //  键盘按下= 下面直接对各种特殊符号对应的情况进行处理
			{
				if(fuhao==1)	//加法
				{	
					SUM=Table_A+Table_B;	 //计算SUM
					Lcd1602_Write_com(0Xcf); //从第二行最右边开始显示
					Lcd1602_Write_com(0X04); //控制指针左移
					while(SUM!=0)			 //一位一位显示 先从num的最低位开始
							{
								Lcd1602_Write_dat(0x30+SUM%10);		//num的最后一位在0x4f的位置也就是最右边
								SUM=SUM/10;							//再取一位的结果数据	
							}
					Lcd1602_Write_dat(0x3d);						//写等于号
				}

				if(fuhao==2)	//减法
				{	
					if(Table_A>Table_B)			//先判断A B大小 
					{
					 	SUM=Table_A - Table_B;
					}
					else
					{
						SUM=Table_B - Table_A;
					}
						Lcd1602_Write_com(0Xcf);  //从第二行最右边开始显示
						Lcd1602_Write_com(0X04);  //控制指针左移
						while(SUM!=0)	 	      //一位一位显示 先从num的最低位开始
								{
									Lcd1602_Write_dat(0x30+SUM%10);		//显示结果的最后一位在0x4f的位置
									SUM=SUM/10;							//取前面的结果数据	
								}
						if(Table_A < Table_B)	//如果A<B 在结果显示完后需要给一个负号
						{
							Lcd1602_Write_dat(0x2d);   //lcd显示负号
						}
						Lcd1602_Write_dat(0x3d);	   //写等于号
				}

				if(fuhao==3)	//乘法
				{	
					SUM=(Table_A)*(Table_B);
					Lcd1602_Write_com(0Xcf);			 //第二行最后一位显示
					Lcd1602_Write_com(0X04);			 //指针左移
					while(SUM!=0)	 		//一位一位显示
							{
								Lcd1602_Write_dat(0x30+SUM%10);		//显示结果的最后一位在0x4f的位置
								SUM=SUM/10;							//取前面的结果数据	
							}
					Lcd1602_Write_dat(0x3d);						//写等于号
				}

				if(fuhao==4)	//除法	 重点!
				{
					uchar i;
					SUM=((Table_A/Table_B)*1000);		  //sum放大1000倍	例如 sum=42/2689=0.01561919  放大1000倍 sum=15
					Lcd1602_Write_com(0Xcf);			  //lcd从第二行最后一位显示
					Lcd1602_Write_com(0X04);			  //指针左移
					if((Table_A < Table_B)&&SUM<100)	  //当两个数的值相差不到前面的数字的100倍 
					                                      //例如 42和2689 2689<4200 计算器可以算出准确结果  也可以试着自己直接改一改
					{
					while(SUM!=0)	 		//一位一位显示 例如 sum=42/2689=0.01561919  放大1000倍 sum=15
							{
								i++;
								Lcd1602_Write_dat(0x30+SUM%10);		//显示结果的最后一位在0x4f的位置
								SUM=SUM/10;							//SUM取余
								if(i==2)							//此时已经输出了15这两个数字 正确的值为0.01561919
								{
								Lcd1602_Write_dat(0x30);			//写一个0
								Lcd1602_Write_dat(0x2e);			//写小数点
								i=0;
								}				
							}
					}
					
					if(Table_A < Table_B)
					{
						Lcd1602_Write_dat(0x30);					 //上面写完小数点再写一个0 输出0.015
					}
					
					if((Table_A > Table_B))	 //A>B就没有那么多事情了 例如1589/33=48.1515  sum放大1000倍 sum=48151
					{
					while(SUM!=0)	 		//SUM*1000是保留三位小数 
							{
								i++;
								Lcd1602_Write_dat(0x30+SUM%10);		//显示结果的最后一位在0x4f的位置
								SUM=SUM/10;
								
								if(i==3)							//i=3的时候就该输出小数点了 因为小数部分已经输出完毕
								{
								Lcd1602_Write_dat(0x2e);			//输出小数点
								}
							}
					}	
					if(Table_A < Table_B)
					{
					Lcd1602_Write_dat(0x30);					   //上
					}

					Lcd1602_Write_dat(0x3d);						//最后写等于号
				
				}
			}	 

	}	
}

void main()
{
	Lcd_Init();		//初始化LCD
    while(1)
	{
	Keydown();
	}
}

接着就是LCD驱动的代码了写在了lcd.c文件中 这一部分没什么注释 可以去b站大学看看LCD驱动的编写

#include "reg52.h"
#include "lcd.h"
#include "intrins.h"

void delay1ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=199;b>0;b--)
        for(a=1;a>0;a--);
}
void delay5ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=185;b>0;b--)
        for(a=12;a>0;a--);
}

void Lcd1602_Write_com(uchar com)
{
	RW=0;
	RS=0;
	_nop_();
	EN=0;
	IO=com;	
	delay1ms();
	EN=1;
	delay5ms();
	EN=0;
}

void Lcd1602_Write_dat(uchar dat)
{
	RW=0;
	RS=1;
	_nop_();
	EN=0;
	IO=dat;	
	delay1ms();
	EN=1;
	delay5ms();
	EN=0;	
}

void Lcd_Init()
{
	Lcd1602_Write_com(0x38);
	Lcd1602_Write_com(0x0c);
	Lcd1602_Write_com(0x06);
	Lcd1602_Write_com(0x01);
	Lcd1602_Write_com(0x80);
}

接着是lcd.h文件

#ifndef _LCD_H
#define _LCD_H

typedef unsigned char uchar;
typedef unsigned int uint;

#define IO P0
sbit RW=P2^5;
sbit RS=P2^6;
sbit EN=P2^7;

void Lcd1602_Write_com(uchar com);
void Lcd1602_Write_dat(uchar dat);
void Lcd_Init();



#endif

以上就是这个小设计的全部,作为有做同样设计的一个参考,这个小程序还是不太完善,不能实现两个数字差太多倍的除法(不想弄了准备学习其他的了)还有没实现更高级的操作例如连续的加减乘除运算。。。 大家加油!

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:50:57  更:2021-09-22 14:52:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:20:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码