单片机按键扫描程序和显示程序及延时程序解析

单片机按键扫描程序和显示程序及延时程序解析

单片机按键扫描程序和显示程序及延时程序解析

//程序中没有做按键去抖,也没有考虑多个键同时按下的情况。

//最低两位数码管显示相应的按键(如按下S10,在显示10;按下S25,则显示25)

//无按键按下的时候显示FF

//按键跟按键的扫描结果满足如下关系:

//按键扫描结果(result)按键扫描结果

//K100XE7K180XB7

//K110XEBK190XBB

//K120XEDK200XBD

//K130XEEK210XBE

//K140XD7K220X77

//K150XDBK230X7B

//K160XDDK240X7D

//K170XDEK250X7E

#include//包含单片机内部资源预定义

__CONFIG(0x1832);

//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡

intresult;

voiddelay();//delay函数申明

voidinit();//I/O口初始化函数申明

voidsCAN();//按键扫描程序申明

voiddisplay(intx);//显示函数申明

//---------------------------------------------------

//主程序

voidmain()

{

单片机89C52行列式键盘扫描程序(汇编)

实验八键盘扫描显示实验 所需软硬件: Keil STC-ISP MCS-51 89C52实验箱 程序清单: 基于汇编语言 //连线P0接8列(同时也是数码管的位选线)高电平选中某位。P3低两位接行P1接数码管(段选线)低电平选中某段亮。 ORG 0000H LJMP MAIN MAIN: MOV 30H,#00H MOV 31H,#00H MOV 32H,#00H MOV 33H,#00H MOV 34H,#00H MOV 35H,#00H BEGIN: ACALL SCAN ACALL CHECK ACALL DISP SJMP BEGIN //子程序SCAN 全扫描2次扫描去抖 SCAN:;全扫描 MOV R0,#00H;去抖,扫描2次计数标志

MOV A,#00H MOV P0,A;送列扫描码 LOOP: MOV A,P3;回读行信号 ANL A,#03H;只取低两位 INC R0 CJNE A,#03H,K1 CLR F0;无键,置标志位为0 K1: NOP NOP CJNE R0,#02H,LOOP;去抖,扫描2次 SETB F0;有键,置标志位为1 RET //子程序CHECK 逐列扫描确定键码 CHECK: MOV R1,#0FEH ;开始逐列扫描,从第0列开始 MOV R4,#00H;记录列号 MOV R5,#00H;记录行号 MOV A,R1 PUSH ACC;压栈保留第0列扫描码 LOOP1: MOV P0,A;送列扫描码 MOV A,P3 ANL A,#03H CJNE A,#03H,K2;有键转K2确定为哪一行 POP ACC;无键扫描下一列 RL A INC R4 CJNE R4,#08H,LOOP1 ; 是否扫描进行到最后一列 RET K2: DEC SP;为保证堆栈平衡 CJNE A,#00H,K3;分支判断,看是否为第一行 SJMP OVER K3: MOV A, R5 ADD A,#08H MOV R5,A;不是第一行,就是第二行,行码加8 OVER: MOV A,R4 ADD A,R5;行码+列码=键码 PUSH ACC;键码入栈保护 NOP

STC12系列单片机C语言的延时程序

STC12系列单片机C语言的延时程序 本举例所用CPU 为STC12C5412 系列12 倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。共有三条延时函数说明如下:函数调用 分两级:一级是小于10US 的延时,二级是大于10US 的延时 //====================小于10US 的【用1US 级延时】 ====================//----------微秒级延时---------for(i=X;i>X;i--) 延时时间 =(3+5*X)/12 提示(单位us, X 不能大于255)//================大于10US0;Ms--)for(i=26;i>0;i--);}i=[(延时值-1.75)*12/Ms-15]/4 如想延时60US 则 i=[(60-1.75)*12/6-15]/4=25.375≈26; 修改i 的值=26,再调用上面的【10US 级延时函数】Delay10us(6); 则就精确延时60US;如果想延时64US 可以用这二种函数组合来用: Delay10us(6); for(i=9;i>X;i--) 共延时64US//============== 对于大于20Ms 的可用中断来实现程序运行比较好===============中断用定 时器0, 1Ms 中断:void timer0(void) interrupt 1{ TL0=(0xffff-1000+2)% 0x100;TH0=(0xffff-1000+2)/0x100; //每毫秒执行一次if(DelayMs_1>0) DelayMs_1--;//大于20Ms 延时程序}函数调用void DelayMs(uint a)//延时 a 乘以1(ms)的时间。{ DelayMs_1=a; while(DelayMs_1);}如果延时50Ms 则函数值为DelayMs(50)tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

51单片机04矩阵按键逐行扫描,行列扫描代码

矩阵键盘扫描原理 方法一: 逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。 方法二: 行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。

//行列扫描 #include #define GPIO_KEY P0 #define GPIO_LCD P2 unsigned char code a[17]= {~0xfc,~0x60,~0xda,~0xf2,~0x66,~0xb6,~0xbe,~0xe0, ~0xfe,~0xf6,~0xee,~0x3e,~0x9c,~0x7a,~0xde,~0x8e,~0x00}; //按位取反的用法 void delay10ms(); void keydown();//要与下面的定义一致 void main() { GPIO_LCD=a[16];//初始化数码管 while(1) { keydown(); } }

void delay10ms() { unsigned char a,b; for(a=38;a>0;a--) for(b=130;b>0;b--); } void keydown() //检测按下,按下时需要消抖,检测松开,返回按键值//没有按键时保持 { unsigned char n=0,key; GPIO_KEY=0x0f; if(GPIO_KEY!=0x0f)//读取按键是否按下 { delay10ms(); //延时10ms消抖 if(GPIO_KEY!=0x0f)//再次检测按键是否按下 { GPIO_KEY=0x0f;//测试列 switch(GPIO_KEY) { case 0x07: key=0;break;

单片机矩阵键盘扫描程序

#include #include #define uint unsigned int #define uchar unsigned char sbit E=P2^7; //1602使能引脚 sbit RW=P2^6; //1602读写引脚 sbit RS=P2^5; //1602数据/命令选择引脚 uint keyflag ; //键盘正在读取标志位,如果Keyflag为1 ,表示正在读取键盘,停止其他功能; char x,y,m,n,c; //Keyflag为0,读取键盘结束,恢复其他功能 char flag1=0; //频率范围10~1000Hz uchar Hrate = 0; //一个周期内高点平占据时间 uchar Lrate = 0; //一个周期内低电平占据时间 uint FREQ0; //定时器T0的计数变量// uint FREQ1; //定时器T1的计数变量// sbit P2_1=P2^0; //设置P2.1,作为信号输出口// uint disbuf[3]; uint figure=0; int sum2=0; int sum1=0; int flag=0; uint count=0; uint max=0; uint disbuf_temp=0; /******************************************************************** * 名称: 1602显示延时函数delay() * 功能: 延时,延时时间大概为5US。

* 输出: 无 ***********************************************************************/ void delay() { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } /******************************************************************** * 名称: bit Busy(void) * 功能: 这个是一个读状态函数,读出函数是否处在忙状态 * 输入: 输入的命令值 * 输出: 无 ***********************************************************************/ bit Busy(void) { bit busy_flag = 0; RS = 0; RW = 1; E = 1; delay(); busy_flag = (bit)(P0 & 0x80); E = 0; return busy_flag; } /******************************************************************** * 名称: wcmd(uchar del) * 功能: 1602命令函数 * 输入: 输入的命令值 * 输出: 无 ***********************************************************************/ void wcmd(uchar del) { while(Busy()); RS = 0; RW = 0; E = 0; delay(); P0 = del; delay(); E = 1;

单片机4X4键盘扫描和显示课程设计

二、设计内容 1、本设计利用各种器件设计,并利用原理图将8255单元与键盘及数码管显示单元连接,扫描键盘输入,最后将扫描结果送入数码管显示。键盘采用4*4键盘,每个数码管可以显示0-F共16个数。将键盘编号,记作0-F,当没按下其中一个键时,将该按键对应的编号在一个数码管上显示出来,当在按下一个 键时,便将这个按键的编号在下一个数码管上显示,数码管上 可以显示最近6次按下的按键编号。 设计并实现一4×4键盘的接口,并在两个数码管上显示键盘所在的行与列。 三、问题分析及方案的提出 4×4键盘的每个按键均和单片机的P1口的两条相连。若没有按键按下时,单片机P1口读得的引脚电平为“1”;若某一按键被按下,则该键所对应的端口线变为地电平。单片机定时对P1口进行程序查询,即可发现键盘上是否有按键按下以及哪个按键被按下。 实现4×4键盘的接口需要用到单片机并编写相应的程序来识别键盘的十六个按键中哪个按键被按下。因为此题目还要求将被按下的按键显示出来,因此可以用两个数码管来分别显示被按下的按键的行与列

表示任意一个十六进制数)分别表示键盘的第二行、第三行、第四行;0xXE、0xXD、0xXB、0xX7(X表示任意一个十六进制数)则分别表示键盘的第一列、第二列、第三列和第四列。例如0xD7是键盘的第二行第四列的按键 对于数码管的连接,采用了共阳极的接法,其下拉电阻应保证芯片不会因为电流过大而烧坏。 五、电路设计及功能说明 4×4键盘的十六个按键分成四行四列分别于P1端口的八条I/O 数据线相连;两个七段数码管分别与单片机的P0口和P2口的低七 位I/O数据线相连。数码管采用共阳极的接法,所以需要下拉电阻 来分流。结合软件程序,即可实现4×4键盘的接口及显示的设计。 当按下键盘其中的一个按键时,数码管上会显示出该按键在4×4键 盘上的行值和列值。所以实现了数码管显示按键位置的功能 四、设计思路及原因 对于4×4键盘,共有十六个按键。如果每个按键与单片机的一个引脚相连,就会占用16个引脚,这样会使的单片机的接口不够用(即使够用,也是对单片机端口的极大浪费)。因此我们应该行列式的接法。行列式非编码键盘是一种把所有按键排列成行列矩阵的键盘。在这种键若没有按键按下时,单片机从P1口读得的引脚电平为“1”;若某一按键被按下,则该键所对应的端口线变为地电平。因此0xEX(X表示任意4×4键盘的第一行中的某个按键被按下,相应的0xDX、0xBX、0x7X(X 二、实验内容

51单片机的几种精确延时

51单片机的几种精确延时实现延时 51单片机的几种精确延时实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。 1 使用定时器/计数器实现精确延时 单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。 在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC 语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。 2 软件延时与时间计算 在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。下面介绍几种软件延时的方法。 2.1 短暂延时 可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,如Delay10us( )、Delay25us( )、Delay40us( )等存放在一个自定义的C文件中,需要时在主程序中直接调用。如延时10 μs的延时函数可编写如下: void Delay10us( ) { _NOP_( ); _NOP_( ); _NOP_( ); _NOP_( ); _NOP_( ); _NOP_( ); } Delay10us( )函数中共用了6个_NOP_( )语句,每个语句执行时间为1 μs。主函数调用Delay10us( )时,先执行一个LCALL指令(2 μs),然后执行6个_NOP_( )语句(6 μs),最后执行了一个RET指令(2 μs),所以执行上述函数时共需要10 μs。可以把这一函数

基于51单片机的精确延时(微秒级)

声明: *此文章是基于51单片机的微秒级延时函数,采用12MHz晶振。 *此文章共包含4个方面,分别是延时1us,5us,10us和任意微秒。前三个方面是作者学习过程中从书本或网络上面总结的,并非本人所作。但是延时任意微秒函数乃作者原创且亲测无误。欢迎转载。 *此篇文章是作者为方便初学者使用而写的,水平有限,有误之处还望大家多多指正。 *作者:Qtel *2012.4.14 *QQ:97642651 ----------------------------------------------------------------------------------------------------------------------序: 对于某些对时间精度要求较高的程序,用c写延时显得有些力不从心,故需用到汇编程序。本人通过测试,总结了51的精确延时函数(在c语言中嵌入汇编)分享给大家。至于如何在c 中嵌入汇编大家可以去网上查查,这方面的资料很多,且很简单。以12MHz晶振为例,12MHz 晶振的机器周期为1us,所以,执行一条单周期指令所用时间就是1us,如NOP指令。下面具体阐述一下。 ----------------------------------------------------------------------------------------------------------------------1.若要延时1us,则可以调用_nop_();函数,此函数是一个c函数,其相当于一个NOP指令,使用时必须包含头文件“intrins.h”。例如: #include #include void main(void){ P1=0x0; _nop_();//延时1us P1=0xff; } ----------------------------------------------------------------------------------------------------------------------2.延时5us,则可以写一个delay_5us()函数: delay_5us(){ #pragma asm nop #pragma endasm } 这就是一个延时5us的函数,只需要在需要延时5us时调用此函数即可。或许有人会问,只有一个NOP指令,怎么是延时5us呢? 答案是:在调用此函数时,需要一个调用指令,此指令消耗2个周期(即2us);函数执行完毕时要返回主调函数,需要一个返回指令,此指令消耗2个周期(2us)。调用和返回消耗了2us+2us=4us。然后再加上一个NOP指令消耗1us,不就是5us吗。

单片机一些常用的延时与中断问题及解决方法

单片机一些常用的延时与中断问题及解决方法 延时与中断出错,是单片机新手在单片机开发应用过程中,经常会遇到的问题,本文汇总整理了包含了MCS-51系列单片机、MSP430单片机、C51单片机、8051F的单片机、avr单片机、STC89C52、PIC单片机…..在内的各种单片机常见的延时与中断问题及解决方法,希望对单片机新手们,有所帮助! 一、单片机延时问题20问 1、单片机延时程序的延时时间怎么算的? 答:如果用循环语句实现的循环,没法计算,但是可以通过软件仿真看到具体时间,但是一般精精确延时是没法用循环语句实现的。 如果想精确延时,一般需要用到定时器,延时时间与晶振有关系,单片机系统一般常选用 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。 2、求个单片机89S51 12M晶振用定时器延时10分钟,控制1个灯就可以 答:可以设50ms中断一次,定时初值,TH0=0x3c、TL0=0xb0。中断20次为1S,10分钟的话,需中断12000次。计12000次后,给一IO口一个低电平(如功率不够,可再加扩展),就可控制灯了。 而且还要看你用什么语言计算了,汇编延时准确,知道单片机工作周期和循环次数即可算出,但不具有可移植性,在不同种类单片机中,汇编不通用。用c的话,由于各种软件执行效率不一样,不会太准,通常用定时器做延时或做一个不准确的延时,延时短的话,在c中使用汇编的nop做延时 3、51单片机C语言for循环延时程序时间计算,设晶振12MHz,即一个机器周期是1us。for(i=0,i<100;i++) for(j=0,j<100;j++) 我觉得时间是100*100*1us=10ms,怎么会是100ms 答: 不可能的,是不是你的编译有错的啊

51单片机矩阵键盘扫描程序

/*----------------------------------------------- 名称:矩阵键盘依次输入控制使用行列逐级扫描 论坛:https://www.360docs.net/doc/dc11113034.html, 编写:shifang 日期:2009.5 修改:无 内容:如计算器输入数据形式相同从右至左使用行列扫描方法 ------------------------------------------------*/ #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #define DataPort P0 //定义数据端口程序中遇到DataPort 则用P0 替换 #define KeyPort P1 sbit LATCH1=P2^2;//定义锁存使能端口段锁存 sbit LATCH2=P2^3;// 位锁存 unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};// 显示段码值0~F unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码 unsigned char TempData[8]; //存储显示值的全局变量 void DelayUs2x(unsigned char t);//us级延时函数声明 void DelayMs(unsigned char t); //ms级延时 void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数 unsigned char KeyScan(void);//键盘扫描 unsigned char KeyPro(void); void Init_Timer0(void);//定时器初始化 /*------------------------------------------------ 主函数 ------------------------------------------------*/ void main (void) { unsigned char num,i,j; unsigned char temp[8]; Init_Timer0(); while (1) //主循环 { num=KeyPro();

51单片机精确延时源程序

51单片机精确延时源程序 一、晶振为 11.0592MHz,12T 1、延时 1ms: (1)汇编语言: 代码如下: DELAY1MS: ;误差 -0.651041666667us MOV R6,#04H DL0: MOV R5,#71H DJNZ R5,$ DJNZ R6,DL0 RET (2)C语言: void delay1ms(void) //误差 -0.651041666667us { unsigned char a,b; for(b=4;b>0;b--) for(a=113;a>0;a--); } 2、延时 10MS: (1)汇编语言: DELAY10MS: ;误差 -0.000000000002us MOV R6,#97H DL0: MOV R5,#1DH DJNZ R5,$ DJNZ R6,DL0

RET (2)C语言: void delay10ms(void) //误差 -0.000000000002us { unsigned char a,b; for(b=151;b>0;b--) for(a=29;a>0;a--); } 3、延时 100MS: (1)汇编语言: DELAY100MS: ;误差 -0.000000000021us MOV R7,#23H DL1: MOV R6,#0AH I

棋影淘宝店:https://www.360docs.net/doc/dc11113034.html,QQ:149034219 DL0: MOV R5,#82H DJNZ R5,$ DJNZ R6,DL0 DJNZ R7,DL1 RET (2)C语言: void delay100ms(void) //误差 -0.000000000021us { unsigned char a,b,c; for(c=35;c>0;c--) for(b=10;b>0;b--) for(a=130;a>0;a--); } 4、延时 1S: (1)汇编语言: DELAY1S: ;误差 -0.00000000024us MOV R7,#5FH DL1: MOV R6,#1AH DL0: MOV R5,#0B9H DJNZ R5,$ DJNZ R6,DL0 DJNZ R7,DL1 RET (2)C语言: void delay1s(void) //误差 -0.00000000024us { unsigned char a,b,c; for(c=95;c>0;c--) for(b=26;b>0;b--)

C51精确延时

C51中精确延时 C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章51单片机Keil C 延时程序的简单研究,作者:InfiniteSpace Studio/isjfk,写得不错,他是用while(--i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振12MHz,一个机器周期1us.) 在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响. 一. 500ms延时子程序 程序: void delay500ms(void) { unsigned char i,j,k; for(i=15;i>0;i--) for(j=202;j>0;j--) for(k=81;k>0;k--); } 产生的汇编: C:0x0800 7F0F MOV R7,#0x0F C:0x0802 7ECA MOV R6,#0xCA C:0x0804 7D51 MOV R5,#0x51 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C:0x080C 22 RET 计算分析: 程序共有三层循环 一层循环n:R5*2 = 81*2 = 162us DJNZ 2us 二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值1us = 3us 三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值1us = 3us 循环外: 5us 子程序调用2us + 子程序返回2us + R7赋值1us = 5us 延时总时间= 三层循环+ 循环外= 499995+5 = 500000us =500ms 计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5 二. 200ms延时子程序 程序: void delay200ms(void) { unsigned char i,j,k; for(i=5;i>0;i--) for(j=132;j>0;j--)

51单片机键盘设置

\\\§8.3 键盘接口技术 一、键盘输入应解决的问题 键盘是一组按键的集合,它是最常用的单片机输入设备. 操作人员可以通过键盘输入数据或命令,实现简单的人机通讯。 键是一种常开型按钮开关,平时(常态)键的二个触点处于断开状态,按下键时它们才闭合(短路)。 键盘分编码键盘和非编码键盘。 键盘上闭合键的识别由专用的硬件译码器实现并产生编号或键值的称为编码键盘, 如:ASCⅡ码键盘、BCD码键盘等; 靠软件识别的称为非编码键盘。 在单片机组成的测控系统及智能化仪器中用得最多的是非编码键盘。 本节着重讨论非编码键盘的原理、接口技术和程序设计。 键盘中每个按键都是—个常开关电路,如图所示。

1.按键的确认:P1.7=1 无按键; P1.7=0 有按键; 2.去抖动 去抖动的方法: ①硬件去抖动采用RS触发器: 优点: 速度快,实时, 缺点: 增加了硬件成本 ②软件去抖动采用延时方法 延时5—10ms 延时5—10ms P1.7=0 确认P1.7=0 P1.7=1 (去前沿抖动) (去后沿抖动) 二、独立式键盘

每个I/O口连接一个按,S1 P1.0 S2 P1.1 ………………………. S8 P1.7 软件: START:MOV P1,#0FFH ;置P1口为高电平 JNB P1.0, RS1 ; S1按下,程序去执行RS1 JNB P1.1, RS2 ; S2按下,程序去执行RS2

JNB P1.2, RS3 ; S3按下,程序去执行RS3 JNB P1.3, RS4 ; S4按下,程序去执行RS4 JNB P1.4, RS5 ; S5按下,程序去执行RS5 JNB P1.5, RS6 ; S6按下,程序去执行RS6 JNB P1.6, RS7 ; S7按下,程序去执行RS7 JNB P1.7, RS8 ; S8按下,程序去执行RS8 AJMP START ; 继续扫描按键 …………. RS1: AJMP PK1 ; RS2: AJMP PK2 ; RS3: AJMP PK3 ; RS4: AJMP PK4 ; RS5: AJMP PK5 ; RS6: AJMP PK6 ; RS7: AJMP PK7 ; RS8: AJMP PK8 ; AJMP START ; 无键按下,继续扫描………………… PK1: ……….. ;按键S1功能处理程序 AJMP START ;处理S1按键后, 继续扫描PK2: ……….. ;按键S2功能处理程序

单片机精确毫秒延时函数

单片机精确毫秒延时函数 实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。今天主要介绍软件延时以及单片机精确毫秒延时函数。 单片机的周期介绍在电子技术中,脉冲信号是一个按一定电压幅度,一定时间间隔连续发出的脉冲信号。脉冲信号之间的时间间隔称为周期;而将在单位时间(如1秒)内所产生的脉冲个数称为频率。频率是描述周期性循环信号(包括脉冲信号)在单位时间内所出现的脉冲数量多少的计量名称;频率的标准计量单位是Hz(赫)。电脑中的系统时钟就是一个典型的频率相当精确和稳定的脉冲信号发生器。 指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。 时钟周期:也称为振荡周期,一个时钟周期= 晶振的倒数。对于单片机时钟周期,时钟周期是单片机的基本时间单位,两个振荡周期(时钟周期)组成一个状态周期。 机器周期:单片机的基本操作周期,在一个操作周期内,单片机完成一项基本操作,如取指令、存储器读/写等。 机器周期=6个状态周期=12个时钟周期。 51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/ 晶振频率)= x s。常用单片机的晶振为11.0592MHz,12MHz,24MHz。其中11.0592MHz 的晶振更容易产生各种标准的波特率,后两种的一个机器周期分别为1 s和2 s,便于精确延时。 单片机精确毫秒延时函数对于需要精确延时的应用场合,需要精确知道延时函数的具体延

实验七 单片机键盘LED显示实验

实验七单片机键盘LED显示实验 一、实验目的 1、掌握键盘和LED显示器的接口方法和编程方法。 2、掌握键盘扫描和LED八段码显示器的工作原理。 3、学习并口扩展的程序编写方法。 二、实验说明 利用实验仪提供的键盘扫描电路和显示电路,做一个扫描键盘和数码显示实验,把按键输入的键码在六位数码管上显示出来。 实验程序可分成三个模块。 ①键输入模块:扫描键盘、读取一次键盘并将键值存入键值缓冲单元。 ②显示模块:将显示单元的内容在显示器上动态显示。 ③主程序:调用键输入模块和显示模块。 三、实验仪器 计算机 伟福实验箱(lab2000P ) 四、实验内容 1、本实验仪提供了一个6×4的小键盘,向列扫描码地址(0X002H)逐列输出低电平,然后从行码地址(0X001H)读回。如果有键按下,则相应行的值应为低,如果无键按下,由于上拉的作用,行码为高。这样就可以通过输出的列码和读取的行码来判断按下的是什么键。在判断有键按下后,要有一定的延时,防止键盘抖动。地址中的X是由KEY/LED CS 决定,参见地址译码。做键盘和LED实验时,需将KEY/LED CS 接到相应的地址译码上。以便用相应的地址来访问。例如将KEY/LED CS信号接CS0上,则列扫描地址为08002H,行码地址为08001H。列扫描码还可以分时用作LED的位选通信号。 2、本实验仪提供了6 位8段码LED显示电路,只要按地址输出相应数据,就可以实现对显示器的控制。显示共有6位,用动态方式显示。8位段码、6位位码是由两片74LS374输出。位码经MC1413或ULN2003倒相驱动后,选择相应显示位。 3、本实验仪中8位段码输出地址为0X004H,位码输出地址为0X002H。此处X是由KEY/LED CS 决定,参见地址译码。做键盘和LED实验时,需将KEY/LED CS 接到相应的地址译码上。以便用相应的地址来访问。例如,将KEY/LED CS 接到CS0上,则段码地址为08004H,位码地址为08002H。 五、思考题 1、按键接收到的数据加1显示出来; 2、实现第2功能键,即按下A后,再按下0-9键为加1显示; 3、保存前一个接收到的数据,数据向前推动显示。 六、源程序修改原理及其仿真结果 原程序: OUTBIT equ 08002h ; 位控制口 OUTSEG equ 08004h ; 段控制口 IN equ 08001h ; 键盘读入口 LEDBuf equ 60h ; 显示缓冲 ljmp Start

单片机按键扫描编程

实验四单片机按键扫描编程 一、实验目的 1、掌握单片机按键扫描的工作方式; 2、掌握单片机按键扫描的编程方法。 二、实验内容 1、学习单片机按键扫描的工作方式; 2、扫描按键,控制LED灯实现闪烁和停止闪烁两种状态的切换。 基本要求: 用按键Key1控制,按一下Key1,控制LED灯闪烁和停止闪烁的切换。 三、实验设备 1、STC单片机开发板; 2、PC机以及串口线。 四、实验分析及关键代码 #include #include #define uchar unsigned char uchar counter=0; sbit KEY1=P2^6; //按下,值为0 sbit LEDG=P2^5; void delay_10ms(void) //10ms延时函数 { unsigned char i,j;

for(j=0;j<10;j++) {for (i=0;i<250;i++) _nop_(); } } void timer()interrupt 1 using 1 //定时器1方式1,采用中断方式{ TH0=(65536-50000)/256; TL0=(65536-50000)%256; //重置初值 counter++; if(counter==10) { LEDG=!LEDG; //LEDG取反改变灯的状态 counter=0; } } void main() { TMOD=0X21; EA=1;

ET0=1; TR0=1; //启动T/C0开始定时 while(1) { if(!KEY1) { delay_10ms(); if(!KEY1) { while(!KEY1); delay_10ms(); TR0=!TR0; //执行按键任务} } } 五、实验总结

51单片机延时函数

C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char 作为延时变量。以某晶振为12MHz的单片机为例,晶振为12MHz即一个机器周期为1us。 一. 500ms延时子程序 程序: void delay500ms(void) { unsigned char i,j,k; for(i=15;i>0;i--) for(j=202;j>0;j--) for(k=81;k>0;k--); } 》 计算分析: 程序共有三层循环

一层循环n:R5*2 = 81*2 = 162us DJNZ 2us 二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值1us = 3us 三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值1us = 3us 循环外: 5us 子程序调用2us + 子程序返回2us + R7赋值1us = 5us 延时总时间= 三层循环+ 循环外= 499995+5 = 500000us =500ms 计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5 二. 200ms延时子程序 程序: ( void delay200ms(void) {

unsigned char i,j,k; for(i=5;i>0;i--) for(j=132;j>0;j--) for(k=150;k>0;k--); } 三. 10ms延时子程序程序: void delay10ms(void) $ { unsigned char i,j,k; for(i=5;i>0;i--)

单片机实验--键盘扫描

实验 4 键盘实验 一、实验目的: 1.掌握 8255A 编程原理。 2.了解键盘电路的工作原理。 3.掌握键盘接口电路的编程方法。 二、实验设备: CPU 挂箱、 8031CPU 模块 三、实验原理: 1.识别键的闭合,通常采用行扫描法和行反转法。 行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如所读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。 本实验例程采用的是行反转法。 行反转法识别键闭合时,要将行线接一并行口,先让它工作于输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使 CPU 通过输出端口往各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为 0。然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上的输入值,那么,在闭合键所在的行线上的值必定为 0 。这样,当一个键被按下时,必定可以读得一对唯一的行线值和列线值。 2.程序设计时,要学会灵活地对8255A 的各端口进行方式设置。 3.程序设计时,可将各键对应的键值(行线值、列线值)放在一个表中,将要显示的 0?F字符放在另一个表中,通过查表来确定按下的是哪一个键并正确显示出来。 实验题目 利用实验箱上的 8255A 可编程并行接口芯片和矩阵键盘,编写程序,做到在键盘上每 按一个数字键(0?F),用发光二极管将该代码显示出来。 四、实验步骤: 将键盘 RL10 ? RL17 接 8255A 的 PB0 ? PB7;KA10 ? KA12 接 8255A 的 PA0? PA2; PC0?PC7接发光二极管的 L1?L8 ; 8255A 芯片的片选信号 8255CS接CS0。 五、实验电路:

单片机写延时程序的几种方法

单片机写延时程序的几种方法 1)空操作延時(12MHz) void delay10us() { _NOP_(); _NOP_(); _NOP_(); _NOP_(); _NOP_(); _NOP_(); } 2)循環延時 (12MHz) Void delay500ms() { unsigned char i,j,k; for(i=15;i>;0;i--) for(j=202;j>;0;j--) for(k=81;k>;0;k--); }

延時總時間=[(k*2+3)*j+3]*i+5 k*2+3=165 us 165*j+3=33333 us 33333*i+5=500000 us=500 ms 3)計時器中斷延時(工作方式2) (12MHz) #include; sbit led=P1^0; unsigned int num=0; void main() { TMOD=0x02; TH0=6; TL0=6; EA=1; ET0=1; TR0=1; while(1) { if(num==4000) { num=0;

