当前位置:文档之家› 状态机方式按键扫描单片机程序

状态机方式按键扫描单片机程序

状态机方式按键扫描单片机程序

状态机方式按键扫描单片机程序

这是从51hei/bbs/dpj-19294-1.html这个单片机做的收音机里面截取出来的

一个子程序,完整的代码和

adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=17&is_app=0&jk=66a

41a025f30382d&k=%D4%AD%C0%ED%CD%BC&k0=%D4%AD%C0%ED%CD%B C&kdi0=0&luki=3&n=10&p=baidu&q=98059059_cpr&rb=0&rs=1&seller_id=1&si

d=2d38305f21aa466&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1831118&u=http%3A%2 F%2Fwww%2E51hei%2Ecom%2Fmcu%2F1974%2Ehtml&urlid=0” id=“5_nwl” mpid=“5” target=“_blank”>原理图可从原帖下载. /*-----------状态机方式按键扫描-----------*/ /*------------外部晶振为12MHz-----------*/ /*--------最后修改2011.02.26--------------*/#include “STC12C5620AD.H”#include “Key_Scan.H”#define Key_Mask 0x0f //屏蔽不用的按键,不用的按键用0屏蔽

?/********************** 声明外部变量**************************/extern uchar Work_Mode; //From Main.c/********************** 按键扫描读取**************************/uchar Key_Scan(void){static uchar Key_State=0; //

定义按键状态uchar Key_Press;uchar Key_Return=0x00; //定义按键返回的键值Key_Press=Key_Input&Key_Mask;//读按键I/O电平switch(Key_State){case 0: // 按键初始态if (Key_Press!=Key_Mask)Key_State=1; // 键被按下,状态转换到键

确认态break;case 1: // 按键确认态if (Key_Press==Key_Input&Key_Mask) {Key_Return=Key_Press; // 按键仍按下且键值键值,按键确认输出BEEP_DRV=1; // 驱动蜂鸣器Key_State=2;// 状态转换到键释放态} elseKey_State=0;// 按键已抬起或改变,并转换到按键初始态break;case 2:if

(完整版)51单片机实现双机通信(自己整理的)

1号机程序 #in clude #defi ne uint un sig ned int #defi ne uchar un sig ned char sbit p10=P1 A 0; uchar a,b,kk; //uchar code d_c[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; void delay_ms(uchar y) { uchar i; while(y__) for(i=0;i<120;i++) 5 } void put(uchar x) // 发送函数 { SBUF=x; //SBUF:串行口数据缓冲器 while (TI==0); 〃等待发送结束 TI=0; } P £j £fA>l3 旳 4阳 1370 丘阳 H 鮎口 PDLWAJil- PDSA>f POfiAME PQ TiJT FZ^KS 畑 阳pz- A A-m FZW11 PZ.AtZ FZj9jAl4 PZ.TW? P3£VR : iD paimcc P3.sii nrn pjjfflrn F3.WTI] M*Tl pgtjgQIH F3.7/IF 1E 11 左边1号机,右边2号机, ,功能实现 帕叶DO ■ 口 IJApi FDJ H [I Z — 观旧 IP 口 .hQKD* *QAADf H ^ 弓 H.Lta RQfMM FZJWS pz. iwe F2JKA-IDI P2JTA11I F2.HW1Z P2JSM13 F2W.14 F2JM1S F3Ji nHX& gj.im:& riaiWTO rjjfWTT F3.1/W f3AT1 P3JillW F3JMF ■T2 1E

单片机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

自己写的按键单片机程序

