用51单片机、8255、138、373等实现数码管显示按键数值的程序
51单片机数字显示

单片机数字显示
本例程给您展示一个很简单的数码管显示!
虽然这是个没有什么技术含量的,但绝对对初学者是个很好的提示作用。
在你懂得了这个以后,您就可以做出更多好的作品出来。
先把硬件图给出:
他的工作过程就是,在数码管的第一位显示数字从0~9依次显示完,然后在从数码管的第二、第三、第四位重复以上动作。
以下是程序:
#include<reg52.h>
#define uchar unsigned char
uchar a[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数字的代码段数组
uchar b[]={1,2,4,8};//数码管位选数组
void delay(uchar a);//延时函数
void main()
{
uchar i,n;
while(1)
{
for(i=0;i<=3;i++)
{
P2=b[i];
for(n=0;n<=9;n++)
{
P0=a[n];
delay(200);
}
}
}
}
void delay(uchar a)
{
uchar x,y;
for(x=0;x<=a;x++)
for(y=0;y<=a;y++);
}
用Protues 7.7仿真软件的显示效果图:
第一位显示
第二位显示
第三位显示
第四位显示。
51单片机数码管显示计算器程序

定义位变量 定义液主函数 *51 单片机数码管显示计算器程序计算器程序#include<reg52.h>#include <intrins.h>#include<string.h> #include <math.h>#include <stdio.h>#define uchar unsigned char #define uint unsigned int ucharkey,sym,sumsz[13],adders=0; // 定义变量float sum,number1=0,number2=0; // 定义变量 bit flag=0; //标志位 sbit lcdrs=P2A 5; // 定义液晶的读 10 口 sbit lcdwr=P2W; // 晶的写I0 口 sbit lcden=P2A7; // 定义液晶的使能I0 口 uchar lcd_s[]={'0','1','2','3','4','5','6','7','8','9','+','-','*',0xfd,'.','='};//void keyscan(); // 函数声明void delayms(uchar z);void write_com(uchar com); void write_data(uchar dat); void init(); void delay(int z); bit buzz(); void yuans();void clear();/***********************void main()init(); // 液晶初始化while(1) // 循环函数keyscan(); // 调用键盘扫描函数键盘扫面*************************/ void keyscan()uchar temp=0;P1=0xfe; // 第1 次判断函数temp=P1;temp=temp&0xf0;if(temp!=0xf0)delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; // 确定按键按下,执行if 函数switch(temp)case 0xee:key=1;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;// 显示字符1,并记入相加的变量case 0xde:key=2;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;// 显示字符2,并记入相加的变量case 0xbe:key=3;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;// 显示字符3,并记入相加的变量case 0x7e: key=10;write_data(lcd_s[key]);sym='+';flag=1; break;// 示‘+'号,并将sym付‘ +'}while((P1&0xf0)!=0xf0); // 等待按键释放}}P1=0xfd; // 第2 次判断temp=P1;temp=temp&0xf0;if(temp!=0xf0){delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; // 确定按键按下,执行if 函数switch(temp){case 0xed:key=4;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key; break;// 显示字符4,并记入相加的变量case 0xdd:key=5;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key; break;// 显示字符5,并记入相加的变量case 0xbd:key=6;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break; // 显示字符6,并记入相加的变量case 0x7d: key=11;write_data(lcd_s[key]);sym='-';flag=1; break;//示‘-'号,并将sym付‘-'}while((P1&0xf0)!=0xf0);}}P1=0xfb; // 第3 次判断temp=P1;temp=temp&0xf0;if(temp!=0xf0)delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; // 确定按键按下,执行if 函数switch(temp){case 0xeb:key=7;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key; break;// 显示字符7,并记入相加的变量case 0xdb:key=8;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key; break;// 显示字符8,并记入相加的变量case 0xbb:key=9;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break; // 显示字符9,并记入相加的变量case 0x7b: key=12;write_data(lcd_s[key]);sym='*';flag=1; break;//示‘ * '号,并将sym付‘ *'}while((P1&0xf0)!=0xf0); // 等待按键释放}P1=0xf7; // 第4 次判断temp=P1;temp=temp&0xf0;if(temp!=0xf0){delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; // 确定按键按下,执行if 函数switch(temp){case 0xe7: key=0;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} elsenumber2=number2*10+key;break;// 显示字符0,并记入相加的变量case 0xd7: key=14;clear(); break;// 调用清零函数case 0xb7: key=15;yuans();flag=1;adders--;break;// 调用运算函数case 0x77: key=13;write_data(lcd_s[key]);sym='/';flag=1; break;//示‘/ '号,并将sym付‘ /'}液晶写数据程序 { while((P1&0xf0)!=0xf0); // 等待按键释放液晶****************************/void write_com(uchar com) //液晶写指令程序{while(buzz()) ; lcdrs=0; // lcdwr=0; // lcden=0;P0=com; // _nop_();_nop_();_nop_();_nop_();lcden=1; // _nop_();_nop_();_nop_();_nop_();lcden=0; // void write_data(uchardat) // while(buzz());lcdrs = 1;液晶初始化程序 {lcdwr = 0;lcden = 0; P0 = dat; _nop_(); _nop_(); _nop_(); _nop_(); lcden = 1; _nop_(); _nop_(); _nop_(); _nop_(); lcden = 0;} void init() // lcden=0; // write_com(0x38); // write_com(0x0c); // write_com(0x06); // write_com(0x01); // } bit buzz() // 液晶测忙程序 { bit b; lcdwr=1; // lcdrs=0; //延时子程序 {延时函数 lcden=1;_nop_();_nop_();_nop_();_nop_();b=(bit)(P&0x80);lcden=0;return b;void delay(int z) // int i;while(z--){for(i = 0; i< 250; i++){_nop_();_nop_();_nop_();_nop_();}}}/********************* voiddelayms(uchar z) // 延时毫秒程序 {运算程序uchar i,j;for(i=z;i>0;i--) for(j=110;j>0;j--); }void clear() // 清零程序{ uchar i;for(i=0;i<16;i++) // 对液晶写入空格 { write_com(0x80+i);write_data(' ');}for(i=0;i<15;i++){write_com(0x80+0x40+i);write_data(' ');}write_data('0');write_com(0x80);flag=0;number1=0;number2=0;adders=0; // 将数据变量清零}void yuans() // 运算函数 { uchar i,j,temp1; /*********************** 运算*********************************/ /******************** 清零函数******************************************* */两数相加两数相减两数相乘两数相除 switch(sym){ case '+':number1+=number2;break; // case '-':number1-=number2;break; // case '*':number1*=number2;break; //case '/':number1/=number2;break; // }sprintf(sumsz,"%10.2f",number1); // j=strlen(sumsz); write_com(0x80+0x40+16-j); for(i=0;i<j;i++) // 显示结果 { temp1=sumsz[i];write_data(temp1);delay(10);}number2=0; write_com(0x80+adders-1); }。
51单片机数码管的程序代码

wei=1; P0=WM[x]; //取位码 wei=0; delay(5); // 扫描间隙延时,时间太长会闪烁,太短会造成重影
x++;y++; if(4==x) //检测 4 位扫描完全结束?如扫描完成则从第一个开始再次扫描 8 位
x=0; if(y==400) //检测当前数值显示了一小段时间后,需要显示的数值加 1,实现数据 显示的变化 {
y=0; num++; if(num==13)
num=0; } } }
void delay(unsigned int sm) {
for(i=sm;i>0;i--) for(j=70;j>0;j--); }
void main () {
P0=0x00; line =0; P0=0xff; led=0;
wei=1; P0=0x7f; wei=0;
while (1) {
for (a=0;a<10;a++) {
duan=1; P0=table[a]; duan=0; delay (500); } }
} void delay (uint s) {
/*串口初始化,波特率 9600,方式 1 */ void init_com() { TMOD=0x20; //设置定时器 1 为模式 2 TH1=0xfd; //装初值设定波特率 TL1=0xfd;
TR1=1; SM0=0; SM1=1; PCON=0;
//启动定时器 //串口通信模式设置
//波特率不倍频
//段选
unsigned char code table []=
基于MCS51系列单片机实现键盘按键与数字动态显示计数器课程设计

毕业设计论文摘要单片机自20世纪70年代问世以来,以其极高的性能价格比,受到人们的重视和关注,应用很广、发展很快。
而51单片机是各单片机中最为典型和最有代表性的一种。
本实验是基于MCS51系列单片机所设计的,可以实现键盘按键与数字动态显示并可以用音乐倒数的计数器。
本设计基于单片机技术原理,以单片机芯片AT89C51作为核心控制器,通过硬件电路的制作以及软件程序的编制,设计制作出一个计数器,包括以下功能:输出时间,按下键就开始计时,并将时间显示在LCD1602显示器上。
当倒计数为0时,蜂鸣器就发出音乐声响等等。
该计数器系统主要由计数器模块、LCD显示器模块、蜂鸣器模块、键盘模块、复位模块等部分组成。
关键词:AT89C51、键盘、LCD1602显示、蜂鸣器目录摘要 (I)1 项目概述和要求 (1)1.1 单片机基础知识 (1)1.2 单片机的发展趋势 (1)1.3 项目设计任务与要求 (3)2 系统设计 (4)2.1 框图设计 (4)2.2部分硬件方案论述 (4)2.3电路原理图 (4)2.4元件清单 (5)2.4.1AT89C51芯片 (5)2.4.2字符型LCD1602 (6)2.4.3按键控制模块 (8)2.4.4其它元件 (8)3软件设计 (9)3.1 程序流程图 (9)3.2 程序关键问题的部分代码 (11)4 系统的仿真与调试 (16)4.1 硬件调试 (16)4.2 软件调试 (16)4.3 软硬件调试 (16)5总结 (17)参考文献 (18)1 项目概述和要求1.1 单片机基础知识单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
概括的讲,一块芯片就成了一台计算机。
单片机具有体积小、功能强、应用面广等优点,目前正以前所未见的速度取代着传统电子线路构成的经典系统,蚕食着传统数字电路与模拟电路固有的领地。
它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。
51单片机数码管显示数字原理

主题:51单片机数码管显示数字原理内容:1. 介绍51单片机在现代的电子产品中,单片机被广泛应用于各个领域,它是一种集成了微处理器、存储器和输入/输出端口的集成电路芯片。
其中,51单片机即指的是基于Intel 8051架构的单片机,它具有低功耗、高性能和丰富的外设接口,因此被广泛应用于嵌入式系统设计中。
2. 数码管的基本原理数码管是一种能够显示数字和部分字母的显示器件,它由多个发光二极管组成,可以显示0-9的数字。
数码管按照结构可以分为共阳数码管和共阳数码管两种类型。
共阳数码管的显示原理是通过控制各个发光二极管的通断状态来显示不同的数字,而共阴数码管则是通过控制对应的极性来实现数字的显示。
3. 51单片机连接数码管的原理通过51单片机控制数码管显示数字,需要用到引脚的输出功能。
在连接共阳数码管时,需要通过51单片机的输出引脚控制各个发光二极管的状态;而在连接共阴数码管时,则是通过控制对应的极性来实现数字的显示。
4. 51单片机连接数码管的实现步骤由于51单片机有多个通用IO口,因此可以连接多个数码管。
连接数码管的步骤如下:1)确定数码管的类型,共阴还是共阳2)连接数码管的正极和负极到单片机的对应IO口3)编写程序控制51单片机的IO口输出状态,以显示所需的数字5. 51单片机连接数码管的程序设计下面是一个简单的示例程序,演示了如何使用51单片机连接数码管,并控制其显示数字的过程:```C#include <reg51.h>sbit DIG1 = P0^0; // 数码管第一位sbit DIG2 = P0^1; // 数码管第二位sbit DIG3 = P0^2; // 数码管第三位sbit DIG4 = P0^3; // 数码管第四位void m本人n(){unsigned char DisplayData[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 0-9的显示码unsigned char i;while(1){for(i=0; i<10; i++){DIG1=0; // 打开第一位数码管P2=DisplayData[i]; // 发送段码delay(100); // 延时DIG1=1; // 关闭第一位数码管// 同样的方法依次打开其他位数码管并发送段码// 这里省略其他三个数码管的控制}}}通过以上程序设计,我们可以实现用51单片机控制数码管显示0-9的数字。
51单片机静态数码管显示数字程序

{
Delay10ms();
i++;
}
i=0;
} if(K2==0)
//检测按键 K2 是否按下
{
Delay10ms();
if(K2==0)
{
j=9;
}
while((i<50)&&(K2==0))
{
Delay10ms();
i++;
}
i=0;
} if(K3==0)
//检测按键 K3 是否按下
{
Delay10ms();
for(b=38;b>0;b--)
for(a=130;a>0;a--); }
//2222222222222222222222222222222222222222222222222222222222222222
//2222222222222222222222222222222222222222222222222222222222222222
//1111111111111111111111111111111111111111111111111111111111111111111
//1111111111111111111111111111111111111111111111111111111111111111111
/******************************************************************************
void Delay10ms(); //延时 10ms
/******************************************************************************
单片机控制数码管显示1-100程序

//此函数实现对数码管的控制显示个十百位数#include <reg52.h>#define uint unsigned int#define uchar unsigned charsbit duan=P2^6;//七段选择sbit wei=P2^7;//片选,选择哪个数码管uchar aa,bai,shi,ge,temp;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void init();void delay(uint);void display(uchar bai,uchar shi,uchar ge);void main(){init();//调用初始化函数,定时器0初始化,中断开启while(1){if(aa>=20){aa=0;temp++;if(temp==100){ temp=0;}bai=temp/100;//百位shi=temp%100/10;//十位ge=temp%10;//个位}display(bai,shi,ge);}}void delay(uint k){uint i;uchar j;for(i=k;i>0;i--)for(j=110;j>0;j--);}//显示子函数void display(uchar bai,uchar shi,uchar ge){//显示百位duan=1;P0=table[bai];duan=0;P0=0xff; //消影,下一步位选开启时,瞬间传入的是前面的P0值,所以后3个数码管有乱码wei=1;P0=0xfe;//6片全选wei=0;delay(1);//显示十位duan=1;P0=table[shi];duan=0;P0=0xff;//消影,下一步位选开启时,瞬间传入的是前面的P0值,所以后3个数码管有乱码wei=1;P0=0xfd;wei=0;delay(1);//显示个位duan=1;P0=table[ge];duan=0;P0=0xff;//消影,下一步位选开启时,瞬间传入的是前面的P0值,所以后3个数码管有乱码wei=1;P0=0xfb;wei=0;delay(1);}/*void display() {if(aa>=20){aa=0;ge++;duan=1;P0=table[ge];duan=0;wei=1;P0=0xfd;wei=0;if(ge>=10){ge=0;shi++;duan=1;P0=table[shi];duan=0;wei=1;P0=0xfe;wei=0;}if(shi>=6){shi=0;}}}*/void init(){duan=0;wei=0;temp=0;TMOD=0x01;TH0=(65536-50000)/256; //定时器装初值50ms TL0=(65536-50000)%256;EA=1;//开总中断ET0=1;//开定时器0中断TR0=1;//启动定时器0;使TR0置位=1,定时器0开始计数;停止时,使TR0=0复位;}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;aa++;}。
51单片机数码管显示程序设计

练习3主程序参考:
ORG 0000H LJMP START ORG 000BH LJMP T0SERV ;T0中断入口 ORG 0030H START: MOV SP,#50H ;初始化堆栈 LCALL INIT ;初始化 MOV DISBUF,#0 MOV DISBUF+1,#1 MOV DISBUF+2,#2 MOV DISBUF+3,#3 MOV DISBUF+4,#4 MOV DISBUF+5,#0 MOV FLASH,#11000000B MOV R0,#0 LOOP: MOV DISBUF+5,R0 LCALL DELAY INC R0 CJNE R0,#10,LOOP MOV R0,#0 AJMP LOOP
恢复现场
返回
动态显示参考程序1:定义变量
;--------------------------------------------------------;动态显示程序 ;--------------------------------------------------------;全局变量定义 FLAG EQU 20H ;标志位 DISSEG EQU P0 ;显示段驱动 DISBIT EQU P2 ;显示位驱动P2.7-P2.2 DISBUF EQU 21H ;显示缓冲区首地址21H-26H DISBITBUF EQU 27H ;当前显示位计数器0-5 FLASH EQU 28H ;闪烁控制xxxxxx00,将x=1闪烁,=0不闪 ;小数点的处理: ;若显示‘3’,缓冲区放‘3’,若显示‘3.’,缓冲区放‘3+80H’, 最高位为1 S_PULSE EQU FLAG.0 ;秒脉冲 CNT_2D5MS EQU 2FH ;2.5MS计数器 CNT_10MS1 EQU 30H ;10MS计数器 CN_0D5S EQU 31H ;0.5秒计数器 ;----------------------------------------------------------
51单片机(四位数码管的显示)程序

51单片机(四位数码管的显示)程序基于单片机V1或V2实验系统,编写一个程序,实现以下功能:1)首先在数码管上显示“P_ _ _”4个字符;2)等待按键,如按了任何一个键,则将这4个字符清除,改为显示“0000”4个字符(为数字的0)。
最佳答案下面这个程序是4x4距阵键盘,LED数码管显示,一共可以到0-F显示,你可以稍微改一下就可以实现你的功能了,如还有问题请发信息,希望能帮上你!#include<at89x52.h>unsigned char codeDig[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1 ,0x86,0x8e}; //gongyang数码管0-F 代码unsigned char k; //设置全局变量k 为键盘的键值/************************************键盘延时函数****************************/void key_delay(void) //延时函数{int t;for(t=0;t<500;t++);}/************************************键盘扫描函数******************************/void keyscan(void) //键盘扫描函数{unsigned char a;P2 = 0xf0; //键盘初始化if(P2!=0xf0) //有键按下?{key_delay(); //延时if(P2!=0xf0) //确认真的有键按下?{P2 = 0xfe; //使行线P2.4为低电平,其余行为高电平key_delay();a = P2; //a作为缓存switch (a) //开始执行行列扫描{case 0xee:k=15;break;case 0xde:k=11;break;case 0xbe:k=7;break;case 0x7e:k=3;break;default:P2 = 0xfd; //使行线P2.5为低电平,其余行为高电平a = P2;switch (a){case 0xed:k=14;break;case 0xdd:k=10;break;case 0xbd:k=6;break;case 0x7d:k=2;break;default:P2 = 0xfb; //使行线P2.6为低电平,其余行为高电平a = P2;switch (a){case 0xeb:k=13;break;case 0xdb:k=9;break;case 0xbb:k=5;break;case 0x7b:k=1;break;default:P2 = 0xf7; //使行线P2.7为低电平,其余行为高电平a = P2;switch (a){case 0xe7:k=12;break;case 0xd7:k=8;break;case 0xb7:k=4;break;case 0x77:k=0;break;default:break;}}}break;}}}}/****************************** ***主函数*************************************/ void main(void){while(1){keyscan(); //调用键盘扫描函数switch(k) //查找按键对应的数码管显示代码{case 0:P0=Dig[0];break;case 1:P0=Dig[1];break;case 2:P0=Dig[2];break;case 3:P0=Dig[3];break;case 4:P0=Dig[4];break;case 5:P0=Dig[5];break;case 6:P0=Dig[6];break;case 7:P0=Dig[7];break;case 8:P0=Dig[8];break;case 9:P0=Dig[9];break;case 10:P0=Dig[10];break;case 11:P0=Dig[11];break;case 12:P0=Dig[12];break;case 13:P0=Dig[13];break;case 14:P0=Dig[14];break;case 15:P0=Dig[15];break;default:break; //退出}}}/**********************************end***************************************/。
8255控制数码管、单片机程序

8255 管脚图下面是8255 管脚设置,具体代码要看原理图中各管脚的连接情况。
reset = 0; 禁止复位cs = 0;wr = 0;//允许CPU将数据或控制字写入8255//A1=1.A0=1;选择.控制寄存器//假设00001111控制D口的数据,从A口输出;11110000控制D口的数据,从B口输出;实际情况由实际管脚连接决定。
d0 = d1=d2= d3=0;d4 = d5=d6=d7 = 1;A1=0;A0=0;选择PA口//pa口--数码管的段选//根据原理图设置pa口各引脚,假设使pa输出00000001控制第1个数码管pa0 = pa1=pa2=pa3=pa4=pa5=pa6= 0;pa7 = 1;A1=0;A0=1;选择PB口//PB口--数码管的位选//根据原理图设置pb口各引脚,假设使pb输出00000001控制数码管显示0 pa0 = pa1=pa2=pa3=pa4=pa5=pa6= 0;pa7 = 1;//=========A1=1.A0=1;选择.控制寄存器//假设00001111控制D口的数据,从A口输出;11110000控制D口的数据,从B口输出;实际情况由实际管脚连接决定。
d0 = d1=d2= d3=1;d4 = d5=d6=d7 = 0;A1=0;A0=0;选择PA口//pa口--数码管的段选//根据原理图设置pa口各引脚,假设使pa输出00000010控制第2个数码管pa0 = pa1=pa2=pa3=pa4=pa5=pa7= 0;pa6 = 1;A1=0;A0=1;选择PB口//PB口--数码管的位选//根据原理图设置pb口各引脚,假设使pb输出00000001控制数码管显示0 pa0 = pa1=pa2=pa3=pa4=pa5=pa6= 0;pa7 = 1;。
利用8255和51单片机实现数码管显示按键值的实验

三个附加的控制端、和。当、时,输出为高电平(S=1),译码器处 于工作状态。否则,译码器被禁止,所有的输出端被封锁在高电平, 如表 3.3.5 所示。这三个控制端也叫做“片选”输入端,利用片选的作 用可以将多篇连接起来以扩展译码器的功能。 带控制输入端的译码 器又是一个完整的数据分配器。在图 3.3.8 电路中如果把作为“数据” 输入端(同时),而将作为“地址”输入端,那么从送来的数据只能通 过所指定的一根输出线送出去。这就不难理解为什么把叫做地址输入 了。例如当=101 时,门的输入端除了接至输出端的一个以外全是高 电平,因此的数据以反码的形式从输出,而不会被送到其他任何一个 输出端上。 【例 3.3.2】 试用两片 3 线-8 线译码器 74LS138 组成 4 线-16 线译码器,将输入的 4 位二进制代码译成 16 个独立的低电平 信号。 解:由图 3.3.8 可见,74LS138 仅有 3 个地址输入端。如果 想对 4 位二进制代码,只能利用一个附加控制端(当中的一个)作为 第四个地址输入端。 取第(1)片 74LS138 的和作为它的第四个地 址输入端(同时令),取第(2)片的作为它的第四个地址输入端(同 时令),取两片的、、,并将第(1)片的和接至,将第(2)片的接至, 如图 3.3.9 所示,于是得到两片 74LS138 的输出分别为 图 3.3.9 用 两片 74LS138 接成的 4 线-16 线译码器 式(3.3.8)表明时第(1) 片 74LS138 工作而第(2)片 74LS138 禁止,将的 0000~0111 这 8 个代码译成 8 个低电平信号。而式(3.3.9)表明时,第(2)片 74LS138 工作,第(1)片 74LS138 禁止,将的 1000~1111 这 8 个代码译成 8 个低电平信号。这样就用两个 3 线-8 线译码器扩展成一个 4 线-
51单片机数码管显示计算器程序

51单片机数码管显示计算器程序/***************************计算器程序***********************************/#include<reg52.h>#include <intrins.h>#include<string.h>#include <math.h>#include <stdio.h>#define uchar unsigned char #define uint unsigned int ucharkey,sym,sumsz[13],adders=0; // 定义变量float sum,number1=0,number2=0; // 定义变量 bit flag=0; // 定义位变量标志位 sbit lcdrs=P2^5; // 定义液晶的读IO口 sbit lcdwr=P2^6; // 定义液晶的写IO口 sbit lcden=P2^7; // 定义液晶的使能IO口 ucharlcd_s[]={'0','1','2','3','4','5','6','7','8','9','+','-','*',0xfd,'.','='};//void keyscan(); //函数声明void delayms(uchar z);void write_com(uchar com); void write_data(uchar dat); void init(); void delay(int z); bit buzz();void yuans();void clear();/***********************主函数*****************************/void main(){init(); //液晶初始化while(1) //循环函数{keyscan(); //调用键盘扫描函数}}/**********************键盘扫面*************************/ void keyscan(){uchar temp=0;P1=0xfe; //第1次判断函数temp=P1;temp=temp&0xf0;if(temp!=0xf0){delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; //确定按键按下,执行if函数switch(temp){case 0xee:key=1;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;//显示字符1,并记入相加的变量case 0xde:key=2;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;//显示字符2,并记入相加的变量case 0xbe:key=3;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;//显示字符3,并记入相加的变量case 0x7e: key=10;write_data(lcd_s[key]);sym='+';flag=1; break;//显示‘+’号,并将sym付‘+’}while((P1&0xf0)!=0xf0); //等待按键释放}}P1=0xfd; //第2次判断temp=P1;temp=temp&0xf0;if(temp!=0xf0){delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; //确定按键按下,执行if函数switch(temp){case 0xed:key=4;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key; break;//显示字符4,并记入相加的变量case 0xdd:key=5;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key; break;//显示字符5,并记入相加的变量case 0xbd:key=6;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} elsenumber2=number2*10+key;break; //显示字符6,并记入相加的变量case 0x7d: key=11;write_data(lcd_s[key]);sym='-';flag=1; break;//显示‘-’号,并将sym付‘-’}while((P1&0xf0)!=0xf0);}}P1=0xfb; //第3次判断temp=P1;temp=temp&0xf0;if(temp!=0xf0){delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; //确定按键按下,执行if函数switch(temp){case 0xeb:key=7;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} elsenumber2=number2*10+key; break;//显示字符7,并记入相加的变量case 0xdb:key=8;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} elsenumber2=number2*10+key; break;//显示字符8,并记入相加的变量case 0xbb:key=9;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} elsenumber2=number2*10+key;break; //显示字符9,并记入相加的变量case 0x7b: key=12;write_data(lcd_s[key]);sym='*';flag=1; break;//显示‘*’号,并将sym付‘*’}while((P1&0xf0)!=0xf0); //等待按键释放}}P1=0xf7; // 第4次判断temp=P1;temp=temp&0xf0;if(temp!=0xf0){delayms(15);temp=P1;temp=temp&0xf0;if(temp!=0xf0){ temp=P1;adders++; //确定按键按下,执行if函数switch(temp){case 0xe7: key=0;write_data(lcd_s[key]);if(flag==0){number1=number1*10+key;} else number2=number2*10+key;break;//显示字符0,并记入相加的变量case 0xd7: key=14;clear(); break;//调用清零函数case 0xb7: key=15;yuans();flag=1;adders--;break;//调用运算函数case 0x77: key=13;write_data(lcd_s[key]);sym='/';flag=1; break;//显示‘/’号,并将sym付‘/’}while((P1&0xf0)!=0xf0); //等待按键释放}}}/*********************液晶****************************/ void write_com(uchar com) //液晶写指令程序 {while(buzz()) ; lcdrs=0; //lcdwr=0; //lcden=0;P0=com; //_nop_();_nop_();_nop_();_nop_();lcden=1; //_nop_();_nop_();_nop_();_nop_();lcden=0; //}void write_data(uchar dat) //液晶写数据程序 {while(buzz());lcdrs = 1;lcdwr = 0;lcden = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();lcden = 1;_nop_();_nop_();_nop_();_nop_();lcden = 0;}void init() // 液晶初始化程序 { lcden=0; //write_com(0x38); //write_com(0x0c); //write_com(0x06); //write_com(0x01); // }bit buzz() //液晶测忙程序 {bit b;lcdwr=1; //lcdrs=0; //lcden=1;_nop_();_nop_();_nop_();_nop_();b=(bit)(P&0x80);lcden=0;return b;}void delay(int z) // 延时子程序 {int i;while(z--){for(i = 0; i< 250; i++){_nop_();_nop_();_nop_();_nop_();}}}/*********************延时函数**********************************/ void delayms(uchar z) //延时毫秒程序 {uchar i,j;for(i=z;i>0;i--)for(j=110;j>0;j--); }/***********************运算*********************************/ /********************清零函数********************************************/void clear() //清零程序{ uchar i;for(i=0;i<16;i++) //对液晶写入空格{ write_com(0x80+i);write_data(' ');}for(i=0;i<15;i++){write_com(0x80+0x40+i);write_data(' ');}write_data('0');write_com(0x80);flag=0;number1=0;number2=0;adders=0; //将数据变量清零 }/**********************运算程序******************************/ void yuans() //运算函数 {uchar i,j,temp1;switch(sym){case '+':number1+=number2;break; //两数相加case '-':number1-=number2;break; //两数相减case '*':number1*=number2;break; //两数相乘case '/':number1/=number2;break; //两数相除}sprintf(sumsz,"%10.2f",number1); //j=strlen(sumsz);write_com(0x80+0x40+16-j);for(i=0;i<j;i++) //显示结果{ temp1=sumsz[i];write_data(temp1);delay(10);}number2=0;write_com(0x80+adders-1); }。
单片机实验键盘显示

实验七8255 键盘显示实验【实验目的】1.熟悉8255与单片机的接线和I/O编程方法;2.熟悉数码管的显示原理与编程;3.熟悉8255扫描键盘与读取键值的编程。
【实验内容】使用单片机、8255模块和数码管显示电路,编程实现在数码管上从右至左显示0-5,当有键按下时在数码管最右1位显示按键的键码。
【实验原理与设计】1.硬件电路设计本次实验使用实验箱上的E1、E3和F6模块电路。
如图7.1所示。
E1E3F6图7.1 实验箱(1)8255模块(E3区)PA口作为位扫描口(键扫描口),PB口输出字形码,PC口作为键值读入口,与数码管显示电路和矩阵键盘模块电路(F6区)相应接口连接,8255的数据总线D0-D7、读(/RD)、写(/WR)、端口选择A0、A1和片选/CS已和单片机接好。
各端口地址如下:PA口:0FF28H;PB口:0FF29H;PC口:0FF2AH;控制口:0FF2BH单片机与8255模块电路连接图如图7.2所示。
图7.2 单片机与8255的电路连接(2)数码管显示电路(F6区)实验箱上提供的数码管显示电路如图7.3所示。
实验时需将数码管显示电路中的JLED与8255的PB口相连,JS与8255的PA口相连,JLED和JS分别位于E6区,同时E6区SW3、SW4和SW4红色拨码开关打在“OFF”位置。
图7.3数码管模块连接电路(3)矩阵键盘模块电路(F6区)实验箱上提供的矩阵键盘模块电路如图7.4所示,实验时将该电路中的JR(位于E6区)与8255的PC口相连。
图7.4矩阵键盘模块电路2.程序设计根据实验内容程序主流程图如图7.5所示。
图7.5 主程序流程图(1)初始化MOV A, #81H ;PA口(位扫描口)和PB口(字形码)做输出,PC口(键扫描口)做输入MOV DPTR, #0FF2BH ;实验箱接线决定8255的控制口地址为FF2BHMOVX @DPTR, A ;将命令字82H送给8255控制口确定各口工作方式(2)显示数据子程序显示数据子程序流程图如图7.6所示。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
姓名专业学号2013年10月28日随着单片机技术的飞速发展,在其推动下,现代的电子产品几乎渗透到了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高。
单片机具有体积小、功能强、应用面广等优点,目前正以前所未见的速度取代着传统电子线路构成的经典系统,蚕食着传统数字电路与模拟电路固有的领地。
它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。
同时,学习使用单片机了解计算机原理与结构的最佳选择。
现在,这种单片机的使用领域已十分广泛。
彩电、冰箱、空调、录像机、VCD、遥控器、游戏机、电饭煲等无处不见单片机的影子,单片机早已深深地融入我们每个人的生活之中。
单片机能大大地提高这些产品的智能性,易用性及节能性等主要性能指标,给我们的生活带来舒适和方便的同时,在工农业生产上也极大地提高了生产效率和产品质量。
单片机按用途大体上可分为两类,一种是通用型单片机,另一种是专用型单片机。
课题要求:用51单片机、8255、138、373等实现数码管显示按键数值的程序各芯片资料:1.8255芯片资料如下用8255A可编程器件扩展并行接口8255: 有三个八位的并行口:PA、PB、PC。
有三种工作方式:方式0,方式1,方式2。
逻辑结构图:包含四个部分:●三个并行数据输入输出端口●两个工作方式控制电路●一个读写逻辑控制电路●八位总线缓冲器⑴.三个并行数据输入输出端口:A口;B口;C口一般,A口,B口作为数据输入输出端口,C口作为控制/状态信息口,可以分为两个部分,分别与A口和B口配合使用,作为控制信息输出或状态信息输入。
⑵.工作方式控制电路工作方式控制电路有两个:A组控制和B组控制电路,A组控制用来控制A口和C口的上半部分PC7——PC4;B组控制用来控制B口和C口的下半部分PC3——PC0;两组控制电路具有一个控制命令寄存器,用来接收来自CPU的数据(控制字),以决定芯片的工作方式,或对C口按位进行清“0”或者置“1”。
⑶.总线缓冲器三态双向八位缓冲器,作为微处理器数据总线与8255之间的接口,用来传送命令、数据及状态信息。
⑷.读写逻辑控制电路读写逻辑控制电路接受CPU来的控制信号:读、写、地址及复位信息,根据控制信号的要求,将数据读出,送往CPU,或者将CPU来的信息写入端口。
引脚说明:CS:片选信号,低电平有效,表示芯片被选中;RD:读操作,低电平有效,控制数据读出;WE:写操作,低电平有效,控制数据写入;A1,A0:地址线, 端口选择信号,用来选择8255内部端口:RESET:复位信号,高电平有效,各端口被置成输入;D7—D0:双向三态数据线;PA7——PA0:A口输入输出线;PB7—PB0:B口输入输出线;PC7——PC0:C口输入输出线;3.工作方式选择——工作方式控制字8255有三种工作方式:方式0,方式1,方式2。
其中方式2只对A口。
8255的工作方式是由工作方式控制字决定,工作方式控制字是由CPU写入。
8255方式控制字定义如下:D7=1:命令控制字有效。
当D7=0,通过控制口对C口进行位操作。
C口具有位操作功能,通过工作方式控制字可以将PC7——PC0中任意一位置1或清0D7 D6 D5 D4 D3 D2 D1 D0D7=0 对C口操作,D6 D5 D4 无效,D3 D2 D1:位选择0 0 0 PC00 0 1 PC10 1 0 PC20 1 1 PC31 0 0 PC41 0 1 PC51 1 0 PC61 1 1 PC7D0=0:清0 ;0=1:置1⑴.工作方式0:基本输入输出方式三个端口都可以设置成输入或输出方式:●具有两个八位端口:A口和B口●具有两个四位端口:PC0——PC3,PC4——PC7●任一端口都可设置为输入或输出●数据输出带锁存,输入时不锁存此时,8255可以工作在无条件传送;也可以查询式传送,C口作为联络信号⑵.工作方式1:选通式输入/输出方式有固定的选通信号,选通信号与数据一齐传送,由选通信号表示数据传送的状态:●三个端口分为两组:A组和B组●每组包括一个八位数据端口和一个四位的控制状态端口●每个八位数据端口均可设置为输入或输出,输入输出均带锁存●四位端口作为八位端口的控制/状态联络信号2. 51芯片资料Vcc40电源端GND20接地端*工作电压为5V,另有AT89LV51工作电压则是2.7-6V, 引脚功能一样。
2.外接晶体引脚图2-2外接晶体引脚XTAL119XTAL218XTAL1是片内振荡器的反相放大器输入端,XTAL2则是输出端,使用外部振荡器时,外部振荡信号应直接加到XTAL1,而XTAL2悬空。
内部方式时,时钟发生器对振荡脉冲二分频,如晶振为12MHz,时钟频率就为6MHz。
晶振的频率可以在1MHz-24MHz内选择。
电容取30PF左右。
*型号同样为AT89C51的芯片,在其后面还有频率编号,有12,16,20,24MHz可选。
大家在购买和选用时要注意了。
如AT89C51 24PC就是最高振荡频率为24MHz,40P6封装的普通商用芯片。
3.复位RST9在振荡器运行时,有两个机器周期(24个振荡周期)以上的高电平出现在此引腿时,将使单片机复位,只要这个脚保持高电平,51芯片便循环复位。
复位后P0-P3口均置1引脚表现为高电平,程序计数器和特殊功能寄存器SFR全部清零。
当复位脚由高电平变为低电平时,芯片为ROM的00H处开始运行程序。
常用的复位电路如图2-3所示。
*复位操作不会对内部RAM有所影响。
图2-3常用复位电路4.输入输出引脚(1) P0端口[P0.0-P0.7] P0是一个8位漏极开路型双向I/O端口,端口置1(对端口写1)时作高阻抗输入端。
作为输出口时能驱动8个TTL。
对内部Flash程序存储器编程时,接收指令字节;校验程序时输出指令字节,要求外接上拉电阻。
在访问外部程序和外部数据存储器时,P0口是分时转换的地址(低8位)/数据总线,访问期间内部的上拉电阻起作用。
(2) P1端口[P1.0-P1.7] P1是一个带有内部上拉电阻的8位双向I/0端口。
输出时可驱动4个TTL。
端口置1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部Flash程序存储器编程时,接收低8位地址信息。
(3) P2端口[P2.0-P2.7] P2是一个带有内部上拉电阻的8位双向I/0端口。
输出时可驱动4个TTL。
端口置1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部Flash程序存储器编程时,接收高8位地址和控制信息。
在访问外部程序和16位外部数据存储器时,P2口送出高8位地址。
而在访问8位地址的外部数据存储器时其引脚上的内容在此期间不会改变。
(4) P3端口[P3.0-P3.7] P2是一个带有内部上拉电阻的8位双向I/0端口。
输出时可驱动4个TTL。
端口置1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部Flash程序存储器编程时,接控制信息。
除此之外P3端口还用于一些专门功能,具体请看表2-2.。
*P1-3端口在做输入使用时,因内部有上接电阻,被外部拉低的引脚会输出一定的电流。
表2-2P3端口引脚兼用功能表呼!一口气说了那么多,停一下吧。
嗯,什么?什么叫上拉电阻?上拉电阻简单来说就是把电平拉高,通常用4.7-10K的电阻接到Vcc电源,下拉电阻则是把电平拉低,电阻接到GND 地线上。
具体说明也不是这里要讨论的,接下来还是接着看其它的引脚功能吧。
5.其它的控制或复用引脚(1) ALE/PROG 30 访问外部存储器时,ALE(地址锁存允许)的输出用于锁存地址的低位字节。
即使不访问外部存储器,ALE端仍以不变的频率输出脉冲信号(此频率是振荡器频率的1/6)。
在访问外部数据存储器时,出现一个ALE脉冲。
对Flash 存储器编程时,这个引脚用于输入编程脉冲PROG(2) PSEN 29 该引是外部程序存储器的选通信号输出端。
当AT89C51由外部程序存储器取指令或常数时,每个机器周期输出2个脉冲即两次有效。
但访问外部数据存储器时,将不会有脉冲输出。
(3) EA/Vpp 31 外部访问允许端。
当该引脚访问外部程序存储器时,应输入低电平。
要使AT89C51只访问外部程序存储器(地址为0000H-FFFFH),这时该引脚必须保持低电平。
对Flash存储器编程时,用于施加Vpp编程电压。
Vpp电压有两种,类似芯片最大频率值要根据附加的编号或芯片内的特征字决定。
具体如表2-3所列。
表2-3Vpp与芯片型号和片内特征字的关系看到这您对AT89C51引脚的功能应该有了一定的了解了,引脚在编程和校验时的时序我们在这里就不做详细的探讨,通常情况下我们也没有必要去撑握它,除非你想自己开发编程器。
下来的课程我们要开始以一些简单的实例来讲述C程序的语法和编写方法技巧,中间穿插相关的硬件知识如串口,中断的用法等等。
成HEX文件和最小化系统在开始C语言的主要内容时,我们先来看看如何用KEIL uVISION2来编译生成用于烧写芯片的HEX文件。
HEX文件格式是Intel公司提出的按地址排列的数据信息,数据宽度为字节,所有数据使用16进制数字表示, 常用来保存单片机或其他处理器的目标程序代码。
它保存物理程序存储区中的目标代码映象。
一般的编程器都支持这种格式。
我们先来打开第一课做的第一项目,打开它的所在目录,找到test.Uv2的文件就可以打开先前的项目了。
然后右击图3-1中的1项目文件夹,弹出项目功能菜单,选Options for Target'Target1',弹出项目选项设置窗口,同样先选中项目文件夹图标,这时在Project 菜单中也有一样的菜单可选。
打开项目选项窗口,转到Output 选项页图3-2所示,图中1是选择编译输出的路径,2是设置编译输出生成的文件名,3则是决定是否要创建HEX文件,选中它就可以输出HEX文件到指定的路径中。
选好了?好,我们再将它重新编译一次,很快在编译信息窗口中就显示HEX文件创建到指定的路径中了,如图3-3。
这样我们就可用自己的编程器所附带的软件去读取并烧到芯片了,再用实验板看结果,至于编程器或仿真器品种繁多具体方法就看它的说明书了,这里也不做讨论。
3. 74HC138芯片资料如下:74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL (LSTTL)系列。
74HC138译码器可接受3位二进制加权地址输入(A0, A1和A3),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。
74HC138特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。
除非E1和E2置低且E3置高,否则74HC138将保持所有输出为高。