C51独立按键
单片机独立按键识别实验报告
桂林电子科技大学
实验报告
2016-2017 学年第一学期
开课单位海洋信息工程学院
适用年级、专业 14级机械设计制造及其自动化
课程名称《单片微型计算机与接口技术-课内实验》
主讲教师周旋
课程序号 BS1615000_03
课程代码 BS1615000 实验名称《独立按键识别》
学号 1416010516 - 17 姓名林亦鹏卢炳荣
独立按键识别实验报告
电路采用无源蜂鸣器,从P1.5口形成脉冲来驱动。
因为单片机开机初始化瞬间,其I/O口为高电平,会有误响动作。
单片机的独立键盘使用的是P1口。
当有键按下时,P1口相应位为低电平。
、查找资料说明按键抖动的原因。
、延时程序是怎么实现延时的?
定义蜂鸣器的连接端口--//。
C51典型例程(按键驱动)
主要(zhǔyào)内容:
1. 键盘(jiànpán) 2. LED数码管 3. 字符型LCD
精品资料
键盘(jiànpán)
1. 独立式键盘(jiànpán)
(1) 独立式键盘的结构 与特点
精品资料
键盘(jiànpán)
1. 独立式键盘(jiànpán)
(2) 编程模式 在确定了键盘的编程结构后,就可以编制键盘接口程序。键盘接口程序 的功能实际上就是驱动键盘工作,完成按键的识别,根据所识别按键的键值, 完成按键子程序的正确散转,从而完成单片机应用系统对用户按键动作的预 定义响应。
形。 (2)16×2字符(zìfú)型LCD引脚说明 16×2字符(zìfú)型LCD共有14个引脚,其功能见表6-3所示。
精品资料
字符(zìfú)型LCD
2. HD44780 驱动器(16×2字符型LCD)
(3)LCD内部的内存 LCD内部存储器共分为3种:固定字形ROM,称为CG(Character
(2) 定时扫描方式
定时扫描方式就是每隔一段时间对键 盘扫描一次,它利用单片机内部的定时 器产生一定时间(例如10ms)的定时, 当定时时间到就产生定时器溢出中断, CPU响应中断后对键盘进行扫描,并在 有键按下时识别出该键,再执行该键的 功能程序。
精品资料
键盘(jiànpán)
4. 键盘(jiànpán)的工作方式
2)忙碌标志(Busy Flag,BF)。当LCD模块内部处于忙碌状态,不能接 收或处理外部信号时,这个标志就会被设定为1,因此在对LCD模块控制时,一 定要先检查这个忙碌标志,当BF=0时,才可以对LCD模块进行控制。
精品资料
字符(zìfú)型LCD
2. HD44780 驱动器(16×2字符型LCD)
利用51单片机,8个按键,8路发光二级管构成一个独立式键盘系统,按下8个按键,点亮对应的灯。
电子信息工程学院电子设计应用软件训练任务【训练任务】:1、熟练掌握PROTEUS软件的使用;2、按照设计要求绘制电路原理图;3、能够按要求对所设计的电路进行仿真;【基本要求及说明】:1、按照设计要求自行定义电路图纸尺寸;2、设计任务如下:利用51单片机,8个按键,8路发光二级管构成一个独立式键盘系统,按下8个按键,点亮对应的灯。
3、按照设计任务在Proteus 6 Professional中绘制电路原理图;4、根据设计任务的要求编写程序,在Proteus下进行仿真,实现相应功能。
【按照要求撰写总结报告】指导教师年月日负责教师年月日学生签字年月日成绩评定表电子设计应用软件训练总结报告一.任务说明本次任务是利用51单片机、按键以及发光二极管设计一个独立式键盘系统,要求独立简单可控。
首先要明确51单片机的工作原理,在此基础上编写单片机程序,再载入到所连电路原理图中实现按键控制二极管亮灭。
此次任务需要完成电路原理图的绘制、单片机汇编语言的编程。
目的是通过本次设计熟悉Proteus软件的工作环境,掌握基本的操作及流程以及对单片机汇编语言的进一步学习,使之前的学习得到巩固。
二.原理图绘制说明总体而言,一个完善的系统最重要的是稳定,精确,设计简单,修护容易,成本低,体积小。
满足以上条件的系统我们都可以说是完善的系统。
因此,我在设计中选用了一些比较成熟的器件,这些器件都经过时间的考验,能稳定的工作,同时,价格也相对便宜。
下面对原理图中主要的硬件进行简单介绍。
2.1 AT89C51的基本概述AT89C5l单片机,是一种低功耗、高性能的、片内含有4KB Flash ROM的8位CMOS 单片机,工作电压范围为2.7~6V(实际使用+5V供电),8位数据总线。
它有—个可编程的全双工串行通信接口,能同时进行串行发送和接收。
AT89C51具有4K并行可编程的非易失性FLASH程序存储器,可实现对器件串行在系统编程ISP和在应用中编程(IAP)。
51单片机_独立按键检测
《51系列单片机_独立按键检测》此程序使用单片机89SC52//1、此程序实现独立按键的检测功能,每次按下按键key5时,数码管最后一位显示的数值加1,按键同时响蜂鸣器#include<reg52.h>sbitkey5 = P1^4;//独立按键sbitP3_6 = P3^6;//蜂鸣器控制端口unsigned char codeBitSet[8] ={0xfe, 0xfd, 0xfb, 0xf7,0xef, 0xdf, 0xbf, 0x7f};//用于设置(低电平位选)数码管的位选信号,从低到高对应8个数码管unsigned charcode NumberCode[16] ={0x3f, 0x06, 0x5b, 0x4f,0x66, 0x6d, 0x7d, 0x07,0x7f, 0x6f, 0x77, 0x7c,0x39, 0x5e, 0x79, 0x71,};//用于设置(共阴极)数码管的段选信号,从0~f共16个数值voiddelay_ms(unsigned int n){//软件延时函数,延时n毫秒unsigned int i, j;for(i=n;i>0;i--)for(j=110;j>0;j--);}voidbeep(int n){inti = n;//喇叭连续响n毫秒while(i>0)//向喇叭输入1000HZ的方波震荡源{P3_6 = 1;delay_ms(1);//0.5毫秒高电平P3_6 = 0;delay_ms(1);//0.5毫秒低电平i--;}}voidmain(){intnum=0;while(1){P2=BitSet[7];//选择最低位的数码管if(key5==0)//判断按键key5是否按下{delay_ms(10);//延时重新判断按键是否按下,延时消除抖动if(key5==0){num++;//每按下一次显示的数值加1beep(200);//喇叭响200毫秒if(num==16) num=0;while(!key5);//直到按键释放,按下时key5==0,持续循环}}P0=~NumberCode[num];}}//2、此程序实现独立按键的检测功能,key5和key6每次按下按键时,数码管次低位和最低位显示的数值加1,按键同时响蜂鸣器#include<reg52.h>sbit key5 = P1^4;sbit key6 = P1^5;sbit P3_6 = P3^6;unsigned char code BitSet[8] ={0xfe, 0xfd, 0xfb, 0xf7,0xef, 0xdf, 0xbf, 0x7f};//用于设置(低电平位选)数码管的位选信号,从低到高对应8个数码管unsigned char code NumberCode[16] ={0x3f, 0x06, 0x5b, 0x4f,0x66, 0x6d, 0x7d, 0x07,0x7f, 0x6f, 0x77, 0x7c,0x39, 0x5e, 0x79, 0x71,};//用于设置(共阴极)数码管的段选信号,从0~f共16个数值void delay_ms(unsigned int n){//软件延时函数,延时n毫秒unsigned int i, j;for(i=n;i>0;i--)for(j=110;j>0;j--);}void beep(int n){int i = n;//喇叭连续响n毫秒while(i>0)//向喇叭输入1000HZ的方波震荡源{P3_6 = 1;delay_ms(1);//0.5毫秒高电平P3_6 = 0;delay_ms(1);//0.5毫秒低电平i--;}}void main(){int num=0, num2=0;while(1){P2=BitSet[6];//选择最低位的数码管if(key5==0)//判断按键key5是否按下{delay_ms(10);//延时重新判断按键是否按下,延时消除抖动if(key5==0){num++;//每按下一次显示的数值加1beep(100);//喇叭响100毫秒if(num==16) num=0;while(!key5){P2=BitSet[6];//选择次低位的数码管P0=~NumberCode[num];delay_ms(3);P2=0xff;}}}};P2=BitSet[7];//选择最低位的数码管P0=~NumberCode[num2];delay_ms(3);P2=0xff;//直到按键释放,按下时key5==0,持续循环P0=~NumberCode[num];delay_ms(3);P2=0xff;}P2=BitSet[7];//选择最低位的数码管if(key6==0)//判断按键key6是否按下{delay_ms(10);//延时重新判断按键是否按下,延时消除抖动if(key6==0){num2++;//每按下一次显示的数值加1beep(100);//喇叭响100毫秒if(num2==16) num2=0;while(!key6){P2=BitSet[6];//选择次低位的数码管P0=~NumberCode[num];delay_ms(3);P2=0xff;P2=BitSet[7];//选择最低位的数码管P0=~NumberCode[num2];delay_ms(3);P2=0xff;};;//直到按键释放,按下时key6==0,持续循环}} P0=~NumberCode[num2];delay_ms(3);P2=0xff;。
c51常用程序大全
2.独立按键:51开发板独立键和矩阵键盘不能同时用,会有冲突
sbit s2=P3^4;
while(1) { if(s2==0) led=0; else led=1; }
//通过大循环不断扫描按键状态(方法一)
if(s2==0)
//消抖动 (方法二)
{
delay_ms(20);
if(s2==0)
{
while(!s2); //等待按键释放
//0000 0011 设置定时器0为工作方式3
TH0= 256-250 ; //6 以1s装初值,12M溢出4000次,11.0592溢出3686次 TL0= 256-250 ; //6 EA=1; //开总中断 ET0=1; //定时器/计数器0 中断允许位 ET1=1; //开定时器1中断 TR0=1; //启动定时器0 TR1=1; //启动定时器0的高8位计数器 while(1) //程序停止在这里等待中断发生
delay_ms(20);//延时30ms scan1=P3; if((scan1&0xf0)!=0xf0)//二次判键是否按下 {
P3=0x0f;//线翻转法 delay_ms(1);//延时 scan2=P3;//读P3口的状态 keycode=scan1|scan2; //组合成键编码 while(P3!=0x0f); //等待按键释放 for(j=0;j<=15;j++)
作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微
秒。 NOP指令为单周期指令(即为12个时钟周期),1/12 us可由晶振频率算出延时时间,对于12M晶振, 延时1uS;对于11.0592M,则n个NOP指令为单周期为1.08155 us * n 对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现
51单片机 键盘F1F2F3功能键盘
#include<reg52.h>#include<stdio.h>unsigned char b[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; unsigned char c[8];unsigned char K,Key,fl=0,ac=0; //fl功能键标志,ac表示数码管显示个数void delay(unsigned char pp) //延迟时间等于k*1ms{while(pp--){unsigned char j;// P2=P2&0XF8;for(j = 0;j<123;j++); //j进行的内部循环,1次延迟8us,延迟1ms}}void display(){ unsigned char i;for(i=0;i<ac;i++) //为了让8个数码管轮流亮一遍过去{P0=c[i];P2=i;delay(2);}}void fun1(){ unsigned char i;for(i=0;i<10;i++){P0=0XFF;P2=0;delay(255);P0=0XC0;delay(255);}P0=0XFF ;fl=0;}void fun2(){unsigned char i,j;for(i=0;i<16;i++)for(j=0;j<8;j++){P0=b[i];P2=j;delay(255);}P0=0XFF ;fl=0;}void fun3(){unsigned char i,j;for(j=0;j<255;j++){for(i=0;i<8;i++){P0=b[i];P2=i;delay(1);}}P0=0XFF ;fl=0;}unsigned char Keycan(void) //按键扫描程序P1.0--P1.3为行线P1.4--P1.7为列线{unsigned char rcode, ccode;P1 = 0xF0; // 发全0行扫描码,列线输入if((P1&0xF0) != 0xF0) // 若有键按下{delay(1);// 延时去抖动if((P1&0xF0) != 0xF0){ rcode = 0xFE; // 逐行扫描初值while((rcode&0x10) != 0){P1 = rcode; // 输出行扫描码if((P1&0xF0) != 0xF0) // 本行有键按下{ccode = (P1&0xF0)|0x0F;//do{;}while((P1&0xF0) != 0xF0) //等待键释放{display();}return ((~rcode) + (~ccode)); // 返回键编码}elsercode = (rcode<<1)|0x01; // 行扫描码左移一位}}}return 0; // 无键按下,返回值为0}void KeyDeal(unsigned char Key){ //unsigned char n;if(Key!=0){switch(Key){case 0x11: K=0; break;case 0x21: K=1; break;case 0x41: K=2; break;case 0x81: K=3; break;case 0x12: K=4; break;case 0x22: K=5; break;case 0x42: K=6; break;case 0x82: K=7; break;case 0x14: K=8; break;case 0x24: K=9; break;case 0x44: K=10; break;case 0x84: K=11; break;case 0x18: K=12; break;case 0x28: K=13; break;case 0x48: K=14; break;case 0x88: K=15,fl=1; break;default: break;}if(K<=9){c[7]=c[6];c[6]=c[5];c[5]=c[4];c[4]=c[3];c[3]=c[2];c[2]=c[1];c[1]=c[0];c[0]=b[K];ac++;if(ac>8)ac=8;}if(fl==1){switch(K){case 1: fun1(); break;//功能键1case 2: fun2(); break;//功能键2case 3: fun3(); break;//功能键3default: break;}}}}void main(){while(1){Key = Keycan();//键盘扫描获取一次按键的编码0x11-0x88KeyDeal(Key); //对扫描到的键盘编码进行转换处理,变成数据键盘0-9,11-15 display();}}。
KeilC51学习4按键外部中断
KeilC51学习4按键外部中断主板介绍:P3^2~P^5为四个按键;P1^0~P1^7为8个LED灯#include "reg52.h"//此⽂件中定义了单⽚机的⼀些特殊功能寄存器typedef unsigned int uint; //对数据类型进⾏声明定义typedef unsigned char u8;sbit k1=P3^5; //定义P31⼝是k1sbit led=P1^0; //定义P10⼝是led/******************************************************************************** 函数名 : delay* 函数功能 : 晶振11.0592M延时函数*******************************************************************************/void delay(uint z){uint i,j;for(j=z;j>0;j--)for(i=112;i>0;i--);}/******************************************************************************** 函数名 : keypros* 函数功能 : 按键处理函数,判断按键K1是否按下*******************************************************************************/void keypros(){if(k1==0){delay(50);if(k1==0) //再次判断按键是否按下led=~led; //led状态取反}while(!k1); //检测按键是否松开}/******************************************************************************** 函数名 : main* 函数功能 : 主函数* 输⼊ : ⽆* 输出 : ⽆*******************************************************************************/void main(){while(1){keypros(); //按键处理函数}}按键取反灯亮或灭计数器(计数器0⽤P3^4按钮,计数器1⽤P3^5按钮,不懂)/*-----------------------------------------------名称:计数器0论坛:编写:shifang⽇期:2009.5修改:⽆内容:通过外部按键计数进⼊中断执⾏LED取反------------------------------------------------*/#include<reg52.h> //包含头⽂件,⼀般情况不需要改动,头⽂件包含特殊功能寄存器的定义sbit LED=P1^0; //定义LED端⼝/*------------------------------------------------定时器初始化⼦程序(按钮P3^4控制,不知为什么)------------------------------------------------*/void Init_Timer0(void){TMOD |= 0x01 | 0x04; //使⽤模式1,16位计数器,使⽤"|"符号可以在使⽤多个定时器时不受影响TH0=0xFF; //给定初值TL0=245; //从245计数到255EA=1; //总中断打开ET0=1; //定时器中断打开}/*------------------------------------------------主程序------------------------------------------------*/main(){Init_Timer0();while(1);}/*------------------------------------------------定时器中断⼦程序------------------------------------------------*/void Timer0_isr(void) interrupt 1using1{TH0=0xFF; //重新给定初值TL0=245;LED=~LED; //指⽰灯反相,可以看到闪烁}计数器0/*-----------------------------------------------名称:计数器1论坛:编写:shifang⽇期:2009.5修改:⽆内容:通过外部按键计数进⼊中断执⾏LED取反------------------------------------------------*/#include<reg52.h> //包含头⽂件,⼀般情况不需要改动,头⽂件包含特殊功能寄存器的定义sbit LED=P1^0; //定义LED端⼝/*------------------------------------------------定时器初始化⼦程序------------------------------------------------*/void Init_Timer1(void){TMOD |= 0x10 | 0x40; //使⽤模式1,16位计数器,使⽤"|"符号可以在使⽤多个定时器时不受影响TH1=0xFF; //给定初值TL1=245; //从245计数到255EA=1; //总中断打开ET1=1; //定时器中断打开TR1=1; //定时器开关打开}/*------------------------------------------------主程序------------------------------------------------*/main(){Init_Timer1();while(1);}/*------------------------------------------------定时器中断⼦程序------------------------------------------------*/void Timer1_isr(void) interrupt 3{TH1=0xFF; //重新给定初值TL1=245;LED=~LED; //指⽰灯反相,可以看到闪烁}计数器1中断定义:当机器正在执⾏程序的过程中,⼀旦遇到⼀些异常或者特殊请求时,停⽌正在执⾏的程序转⼊必要的处理,处理完毕后,⽴即返回断点继续执⾏。
基于C51按键模式可选以及定时设置程序设计
基于C51按键模式可选程序设计1 我们经常看到在一些电磁炉中可以用一个按键来选择工作模式或者空调中两个按键改变温度的大小,这里为了简便只给出一个按键选择工作模式,另一个按键设置工作的时间;两个按键选着工作模式的的方法更简单一加一减调节温度;我这里用一个按键K1采用循环选择模式。
2 模式选着演示说明:当按下K1红色LED会从上到下的跳动选着工作模(用led来代表工作模式的驱动开关):当然外围的估计要加一些光耦隔离什么的,还有一些外围的大功率开关电源自己能力有限;一时上班也没有那么多时间和大家一起分享。
3定时程序设置:由于单片机中IO口宝贵;本想用一个按键;用SWITH语句把所有的定时子程序都放在里面用一个按键来选择,比如按一下延时一分钟两下两分钟如此递增;自己也是初学这方面的菜鸟,试了三天还是没有达到那种希望的结果;有能力想出方案的朋友能让我参考参考谢谢。
我邮箱1284718502@我这里只能做到按对应的键选,设置对应的延时程序,图中我只用了一个键K2来设置工作模式。
当按K1确定好工作模式后(点亮对应的红色LED,如果按下K2蓝色LED就会不停的取反闪烁,直到蓝色LED完全熄灭后,红色LED也完全熄灭;当面一般定时时间有不同,可以在其他的IO口按K2的方法接弹性开关;类似的采用多级if else语句选择对应的时间参数。
4延时设定我想有一定C基础的朋友可以多用几个for循环,while循环,设置延时函数;还有中断定时计数等方式设置你想要的时间;这点应该不难。
5.如果会keil uvision 和proteus professional两种软件的朋友可以把下面的程序烧到上面的仿真软件里试一下,绝对可行。
当然实际当中单片机的性价比我们可以有更多的选择。
我这里只作参考。
6 程序设计#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit mode1 =P2^1;sbit dinshi=P2^2;sbit LED2=P2^7;void DelayMS(uint x){uchar i;while(x--){for(i=0;i<120;i++);}}void main(){uchar t;P2=0xff;P0=0x10;while(1){if(mode1==0)P0=_crol_(P0,1);DelayMS(150);if(dinshi==0){LED2=0;for(t=0;t<10;t++){。
单片机独立式按键、矩形按键的应用-PPT精品文档
8
8.1.3.独立按键流程图与软件实现
开始 否
ORG LJMP ORG MAIN: MOV MOV CJNE LJMP L_PRESS:
0000H MAIN 0030H P1,#0FFH A,P1 A,#0FFH,L_PRESS MAIN DELAY20MS ;消抖 P1,#0FFH A,P1 A,#0FFH,L_TUREPRESS MAIN A,#11111110B KEY0 L_EXIT A,#11111101B KEY1 L_EXIT A,#11111110B KEY7 MAIN
计算行: 计算列:
行全部输出高电平,列全部输出低电平,读回数据,如果P1.0P1.3某行变为低电平就知道该行上面有按键。代码如左下: 行全部输出低电平,列全部输出高电平,然后读回来判断。如果 P1.4-P1.7某列变为低电平就知道该列上面有按键。代码如右下:
第八章
常规按键的应用
硅谷芯微 技术贡献 网址:threeway
键盘的分类
键盘分编码键盘和非编码键盘。键盘上闭合键的 识别由专用硬件编码器实现,并产生键编码号或 键值的称为编码键盘,如BCD码键盘、ASCLL码 键盘等;而靠软件来识别的称为非编码键盘;在 单片机组成的测控系统及智能化仪器中,用的最 多的是非编码键盘。 非编码键盘有分为:独立式非编码键盘和行列式 非编码键盘(矩阵键盘)。无论是何种按键,其 功能实现都是分为三个步骤:
有按键? 是 消抖
有按键? 是 按键1? 是 处理按键1
否
否
按键n? 是 按键n服务程序
否
LCALL MOV MOV CJNE LJMP L_TUREPRESS: CJNE LCALL LJMP CJNE LCALL LJMP ……….. CJNE LCALL L_EXIT: LJMP
51单片机-独立按键
查询方式
单片机不断的扫描键盘判断按键是否动作 特点:硬件简单,但需要单片出中断请求,单片机响应中断请求后转按键 识别程序
特点:硬件复杂,需要中断电路,但不占用CPU资源
单片机处理按键的流程
单片机处理按键动作需要以下步骤:
按键识别
单片机在识别按键时,IO口工作在输入状态:
按键弹起,IO口电平5V
Vcc
按键按下,IO口电平0V
单片机读取IO口的状态
即可知按键的状态
单片机
按键抖动
实际的按键在被按下或抬起时,由于机械 触点的弹性作用,在闭合或断开的瞬间均伴随有 一连串的抖动现象。
理想波形
实际波形
按下抖动
稳定闭合
释放抖动
完整的按键过程包括: 1. 释放状态 2. 按下抖动阶段 3. 完全按下状态 4. 释放抖动阶段 5. 释放状态
按键防抖
防抖措施:
硬件防抖
在按键输出端加RS或施密特触发器 去抖效果好、电路复杂、成本高
软件防抖
利用软件进行延时(10ms) 电路简单、成本低、但占用CPU时间
键盘的工作方式
判断按键是否按下 按键按下时的防抖 识别哪个按键按下,判断键值 判断按键是否放开 送出键值,处理按键动作
练习:单片机按键查询操作,8个按键对应8个LED灯, K1对应D1,K2对应D2,K3对应D3,……,查询按键, 按下某一个按键后对应的LED亮起,再按一次关闭。
51单片机基础知识
一、单片机基础知识1.1介绍:单片机,简称MCU.内部集成了CPU,RAM,ROM,定时器,终端系统,通讯接口等一系列电脑的常用硬件功能1.1.1点亮一个LED:安装好stc-isp与Keil5C51,配置USB驱动;建立一个新工程,选择AT89C52型号添加新文件选择C语言(通常情况下)通过调节P20的电压实现点亮/熄灭写好程序勾选创建HEX文件,再次编译;配置芯片型号(带RC选RC)与串口点击打开程序文件打开HEX文件下载到单片机;查找时重启单片机电源;成功点亮1.1.2LED闪烁:可从此处进行延时函数复制(系统频率一般默认为12Hz)#include<REGX52.H>//The Definition#include<INTRINS.H>//Using the _nop_()void Delay500ms() //@12.000MHz{unsigned char i, j, k;_nop_();i = 4;j = 205;k = 187;do{do{while (--k);} while (--j);} while (--i);}void main(){while(1){P2 = 0xFE;//1111 1110 There is a pressure drop across the diode Delay500ms();P2 = 0xFF;//1111 1111 There isn't a pressure drop across the diode Delay500ms();}}使用此函数进行LED闪烁;1.1.3LED流水灯:通过控制P2管脚的十六进制数值改变对应LED灯的压降,实现亮/灭;P2实际上为8位一体的导线;P2_X则可以操作单独的LED控件#include<REGX52.H>//The Definition#include<INTRINS.H>//Using the _nop_()void Delay1ms(unsigned int xms) //@12.000MHz{unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}void main(){while(1){P2=0xFE;//1111 1110 D1Delay1ms(500);P2=0xFD;//1111 1101 D2Delay1ms(500);P2=0xFB;//1111 1011 D3Delay1ms(500);P2=0xF7;//1111 0111 D4Delay1ms(500);P2=0xEF;//1110 1111 D5Delay1ms(500);P2=0xDF;//1101 1111 D6Delay1ms(500);P2=0xBF;//1011 1111 D7Delay1ms(500);P2=0x7F;//0111 1111 D8Delay1ms(500);}}1.2独立按键控制LED亮灭:通过查询原理图发现,K1独立按键对应P3_1;#include<REGX52.H>//The Definitionvoid main(){while(1){if(P3_1){//UPP2_0=1;//D1 Dark}else{//DOWNP2_0=0;//D1 Light}}}1.2.1独立按键控制LED状态:按键抖动:对于机械开关,当机械触点断开,闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会立刻断开,开关闭合/断开时往往伴随着波动#include<INTRINS.H>//Using the _nop_()void Delay(unsigned int xms){unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}void main(){while(1){if(!P3_1){//DOWNDelay(20);while(!P3_1);Delay(20);P2_0=~P2_0;}}}消除误差1.2.2独立按键控制LED显示二进制unsigned char 用来表示一个寄存器#include<REGX52.H>//The Definition#include<INTRINS.H>//Using the _nop_() void Delay(unsigned int xms){unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}void main(){unsigned char LEDNumber = 0;while(1){if(!P3_1){//DOWNDelay(20);while(!P3_1);Delay(20);LEDNumber++;P2=~LEDNumber;}}}对P2进行取反操作则为计算二进制数值1.2.3独立按键控制LED移位:#include<REGX52.H>//The Definition#include<INTRINS.H>//Using the _nop_() void Delay(unsigned int xms){unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}void main(){unsigned char LEDNumber=0;P2=~0x01;//Rename the character while(1){if(!P3_0){//K2 DOWN Moving RightDelay(20);while(!P3_0);Delay(20);LEDNumber++;if(LEDNumber>=8){LEDNumber=0;}P2=~(0x01<<LEDNumber);}if(!P3_1){//K1 DOWN Moving LeftDelay(20);while(!P3_1);Delay(20);if(!LEDNumber){LEDNumber=7;}else{LEDNumber--;}P2=~(0x01<<LEDNumber);}}}包括左移(K1)和右移(K2);if语句中为消除误差+移动计算;通过改变P2总导线压降,来控制对应LED灯的亮灭首先对P2进行初始化0000 0001 D1亮0x01<<00000 0010 D2 亮0x00<<1....1000 0000 D8亮0x00<<81.3静态数码管显示:确定静态数码管显示时,先根据所选型号与待输出数据确定位选(3.8引脚的高低电平)与段码(剩下引脚的高低电平)通过此两排端口进行控制,下方端口由P0控制通过138译码器实现仅一位LED为1的操作(其余为0),通过观察真值表确定端口: 三端口为P2引脚.C B A Y0 0 0 70 0 1 60 1 0 50 1 1 41 0 0 31 0 1 21 1 0 11 1 1 0DIR控制数据传输方向DIR通过J24控制电平高低.当DIR接高电平时,从左向右传输数据#include<REGX52.H>//The Definition#include<INTRINS.H>//Using the _nop_()void Delay(unsigned int xms){unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}unsigned char NixieTabel[]={0x3F,0x30,0x5B,0x4F,0x66,0x6D,0x7D,0x07};void Nixie(unsigned char Location, Number){ switch(Location){case8:{P2_4=0;P2_3=0;P2_2=0;break;}case7:{P2_4=0;P2_3=0;P2_2=1;break;}case6:{P2_4=0;P2_3=1;P2_2=0;break;}case5:{P2_4=0;P2_3=1;P2_2=1;break;}case4:{P2_4=1;P2_3=0;P2_2=0;break;}case3:{P2_4=1;P2_3=0;P2_2=1;break;}case2:{P2_4=1;P2_3=1;P2_2=0;break;}case1:{P2_4=1;P2_3=1;P2_2=1;break;}}P0=NixieTabel[Number];}void main(){unsigned int location = 1, number = 0;while(1){if(location > 8){location = 1;number = 0;}Delay(1000);Nixie(location,number);location++;number++;}}1.3.1动态数码管显示在实现显示多个数据时,清零上一个数据,实现消影#include<REGX52.H>//The Definition#include<INTRINS.H>//Using the _nop_()void Delay(unsigned int xms){unsigned char i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}}unsigned char NixieTabel[]={0x3F,0x30,0x5B,0x4F,0x66,0x6D,0x7D,0x07};void Nixie(unsigned char Location, Number){switch(Location){case8:{P2_4=0;P2_3=0;P2_2=0;break;}case7:{P2_4=0;P2_3=0;P2_2=1;break;}case6:{P2_4=0;P2_3=1;P2_2=0;break;}case5:{P2_4=0;P2_3=1;P2_2=1;break;}case4:{P2_4=1;P2_3=0;P2_2=0;break;}case3:{P2_4=1;P2_3=0;P2_2=1;break;}case2:{P2_4=1;P2_3=1;P2_2=0;break;}case1:{P2_4=1;P2_3=1;P2_2=1;break;}}P0=NixieTabel[Number];Delay(1);P0=0x00;//Creat Last digit.}void main(){while(1){Nixie(1,5);Nixie(2,2);Nixie(3,0);}}1.3.2LCD1602调试工具LCD_Init();//初始化LCD_ShowChar(1,1,'A');//显示一个字符LCD_ShowString(1,3,"Hello");//显示字符串LCD_ShowNum(1,9,123,3);//显示十进制数字LCD_ShowSignedNum(1,13,-66,2);//显示有符号十进制数字LCD_ShowHexNum(2,1,0xA8,2);//显示十六进制数字LCD_ShowBinNum(2,4,0xAA,8);//显示二进制数字1.4矩阵键盘:矩阵按键按列扫描P引脚均为弱上拉,即同时输入1&&0,输出0添加如下文件:#include <REGX52.H>#include "Delay.h"unsigned char MatrixKey(){unsigned char KeyNumber=0;//先判断列数,再判断行数,避免电平错位P1=0xFF;//全部置为高电平P1_3=0;//仅启动P1_3--即第一列 if(!P1_7){Delay(20);while(!P1_7);Delay(20);KeyNumber=1;}if(!P1_6){Delay(20);while(!P1_6);Delay(20);KeyNumber=5;}if(!P1_5){Delay(20);while(!P1_5);Delay(20);KeyNumber=9;}if(!P1_4){Delay(20);while(!P1_4);Delay(20);KeyNumber=13;}P1=0xFF;//全部置为高电平P1_2=0;//仅启动P1_2--即第二列 if(!P1_7){Delay(20);while(!P1_7);Delay(20);KeyNumber=2;}if(!P1_6){Delay(20);while(!P1_6);Delay(20);KeyNumber=6;}if(!P1_5){Delay(20);while(!P1_5);Delay(20);KeyNumber=10;}if(!P1_4){Delay(20);while(!P1_4);Delay(20);KeyNumber=14;}P1=0xFF;//全部置为高电平P1_1=0;//仅启动P1_1--即第三列 if(!P1_7){Delay(20);while(!P1_7);Delay(20);KeyNumber=3;}if(!P1_6){Delay(20);while(!P1_6);Delay(20);KeyNumber=7;}if(!P1_5){Delay(20);while(!P1_5);Delay(20);KeyNumber=11;}if(!P1_4){Delay(20);while(!P1_4);Delay(20);KeyNumber=15;}P1=0xFF;//全部置为高电平P1_0=0;//仅启动P1_0--即第四列if(!P1_7){Delay(20);while(!P1_7);Delay(20);KeyNumber=4;}if(!P1_6){Delay(20);while(!P1_6);Delay(20);KeyNumber=8;}if(!P1_5){Delay(20);while(!P1_5);Delay(20);KeyNumber=12;}if(!P1_4){Delay(20);while(!P1_4);Delay(20);KeyNumber=16;}return KeyNumber;}1.4.1矩阵键盘密码锁main函数:#include <REGX52.H>#include "Delay.h"#include "LCD1602.h"#include "MatrixKey.h"unsigned int KeyNumber;unsigned int PassWord,Count;//密码,位数void main(){LCD_Init();LCD_ShowString(1,1,"PassWord:");while(1){KeyNumber=MatrixKey();if(KeyNumber){if(KeyNumber<=10){//将10变成0,仅考虑0~9范围内if(Count<4){PassWord*=10;//每输入一位密码,当前密码左移一位 PassWord+=KeyNumber%10;//获取一位密码Count++;//计次}LCD_ShowNum(2,1,PassWord,4);//输出密码}if(KeyNumber==11){//清零Count=0;//清零次数PassWord=0;//清零密码LCD_ShowNum(2,1,PassWord,4);//更新显示}if(KeyNumber==12){//确认LCD_ShowString(1,12," ");if(PassWord==1976){LCD_ShowString(1,12,"OK");}else{LCD_ShowString(1,12,"ERROR");}//清零Count=0;PassWord=0;LCD_ShowNum(2,1,PassWord,4);//更新显示}}}}1.5定时器1.5.1按键控制LED流水灯模式TMOD:定时器寄存器:配置M1,M2为1 0-更改为16定时器模式0~65535:溢出时才进行中断判断每隔1us计数加一,总共定时时间65535us;赋初值64535-1000us(1ms)后计数器溢出,进行中断操作快捷生成定时器模块该函数未配置中断与中断优先级,且定时器时钟模式不需要定义定时器函数://1ms定时器void Timer0_Init(){//模式寄存器,高四位为计时器1,低四位为计时器2//高四位不变,低四位清零:10101100&11110000=10100000TMOD&=0xF0;//高四位不变,低四位赋1:10101100|00000001=10100001TMOD|=0x01;//控制寄存器;能单独对部分赋值TF0=0;//中断标志TR0=1;//运行控制位;1时运行T0进行计数//给定时器赋初值TH0=0xFC;//64535高八位TL0=0x18;//64535低八位//配置中断ET0=1;EA=1;//优先级选取PT0=0;}中断函数://定时器中断函数void Timer0_Rountine() interrupt 1{static unsigned int T0Count;//计数//复位TH0=0xFC;//64535高八位TL0=0x18;//64535低八位T0Count++;//每中断一次计数加一if(T0Count>=1000){//1ms中断一次,中断1000次则为1s //具体操作T0Count=0;P2_0=~P2_0;//闪烁}}主函数:#include <REGX52.H>#include <INTRINS.H>#include "Timer0.h"#include "Key.h"unsigned char KeyNumber,LEDMode;void main(){P2=0xFE;//点亮D1,给予循环移位初值Timer0_Init();//启用定时器while(1){KeyNumber=Key();if(KeyNumber){//按下独立按键if(KeyNumber==1){//S1为模式改变按键LEDMode++;if(LEDMode>=2){//仅有0|1两种模式LEDMode=0;}}}}}//中断操作void Timer0_Rountine() interrupt 1{ static unsigned int T0Count;//计数//给定时器赋初值复位TH0=0xFC;//64535高八位TL0=0x18;//64535低八位T0Count++;//每中断一次计数加一if(T0Count>=500){//0.5s操作一次T0Count=0;if(LEDMode){//模式1P2=_cror_(P2,1);//右移一位}else{//模式0P2=_crol_(P2,1);//左移一位}}}1.5.2定时器时钟:#include <REGX52.H>#include <INTRINS.H>#include "Timer0.h"#include "LCD1602.h"unsigned char Second,Minute,Hour;void main(){LCD_Init();//显示屏初始化LCD_ShowString(1,1,"Clock:");Timer0_Init();//启用定时器while(1){LCD_ShowNum(2,1,Hour,2);LCD_ShowString(2,3,":");LCD_ShowNum(2,4,Minute,2);LCD_ShowString(2,6,":");LCD_ShowNum(2,7,Second,2);}}//中断操作void Timer0_Rountine() interrupt 1{static unsigned int T0Count;//计数//给定时器赋初值复位TH0=0xFC;//64535高八位TL0=0x18;//64535低八位T0Count++;//每中断一次计数加一if(T0Count>=1000){//0.5s操作一次T0Count=0;Second++;if(Second==60){Minute++;Second=0;if(Minute==60){Hour++;Minute=0;if(Hour==25){Hour=Minute=Second=0;}}}}}1.6串口:1.6.1串口通信:配置波特率:1.6.2交互数据传输:#include <REGX52.H>//串口函数******************void UART_Init(){//配置串行控制寄存器,调整工作模式1SCON=0x50;//允许双向传输,REN置为1,配置使能//配置波特率选择位--需要配置定时器PCON|=0x80;//最高位置1,波特率加倍//定时器模式寄存器式//使用双八位模式(复位与计数分开)提高精度//清除定时器1模式位TMOD&=0x0F;//设定定时器1为八位自动重装方式TMOD|=0x20;//256溢出一次TL1=0xF4;//设定定时器初值TH1=0xF4;//设定定时器重装值ET1=0;//禁止定时器1中断TR1=1;//启动定时器1//使能中断EA=1;ES=1;}//发送函数void UART_SendByte(unsigned char Byte){SBUF=Byte;//发送数据到SBUF缓存器中即可进行传输//检测是否完成while(!TI);TI=0;}#ifndef __UART_H__#define __UART_H__/*串口函数输入:void输出:void功能:实现串口使用的初始化*/void UART_Init();/*串口发送函数输入:void输出:void功能:通过串口发送数据至接收端*/void UART_SendByte(unsigned char Byte);#endifmain:#include <REGX52.H>#include "Delay.h"#include "UART.h"void main(){UART_Init();while(1){}}//使能中断函数;发送/接收中断函数void UART_Routine() interrupt 4{if(RI==1){//限制仅为接收中断才进行后续操作P2=~SBUF;//外部设备传输数据存放在SBUF缓存器内 UART_SendByte(SBUF);//输出传入数据RI=0;}}1.7LED点阵屏:通过74HC595三个引脚控制八个LED 显示(新版板子是没有该八位LED 的)通过控制75HC595进行数据传输: #include <REGX52.H>//重新进行声明sbit RCK = P 3^5; //RCLKsbit SCK = P 3^6; //SRCLKsbit SER = P 3^4;//移位寄存器输入数据void _74HC595_WriteByte(unsigned char Byte){unsigned char i;for(i=0;i<8;i++){//从高位开始缓存数据SER=Byte&(0x80>>i);//非零置一0x80--10000000SCK=1;//赋予高电平进行移位SCK=0;//复位}RCK=1;//传输数据RCK=0;//复位}void main(){//初始化SCK=0;RCK=0;_74HC595_WriteByte(0xF0);while(1){}}1.7.1LED点阵屏显示动画:使用该软件进行数据读取MatrixLED_ShowColumn.c:#include <REGX52.H>#include "Delay.h"#include "MatrixLED_ShowColumn.h"//移位寄存器输入数据,控制段选void _74HC595_WriteByte(unsigned char Byte){unsigned char i;for(i=0;i<8;i++){//从高位开始缓存数据SER=Byte&(0x80>>i);//非零置一0x80--10000000SCK=1;//赋予高电平进行移位SCK=0;//复位}RCK=1;//传输数据RCK=0;//复位}//LED点阵屏void MatrixLED_ShowColumn(unsigned char Column,unsigned char Data){ _74HC595_WriteByte(Data);//段选MATRIX_LED_PORT=~(0x80>>Column);//位选0时出现压降,导通Delay(1);MATRIX_LED_PORT=0xFF;//位清零}//初始化void MatrixLED_Init(){SCK=0;RCK=0;}MatrixLED_ShowColumn.h:#ifndef _MATRIXLED_H__#define _MATRIXLED_H__//重新进行声明sbit RCK= P3^5;//RCLKsbit SCK= P3^6;//SRCLKsbit SER= P3^4;#define MATRIX_LED_PORT P0/*移位寄存器函数输入:Byte-点阵屏行数据输出:void功能:通过输入数据对LED点阵屏行(即位选)进行调整范围:0~7*/void _74HC595_WriteByte(unsigned char Byte);/*LED点阵屏函数输入:Column-位选 Data-段选输出:void功能:通过输入位选与段选实现LED点阵屏的动画演示*/void MatrixLED_ShowColumn(unsigned char Column,unsigned char Data);/*LED点阵屏初始化函数输入:void输出:void功能:对LED相关参数进行初始化*/void MatrixLED_Init();#endifmain.c:#include <REGX52.H>#include "Delay.h"#include "MatrixLED_ShowColumn.h"unsigned char code Animation[]={//存放在flash内存中,避免占用RAM内存0x00,0x40,0x20,0x1F,0x20,0x40,0x00,0x00,0x00,0x40,0x40,0x7F,0x40,0x40,0x00,0x00,0x00,0x7E,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x76,0x91,0x89,0x6E,0x00,0x00,0x00,0x00,0x7F,0x88,0x88,0x70,0x00,0x00,};void main(){//只要是局部变量的定义都要放在所在函数体内的第一行unsigned char j,Offset,Count;MatrixLED_Init();while(1){for(j=0;j<8;j++){MatrixLED_ShowColumn(j,Animation[j+Offset]);}Count++;if(Count>10){//扫描十遍偏移一次Count=0;Offset+=8;Delay(200);if(Offset>32){//防止溢出Offset=0;}}}}1.8DS1032定时时钟:从上到下依次存储不同的时间左边两列为其地址命令字第六位:1-RAM;0-CK,对时钟进行操作(有横线代表低电平有效)仅改变前七位,最后一位恒为1前一个字节是命令字,后一个是数据重新定义该三个端口1.8.1DS1302固定时钟主函数:#include <REGX52.H>#include "Delay.h"#include "DS1302.h"#include "LCD1602.h"void main(){LCD_Init();DS1302_Init();LCD_ShowString(1,1," - - ");LCD_ShowString(2,1," : : ");DS1302_SetTime();//设置时间//DS1302芯片内部自动会进行时间进位,不需要手动设置,只需要输入初始时间即可while(1){DS1302_ReadTime();//读入时间LCD_ShowNum(1,1,DS1302_Time[0],2);LCD_ShowNum(1,4,DS1302_Time[1],2);LCD_ShowNum(1,7,DS1302_Time[2],2);LCD_ShowNum(2,1,DS1302_Time[3],2);LCD_ShowNum(2,4,DS1302_Time[4],2);LCD_ShowNum(2,7,DS1302_Time[5],2);}}DS1302.c:#include <REGX52.H>#include "Delay.h"//重新定义端口名称,便于模块化集成sbit DS1302_SCLK=P3^6;sbit DS1302_IO=P3^4;sbit DS1302_CE=P3^5;#define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_DATE 0x86#define DS1302_MONTH 0x88#define DS1302_DAY 0x8A#define DS1302_YEAR 0x8C#define DS1302_WP 0x8E//Year,Month,Day,Hour,Minute,Second,Weekdayunsigned char DS1302_Time[]={22,5,22,21,19,55,7};//DS1302初始化,将使能端置0,SCLK置0void DS1302_Init(void){DS1302_CE=0;DS1302_SCLK=0;}//写入操作void DS1302_WriteByte(unsigned char Command, unsigned char Data){ //写入预操作//Command的第零位赋予IO口,第零位是标志位,判断读/写//Command与Data都是通过上升沿进行判断,因此总共有16个脉冲unsigned char i;DS1302_CE=1;//进行Command判断for(i=0;i<8;i++){DS1302_IO=Command&(0x01<<i);//进行电平变化,产生上升沿与下降沿DS1302_SCLK=1;Delay(1);//一般需要增加延时,具体参考芯片手册DS1302_SCLK=0;}//进行数据写入for(i=0;i<8;i++){DS1302_IO=Data&(0x01<<i);DS1302_SCLK=1;Delay(1);DS1302_SCLK=0;}//写入末操作DS1302_CE=0;}unsigned char DS1302_ReadByte(unsigned char Command){//读入预操作unsigned char i;unsigned char Data=0x00;Command|=0x01;//此处将最低位,置成1,使输入的写Command变成读Command DS1302_CE=1;//读入的Command是上升沿,而Data是下降沿,因此总共有15个脉冲for(i=0;i<8;i++){DS1302_IO=Command&(0x01<<i);//调整位置确保脉冲与Data一致DS1302_SCLK=0;DS1302_SCLK=1;}//读入数据//IO口默认为0,因此输入的数据为1时,for(i=0;i<8;i++){DS1302_SCLK=1;DS1302_SCLK=0;if(DS1302_IO){Data|=(0x01<<i);}}//读入末操作DS1302_CE=0;DS1302_IO=0;return Data;}unsigned char ChangeToDec(unsigned char Number){return (Number/16*10+Number%16);}。
单片机原理及应用-C51语言李全利
4.3.3 LCD1602模块的命令
序号
指令
RS R/W D7 D6 D5 D4 D3 D2 D1 D0
1 清屏 2 光标归位 3 输入模式设置 4 显示与不显示设置
0
0 00000001
0
0 0000001*
0
0 0 0 0 0 0 1 I/D S
0
0 0 0 0 0 1 DCB
5
光标或屏幕内容移位 选择
字型
00000000B 00000001B 00000010B 00000011B
00000100B 00000101B 00000110B 00000111B
字符00H(或08H)
unsigned char code WeekWord[]=
{
}
数据
LoadCgram(WeekWord);
00000100B DispChar(0,1,0); 00000100B
单片机原理及应用-C51语言李全利
按键 键盘 开关
单片机 最小系统 AT89S52
LED 数码管 蜂鸣器 LCD
每根口线最大可吸收10mA的(灌)电流 P0口吸收电流的总和不能超过26mA P1、P2和P3每个口吸收电流的总和限制在15mA 4个口所有口线的吸收电流总和限制在71mA
CGROM 字符发生器,存储不同的点阵字符图形表, 每个字符都有固定的代码。
CGRAM 自定义字符发生器,可定义8个字符图形。
DDRAM 显示缓冲区。
CGROM
例:代码41H显示字符“A”。
CGRAM
可以自定义8个字符: 0—7 或8--15
CGRAM的内容:
CGRAM地址
4.3.2 LCD1602模块的组成
C51与键盘、显示器、拨盘、打印机的接口设计
图10-6 键盘开关及其波形
①抖动期(t1、t3):一般为5~10ms;
②稳定的闭合期间(t2):一般为十分之几秒到几秒;
③断开期(t0、t4)
12
2. 按键的确认
检测行线电平(图10-6)
高电平:断开; 低电平:闭合。 为了确保对一次按键动作只确认一次按键有效,必须消除抖 动期t1和t3的影响。 3.如何消除按键的抖动 常用软件来消除按键抖动。 基本思想:检测到有键按下,键对应的行线为低,软件延时 10ms后,行线如仍为低,则确认该行有键按下。 当键松开时,行线变高,软件延时10ms后,行线仍为高,说 明按键已松开。 采取以上措施,躲开了两个抖动期t1和t3的影响。
列为按键所在列。
P1.4~P1.7全为“0”,读P1.0~P1.3的状态,则P1.0=0,
其余为1。第4行电平有变化,说明第4列有键按下。 结合上述两步,可确定按键所在行和列。
20
图10-10 线反转法原理图
21
10.2.3 键盘的工作方式
单片机在忙于各项工作任务时,如何兼顾键盘的输入,取 决于键盘的工作方式。
19
b. 线反转法 只需两步便能获得此按键所在的行列值,线反转法的原理如
图10-10。假设3号键被按下。 第1步:列线输出为全低电平,则行线中电平由高变低的所
在行为按键所在行。
P1.0~P1.3全为“0”,读P1.4~P1.7的状态,则P1.4=0,其
余为1。第1行电平有变化,说明第1行有键按下。 第2步:行线输出为全低电平,则列线中电平由高变低所在
14
图10-7 独立式键盘接口电路
15
图10-8为82C55扩展I/O口的独立式按键接口电路。
图10-8 通过82C55扩展的独立式键盘接口
单片机C语言-第3章51单片机P0-P3口的C51编程3
3.3.3 多个按钮型开关—键盘
2.独立式键盘接口技术
当按键的数量比较少(≤8)时,可采用独立式按键硬 件结构。独立式按键是指直接采用一根 I/O口线构成的 单个按键电路。每个独立式按键单独占用一根I/O口线, 每根I/O口线上的按键的工作状态不会影响其他I/O口线 的工作状态。
• 分析:
• 相当于S1为一个控制开关,控制着 灯的亮、灭闪烁;
• 与例题3-8不同。定义一个位单元, 按键每动作一次,该位单元取反:该单 元为0时,灯全亮,该单元为1时,灯闪 烁。
• include<reg51.h> • #define uchar unsigned char • #define uint unsigned int • sbit S1=P3^2; • bit key=0; //定义一个位,存储按键的动作(偶、奇) • void dlxms( uint xms) • { uint t1, t2; • for( t1=0; t1<xms; t1++) • for( t2=0; t2<110; t2++); •}
• #define uint unsigned int
• uchar data keycode=8;
//键值的初值设为8
• uchar data dir_buf;
//显示缓冲区
• code uchar dirtab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0xbf};//显 示的代码表
• sbit K2=P1^6;
51单片机:独立按键与矩阵按键控制数码管
51单⽚机:独⽴按键与矩阵按键控制数码管⼀,独⽴按键注意⼀下⼏点>按下的时候,电压被拉低,所以IO⼝要传低电平( 0x0 )>按下的时候要消除抖动 ( 延时10ms ),在判断,是否还是低电平,再做业务处理下⾯这段程序,就是通过⼀个独⽴按键连接到p1⼝,控制静态数码管的⼀段进⾏亮和灭的切换。
#include <reg52.h>sbit key_control = P1^0;sbit led = P0^0;typedef unsigned char u8;typedef unsigned int u16;void delay( u16 i ){while( i-- );}void key_press(){if( key_control == 0x0 ) {delay( 1110 );if( key_control == 0x0 ){led = ~led;}while( !key_control );}}void main (){/*while( 1 ){if( key_control == 0x0 ) {delay( 1110 ); //⼤概10msif ( key_control == 0x0 ) {led = 1;}}else if( key_control == 0x1 ) {delay( 1110 );if ( key_control == 0x1 ) {led = 0;}}}*/led = 0;while( 1 ) {key_press();}}⼆,当按键⽐较多的时候,⽤矩阵按钮,因为如果不⽤矩阵按钮,⼀个独⽴按键需要⼀个IO⼝,浪费资源。
如: 16个独⽴按键需要16个io⼝,⽽16个矩阵按键(4x4,⼀共8个管脚)需要8个IO⼝下⾯的程序,通过16个矩阵按钮,控制静态数码管,显⽰0~F#include <reg52.h>#define GPIO_DIG P0 //段选数码管#define GPIO_KEY P1 //矩阵按键typedef unsigned char u8;typedef unsigned int u16;void delay( u16 i ){while( i-- );}u8 key_value;//静态数码管段码u8 character [16] = { 0xC0, 0xF9 , 0xA4 , 0xB0 , 0x99 , 0x92,0x82 , 0xF8 , 0x80 , 0x90 , 0x88 , 0x83,0xC6 , 0xA1 , 0x86 , 0x8E};void key_down(){u8 count = 0;//⾏列扫描判断哪个键被按下GPIO_KEY = 0x0F; //⾼四位全部输出低电平,低四位输出⾼电平-->判断被按下的按钮所在的列if( GPIO_KEY != 0x0F ) { //有按键按下delay( 1110 ); //消除抖动if( GPIO_KEY != 0x0F ){switch( GPIO_KEY ){case0x07:key_value = 0; //矩阵第1列的按钮被按下break;case0x0B:key_value = 1; //矩阵第2列的按钮被按下break;case0x0D:key_value = 2; //矩阵第3列的按钮被按下break;case0x0E:key_value = 3; //矩阵第4列的按钮被按下break;}GPIO_KEY = 0xF0; //⾼四位输出⾼电平,低四位输出低电平-->判断被按下的按钮所在的⾏switch( GPIO_KEY ){case0x70:key_value = key_value; //矩阵第1⾏的按钮被按下break;case0xB0:key_value = key_value + 4; //矩阵第2⾏的按钮被按下break;case0xD0:key_value = key_value + 8; //矩阵第3⾏的按钮被按下break;case0xE0:key_value = key_value + 12; //矩阵第4⾏的按钮被按下break;}GPIO_DIG = character[key_value];//如果⼀直按下按键,等待500ms,强制退出while( ( count < 50 ) && ( GPIO_KEY != 0xF0 ) ) {count++;}}}}void main (){while( 1 ) {key_down();}}。
Keil C51操作入门
广州周立功单片机发展有限公司
Tel:(020)38730976,38730977
Fax:38730925
“E:\Project\LedFlash” ,其中“LedFlash”是新建的文件夹。我们建议:今后每新建 一个工程都要在适当的磁盘位置新建一个文件夹用来保存工程文件,以方便管理, 并养成良好的习惯。最后,为工程取名为“LedFlash” ,并保存。参见图 1.3。
图 1.6 保存新建的源程序文件
z 添加源程序文件到工程中。现在,一个空的源程序文件“main.c”已经建立,但是 这个文件与刚才新建的工程之间并没有什么内在联系。我们需要把它添加到工程中 去。单击 Keil C51 软件左边项目工作窗口“Target 1”上的“+” ,将其展开。然后 右击“Source Group 1”文件夹,会弹出如图 1.7 所示的选择菜单。单击其中的“Add Files to Group 'Source Group 1'”项,将弹出如图 1.8 所示的对话框。 z 先选择文件类型为“ C Source file (*.c) ” ,这时,对话框内将出现刚才保存过的 “main.c” 。单击文件“main.c” ,再按一次“Add”按钮(请不要多次点击“Add” 按钮) ,最后按“Close”按钮。这时,源程序文件“main.c”已经出现在项目工作窗 口的“Source Group 1”文件夹内,可以单击左边的“+”展开后查看。
广州周立功单片机发展有限公司
Tel:(020)38730976,38730977
Fax:38730925
z 单击 Keil C51 工具栏的“ ”图标,弹出名为“Options for Target ‘Target 1’”的对 话框。 单击 “Output” 标签页, 选中 “Create HEX File” 项, 然后 “确定” 。 参见图 1.9。
键盘显示的C51编程
第6章MCS-51系列单片机键盘/显示的C51编程 (2)6.1 七段数码显示器的C51编程 (2)6.1.1 7段LED显示器基础知识 (2)6.1.2 七段数码静态显示的C51编程 (3)6.1.3 七段数码动态显示的C51编程 (6)6.1.4 串行口控制的LED显示的C51编程 (10)6.2 键盘接口的C51编程 (11)6.2.1 键盘的基础知识 (11)6.2.2 独立式键盘接口的C51编程 (12)6.2.3 矩阵键盘的C51编程 (14)6.3 点阵LED显示器接口的C51编程 (20)6.3.1 点阵LED显示器基础知识 (20)6.3.2 一个5×7点阵字符显示的C51编程 (21)6.3.3 一个8×8点阵字符串显示的C51编程 (22)6.3.4 两个8×8点阵字符串显示的C51编程 (24)6.4 液晶显示器的C51编程 (26)6.4.1 LCD基础知识 (26)6.4.2 字符型LCD1602应用的C51编程 (27)本章小结 (36)习题 (37)第6章MCS-51系列单片机键盘/显示的C51编程在单片机应用系统中,除了完成基本的功能外,另一个最重要的任务是设计优秀的人机交互接口。
人机交互接口用来实现控制命令及数据的输入,并且将系统运行信息反映给操作者。
系统运行信息的反映是通过各种显示器来完成的,主要包括八段数码显示、液晶显示、点阵显示等;控制命令及数据的输入时通过键盘来实现的。
本章主要介绍键盘及显示的C51编程技术。
6.1 七段数码显示器的C51编程在单片机应用系统中,七段LED显示器的应用非常广泛。
6.1.1 七段LED显示器基础知识1.结构与原理通常的七段LED显示器中有8个发光二极管,管脚如图6-1(a)所示。
a、b、c、d、e、f、g、dp称为LED的段,公共端com称为LED的位。
从管脚a~dp输入不同的8位二进制数,可显示不同的数字或字符。