自己写的按键单片机程序 用4个按键来控制数码管显示的内容#include#define duan P0//段选#define wei P2//位选unsigned char code wei1[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选控制查表的方法控制unsigned char code duan1[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0 x71};//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码unsigned char ge,shi,bai,a,b;sbit key1=P1;sbit key2=P1 ;sbit key3=P1 ;sbit key4=P1 ;void keys();//按键函数void s(unsigned char xms);//延时函数void DigDisplay(); //动态显示函数void init(); //初始化函数void main(void){init(); while(1){DigDisplay();keys();} }void DigDisplay(){unsigned char i;unsigned int j;bai=a/100;shi=a%100/10;ge=a%10;i=0;wei = wei1[i];//发送位选duan = duan1[bai]; //发送段码j = 10;//扫描间隔时间设定while(j--);duan = 0x00; //消隐i++;wei = wei1[i];//发送位选duan = duan1[shi]; //发送段码j = 10;//扫描间隔时间设定while(j--);duan = 0x00; //消隐i++;wei = wei1[i];//发送位选duan = duan1[ge]; //发送段码j = 10;//扫描间隔时间设定while(j--);duan = 0x00; //消隐}void init() {key1=1;key2=1;key3=1;key4=1;TMOD=0X01;TH0=(65536- 45872)/256;TL0=(65536-45872)%256;EA=1;ET0=1;}void s(unsigned char xms){unsigned char x,y;for(x=xms;x>0;x--)for(y=110;y>0;y--);}void times() interrupt 1{TH0=(65536-45872)/256;TL0=(65536-45872)%256;b++;if(b==20){b=0;a++;if(a==256){a=0;}}}void keys(){if(key1==0){s(10);if(key1==0){a++;TR0=0;if(a==256)a=0;while(!key1)Dig Display();}}if(key2==0){s(10);if(key2==0){TR0=0;if(a==0)a=256;a--

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;

51单片机实现双机通信(自己整理的)

左边1号机,右边2号机,,功能实现 1号机程序 #include #define uint unsigned int #define uchar unsigned char sbit p10=P1^0; uchar a,b,kk; //uchar code d_c[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; void delay_ms(uchar y) { uchar i; while(y--) for(i=0;i<120;i++) ; } void put(uchar x) //发送函数 { SBUF=x; //SBUF:串行口数据缓冲器 while(TI==0); //等待发送结束 TI=0; } void main() { uchar j; SCON=0x40; //串行口工作方式1,8位通用异步发送器

— TMOD=0x20; //定时器1工作方式2 PCON=0x00; //波特率不倍增 TH1=0xf4; TL1=0xf4; //波特率2400 TR1=1; //定时器1开始计时 P2=0xc0; while(1) { if(p10==0&&j==0) { delay_ms(15); while(p10==0); kk=1; P2=0xf9; j=1; } if(p10==0&&j==1) { delay_ms(15); while(p10==0); kk=2; P2=0xa4; j=2; } if(p10==0&&j==2) { delay_ms(15); while(p10==0); kk=3; P2=0xb0; j=0; } if(kk==1) put('A'); if(kk==2) put('B'); if(kk==3) put('C'); delay_ms(10); } }

状态机思路在单片机程序设计中的应用

状态机思路在单片机程序设计中的应用 状态机的概念 状态机是软件编程中的一个重要概念。比这个概念更重要的是对它的灵活应用。在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。 比如说一个按键命令解析程序,就可以被看做状态机:本来在A状态下,触发一个按键后切换到了B状态;再触发另一个键后切换到C状态,或者返回到A状态。这就是最简单的按键状态机例子。实际的按键解析程序会比这更复杂些,但这不影响我们对状态机的认识。 进一步看,击键动作本身也可以看做一个状态机。一个细小的击键动作包含了:释放、抖动、闭合、抖动和重新释放等状态。 同样,一个串行通信的时序(不管它是遵循何种协议,标准串口也好、I2C也好;也不管它是有线的、还是红外的、无线的)也都可以看做由一系列有限的状态构成。 显示扫描程序也是状态机;通信命令解析程序也是状态机;甚至连继电器的吸合/释放控制、发光管(LED)的亮/灭控制又何尝不是个状态机。 当我们打开思路,把状态机作为一种思想导入到程序中去时,就会找到解决问题的一条有效的捷径。有时候用状态机的思维去思考程序该干什么,比用控制流程的思维去思考,可能会更有效。这样一来状态机便有了更实际的功用。 程序其实就是状态机。 也许你还不理解上面这句话。请想想看,计算机的大厦不就是建立在“0”和“1”两个基本状态的地基之上么? 状态机的要素 状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果关系的考虑。“现态”和“条件”是因,“动作”和“次态”是果。详解如下: ①现态:是指当前所处的状态。 ②条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。 ③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。 ④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

单片机矩阵键盘扫描程序

#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;

单片机键盘输入程序