led=~led; } } } void T0_time() interrupt 1 { num++; } 4)C程序嵌入組合語言延時 #pragma asm …… 組合語言程序段 …… #pragma endasm KEIL軟件仿真測量延時程序延時時間

這是前段事件總結之延時程序、由於不懂組合語言,故NO.4無程序。希望對你有幫助!!! 對於12MHz晶振,機器周期為1uS,在執行該for循環延時程式的時候 Void delay500ms() { unsigned char i,j,k; for(i=15;i>;0;i--) for(j=202;j>;0;j--) for(k=81;k>;0;k--); } 賦值需要1個機器周期,跳轉需要2個機器周期,執行一次for循環的空操作需要2個機器周期,那么,對於第三階循環 for(k=81;k>;0;k--);,從第二階跳轉到第三階需要2機器周期,賦值需要1個機器周期,執行81次則需要2*81個機器周期,執行一次二階for循環的事件為81*2+1+2;執行了220次,則(81*2+3)*220+3,執行15次一階循環,則 [(81*2+3)*220+3]*15,由於不需要從上階跳往下階,則只加賦值的一個機器周期,另外進入該延時子函數和跳出該函數均需要2個機器周期,故

单片机矩阵键盘行列扫描程序学习资料

//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍 #include //包含头文件 #define uchar unsigned char #define uint unsigned int unsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F uchar keyscan(void); void delay(uint i); void main() { uchar key; P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符 while(1) { key=keyscan();//调用键盘扫描, switch(key) { case 0x7e:P0=dofly[0];break;//0 按下相应的键显示相对应的码值 case 0x7d:P0=dofly[1];break;//1 case 0x7b:P0=dofly[2];break;//2 case 0x77:P0=dofly[3];break;//3 case 0xbe:P0=dofly[4];break;//4 case 0xbd:P0=dofly[5];break;//5 case 0xbb:P0=dofly[6];break;//6 case 0xb7:P0=dofly[7];break;//7 case 0xde:P0=dofly[8];break;//8 case 0xdd:P0=dofly[9];break;//9 case 0xdb:P0=dofly[10];break;//a case 0xd7:P0=dofly[11];break;//b case 0xee:P0=dofly[12];break;//c case 0xed:P0=dofly[13];break;//d case 0xeb:P0=dofly[14];break;//e case 0xe7:P0=dofly[15];break;//f } } } uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法 {

相关文档
最新文档