这是读取键盘的子程序 主要内容为:如何定义位,如何得到按键状态,防止键盘干扰的方法 以及如何处理读入的键值 思路:首先在某一引脚输出一个电平,然后读入引脚的电平,如果刚好相反 那么可能有按键发生,但是不排除干扰,为了防止干扰,需要软件延时20ms 应该说键盘输入是单片机外部指令输入的重要途径,因此如何设计键盘以及键盘的工作原理、读键盘的方法、键盘的抗干扰设计等在单电能机系统设计中占有重要地位。这个例子在系统硬件的基础上设计了软件查询程序、软件延时程序(防止干扰),大致讲述了一种查询式键盘的工作原理与读取方式。 下面是汇编语言写的单片机键盘输入程序 ************************************************** led1 bit p1.0;LED 显示位定义 led2 bit p1.1 led3 bit p1.2 led4 bit p1.3 led5 bit p1.4 led6 bit p1.5 led7 bit p1.6 led8 bit p1.7 s1 bit p0.0 ;数码管位定义 s2 bit p0.1 s3 bit p0.2 s4 bit p0.3 s5 bit p0.4 s6 bit p0.5 s7 bit p0.6 s8 bit p0.7 led_data equ p2;数码管显示数据定义 key1 bit p3.5 ;按键引脚定义

key2 bit p3.6; key3 bit p3.7; key equ 46h;按键寄存单元 org 00h jmp main org 030h main:mov sp,#30h;首先定义 lcall REST;初始化子程序 lp:lcall pro_key;调用键盘查询子程序 lcall KEYPR ;用来显示所查询到的键值jmp lp;反复调用,不断查询 REST: mov a,#00h mov b,#00h mov p0,#0 mov p1,0ffh ; mov p2,#0 mov key,#00h mov p2,#255 clr beep RET KEYPR: mov a,key;键值在累加器KEY中 jz PROEND ;如果A= 0,表示没有按键,返回cjne a,#1,k1;A= 1 ,用户按了第一个键mov a,#1 ;处理 A = 1的情况 mov dptr,#tab_nu ;查表 movc a,@a+dptr mov led_data,a ;显示"1" setb s1 ;在第一位

单片机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 二、实验内容

单片机按键连接方法

单片机按键连接方法总结(五种按键扩展方案详细介绍) 单片机在各种领域运用相当广泛,而作为人机交流的按键设计也有很多种。不同的设计方法,有着不同的优缺点。而又由于单片机I/O资源有限,如何用最少的I/O口扩展更多的按键是我所研究的问题。接下来我给大家展示几种自己觉得比较好的按键扩展方案,大家可以在以后的单片机电路设计中灵活运用。 1)、第一种是最为常见的,也就是一个I/O口对应一个按钮开关。 这种方案是一对一的,一个I/O口对应一个按键。这里P00到P04,都外接了一个上拉电阻,在没有开关按下的时候,是高电平,一旦有按键按下,就被拉成低电平。这种方案优点是电路简单可靠,程序设计也很简单。缺点是占用I/O资源多。如果单片机资源够多,不紧缺,推荐使用这种方案。 2)、第二种方案也比较常见,但是比第一种的资源利用率要高,硬件电路也不复杂。 这是一种矩阵式键盘,用8个I/O控制了16个按钮开关,优点显而易见。当然这种电路的程序设计相对也还是很简单的。由P00到P03循环输出低电平,然后检测P04到P07的状态。比方说这里P00到P03口输出1000,然后检测P04到P07,如果P04为1则说明按下的键为s1,如果P05为1则说明按下的是s2等等。为了电路的可靠,也可以和第一种方案一样加上上拉电阻。 3)、第三种是我自己搞的一种方案,可以使用4个I/O控制8个按键,电路多了一些二极管,稍微复杂了一点。 这个电路的原理很简单,就是利用二极管的单向导电性。也是和上面的方案一样,程序需要采用轮训的方法。比方说,先置P00到P03都为低电平,然后把P00置为高电平,接着查询P02和P03的状态,如果P02为高则说明按下的是s5,若P03为高则说明按下的是s6,然后再让P00为低,P01为高,同样检测P02和P03的状态。接下来分别让P02和P03为高,其他为低,分别检测P00和P01的状态,然后再做判断。这种方案的程序其实也不难。 4)这是我在一本书上看到的,感觉设计的非常巧妙,同样它也用到了二极管,不过比我的上一种方案的I/O利用率更高,他用4个I/O口控制了12个按键。我相信你了解了之后也会惊奇的。 首先好好品味一下这个方案吧,想想怎么来识别按键呢!

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

/*----------------------------------------------- 名称:矩阵键盘依次输入控制使用行列逐级扫描 论坛:https://www.doczj.com/doc/3712693307.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单片机多任务操作系统的原理与实现 51单片机多任务操作系统的原理与实现 -- 一个超轻量级的操作系统 前言 想了很久,要不要写这篇文章?最后觉得对操作系统感兴趣的人还是很多,写吧. 我不一定能造出玉,但我可以抛出砖. 包括我在内的很多人都对51使用操作系统呈悲观态度,因为51的片上资源太少.但对于很多要求不高的系统来说,使用操作系统可以使代码变得更直观,易于维护,所以在51上仍有操作系统的生存机会. 流行的uCos,Tiny51等,其实都不适合在2051这样的片子上用,占资源较多,唯有自已动手,以不变应万变,才能让51也有操作系统可用.这篇贴子的目的,是教会大家如何现场写一个OS,而不是给大家提供一个OS版本.提供的所有代码,也都 是示例代码,所以不要因为它没什么功能就说LAJI之类的话.如果把功能写全了,一来估计你也不想看了,二来也失去灵活性没有价值了. 下面的贴一个示例出来,可以清楚的看到,OS本身只有不到10行源代码,编译后 的目标代码60字节,任务切换消耗为20个机器周期.相比之下,KEIL内嵌的 TINY51目标代码为800字节,切换消耗100~700周期.唯一不足之处是,每个任务要占用掉十几字节的堆栈,所以任务数不能太多,用在128B内存的51里有点难度,但对于52来说问题不大.这套代码在36M主频的STC12C4052上实测,切换任务仅需2uS. #include #define MAX_TASKS 2 //任务槽个数.必须和实际任务数一至 #define MAX_TASK_DEP 12 //最大栈深.最低不得少于2个,保守值为12. unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP]; //任务堆栈. unsigned char task_id; //当前活动任务号 //任务切换函数(任务调度器) void task_switch(){ task_sp[task_id] = SP; if(++task_id == MAX_TASKS) task_id = 0; SP = task_sp[task_id]; } //任务装入函数.将指定的函数(参数1)装入指定(参数2)的任务槽中.如果该槽中原来就有任务,则原任务丢失,但系统本身不会发生错误. void task_load(unsigned int fn, unsigned char tid) {

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功能处理程序

实验七 单片机键盘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; //执行按键任务} } } 五、实验总结

按键处理程序 C语言 单片机

分享一种按键处理程序(用C) //头文件定义: Ustruct KEY { Uchar Val; #define Key_Model_C 0 //按键1值 #define Key_AddVal_C 1 //按键2值 Uint ScanOnTime; Uchar LongKeyState; Uchar LongKeyRestState; Uchar SetInRn; Uchar Model; //按键状态(模式) #define Off_C 0 //之前未按下 #define On_C 1 //现按下 #define Delay_C 2 //按键处理后标志 }Key; //----------------定义两个IO输入口为按键入口--------------------// #define KeyMo_Bin (GPIOB->IDR.Bit.B5) #define KeyAdd_Bin (GPIOB->IDR.Bit.B6) /*===============================================================*/ GPIO_Init(GPIO_Pin_5|GPIO_Pin_6,GPIO_Mode_In_PU_No_IT); //初始化为上拉输入无中断 /*===============================================================*/ //主程序大循环中每1毫秒扫描1次 void KeyScan(void) { if(Key.LongKeyRestState == 1) //长按键标志(复位处理长按键) { if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1)) //当两按键均抬起 { if(++Key.ScanOnTime >= 130) //延时后复位 { Key.LongKeyRestState=0; Key.Model=Delay_C; } } else Key.ScanOnTime=0; return; } if(Key.Model == Off_C) //如果当前按键状态为未按下“Off_C” { if((KeyMo_Bin == 0) || (KeyAdd_Bin == 0))//按键1或按键2已按下(低有效) { if(++Key.ScanOnTime >= 10) //当按下后自加1,加够10次即1ms*10=10ms去抖动

单片机实验--键盘扫描

实验 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。 五、实验电路:

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

//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍 #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)//键盘扫描函数,使用行列反转扫描法 {

相关主题
文本预览
相关文档 最新文档