• 优质范文
  • 工作总结
  • 工作计划
  • 作文大全
  • 心得体会
  • 述职报告
  • 实习报告
  • 写作方案
  • 教案反思
  • 演讲稿
  • 发言稿
  • 读书笔记
  • 精美散文
  • 读观后感
  • 范文大全
  • 当前位置: 博通范文网 > 写作方案 > 正文

    单片机按键扫描实验报告

    时间:2021-10-05 来源:博通范文网 本文已影响 博通范文网手机站

    键盘扫描

    一.实验目的

    (1)掌握矩阵键盘接口电路和键盘扫描编程方法。

    (2)掌握按键值处理与显示电路设计。

    二.实验任务

    (1)设计 4*4 键盘,编写各个键的特征码和对应的键值(0~F); (2)编程扫描按键,将按键对应的数字值使用数码管显示出来。

    三.实验电路及连线方法

    1.采用动态显示

    连线方法:电路由2 片74LS573,1 个六字一体的共阴数码管组成。由U15 输出段选码,U16 做位选码,与单片机的采用I/O 口连接方式,短路片J22 连接P2.0,J23 连接P2.3,做输出信号锁存。

    (实际电路连接是 d7-d6-d5-d4-d3-d2-d1-d0 h-c-d-e-g-b-a-f)。PW12 是电源端。

    2.键盘电路

    连线方法:电路由16 个按键组成,用P1 口扩展4×4 行列式键盘。

    J20 是键盘连接端,连接到P1 口。J21 是行列键盘、独立键盘选择端,当J21 的短路片连接2-3 脚时,构成4×4 行列式键盘;当J21 的短路片连接2-1 脚时,可形成3×4 行列式键盘,4 个独立式 按键S4、S8、S12、S16,这4 个独立按键分别连接P1.4~P1.7;其他12 个键3×4 行列式键盘。

    PW15 是电源端。

    四.编程思路

    1.采用反转法识别按键的闭合。

    2.采用动态显示将键值显示出来。

    五.算法流程图

    六 .资源分配 1.用 P1 口进行查找按键 2.用 R3 做键值指针 3.用 R1 做动态显示为选码指针。

    4.R5 为延时指针。

    七.程序设计

    ORG

    0000H KPIN: MOV

    P1,#0F0H

    MOV

    A,P1

    ANL

    A,#0F0H

    MOV

    B,A

    MOV

    P1,#0FH

    MOV

    A,P1

    ANL

    A,#0FH

    ORL

    A,B

    CJNE

    A,#0FFH,KPIN1

    AJMP

    EXIT KPIN1: MOV

    B,A

    MOV

    DPTR,#TABKP

    MOV

    R3,#0 KPIN2: MOV

    A,R3

    MOVC

    A,@A+DPTR

    CJNE

    A,B,KPIN3

    MOV

    A,R3

    LOOP: MOV

    R1,#0FEH;键盘动态显示 LOOP1: MOV

    A,R3

    ANL

    A,#0FH

    MOV

    DPTR,#TAB

    MOVC

    A,@A+DPTR

    CLR

    P2.0

    CLR

    P2.1

    MOV

    P0,A

    SETB

    P2.0

    NOP

    CLR

    P2.0 LOOP2: MOV

    A,R1;位选码

    MOV

    P0,A

    SETB

    P2.1

    MOV

    R5,#250 LOOP3: DJNZ

    R5,LOOP3

    CLR

    P2.1

    SJMP

    LOOP

    KPIN3: INC

    R3

    CJNE

    A,#0FFH,KPIN2 EXIT: RET TABKP: DB

    0EEH,0DEH,0BEH,7EH,0EDH,0DDH,0BDH,7DH,0EBH

    DB

    0DBH,0BBH,7BH,0E7H,0D7H,0B7H,77H,67H,0FFH TAB: DB

    77H,44H,3EH,6EH,4DH,6BH,7BH,46H,7FH,6FH,5FH

    DB

    79H,33H,7CH,3BH,1BH

    END 八. 调试出现的问题及解决

    问题 1:程序正常运行,但按键显示出现乱码

    解决:动态显示笔形码错误,并改正。

    问题 2:发现有些按键按下时不出现键值

    解决:发现按键坏了,换机器再实验,并且成功。

    总结:与硬件想结合的实验要有足够的耐心,并且不仅要懂得如何编程,还要有足够多的电路知识,这样才能够保证实验成功。

    主题都很生活!

    实验一

    一、实验题目:试编写一段程序,其功能为将21H单元的内容8位分别依次存放到从22H开始的8单元中。

    二、keil代码:

    org 0000h jmp start

    org 0100h start: mov 21h,#8; mov A ,21h;取出21中的数 mov R0,#22h ;初始化 mov R1,#7h ;循环次数为7 loop:

    RRC A;把A之中的最低位移到C

    JC real;判断C里面是数是否为1,如果是1.则跳转到real mov @R0,#0h jmpkk; real: mov @R0,#1h;如果是1,则将1赋到R0单元里 kk: INC r0;依次判断A中的每一位

    DJNZ R1,loop; jmp $;死循环 end

    三、实验截图:

    四、实验小结:

    这是我们单片机的第一个实验,因为刚接触,所以会感觉很陌生,内心有一种畏惧感,看到题目的时候也是没有头绪,可以说完全是不知道到底题目是一个什么意思,更是不知道我们应该如何编写程序。不过后面通过老师的讲解,自己也去查看了一些有关的书籍,慢慢也理解了该如何去实现这种实验题目。 在认真琢磨之后,我开始学会像以前刚开始学习C语言一样慢慢绘制一个程序的流程图,理清思绪,然后根据流程图编写相应的代码。

    下面是本题的实验流程图:

    通过完成这个实验,我对单片机的程序有了很大的认识。实验中,也是深刻的理解到了一个单片机程序每一步的实现与运行。当然,也掌握了在keil中调试的方法。

    实验二

    一、实验题目:若0-5号键的键值分别是:EEH、DEH、BEH、7EH、EDH、DDH。设键值存放在内部RAM 20H单元中,编程实现根据2OH中的键值分别使程序转移到PR0-PR4程序段。要求当以上程序段的功能完成后,都采用RET指令,指定返回到程序的初始入口START标号处。 要求:PR0 :教材75页习题。

    PR1 :同上习题9题 PR2:同上习题10 其余入口,只需完成空操作就返回。

    二、keil代码:

    org 0000 ljmp start org 0100 TAB: DB 0EEH,0DEH,0BEH,7EH,0EDH,0DDH start: movdptr ,#start pushdpl pushdph

    mov A,#0EEH MOV 20H,A

    MOV DPTR ,#TAB

    MOV A,#0 NEXT: PUSH ACC;先保存A寄存器中的值

    MOVC A,@A+DPTR

    ;A是键码表的编码

    ;置键码表首址

    ;表的起始位置的偏移量为零 CJNE A,20H,NEXT1 POP ACC RL A

    ;将20H值和键码表的值比较

    ;如相等,序号乘以2,得到分支表内偏移量2n (8位变16位)

    MOV DPTR,#APJ

    JMP @A+DPTR PRn指令

    NEXT1: POP ACC

    INC A CJNE A,#6,NEXT;表示如果==6了,说明编码查完了也没有相等的,程序直接结束

    SJMP $

    APJ: AJMP PR0 AJMP PR1 AJMP PR2 AJMP PR3 AJMP PR4

    ;不相等,则比较下一个

    ;置分支表首址

    ;执行表JPT+2H中的AJMP

    PR0:

    MOV R7,#5H MOV 3DH,#00H MOV 3EH,#20H MOV 4EH,#88H MOV 5EH,#98H MOV A,#0 MOV R4,A MOV R5,A MOV R6,A

    ;正数个数

    ;负数个数

    ;零的个数

    MOV R0,#40H MOV R1,#50H MOV SP,#3FH LOOP: POP ACC JZ ZERO JB ACC.7,FS INC R4 MOV @R0,A INC R0 AJMP DJ FS: INC R5 MOV @R1,A INC R1 AJMP DJ ZERO: INC R6 DJ: DJNZ R7,LOOP RET

    DATA1:DB 0EFH,3FH,3EH,07H PR1:

    MOV R7,#03H;进行3次循环 MOV R0,#DATA1 MOV A,@R0

    CPL A ;取反 ADD A,#01

    ;加1 MOV @R0,A AB1: INC R0 MOV A,@R0 CPL A ADDC A,#0 ;带进位 DJNZ R7,AB1 ;SJMP $

    RET BUF1:DB 1111B,0101B,0010B,0100B,0101B,0010B,0001B,0000B,1001B,0000B,1010B,1011B,0000B,0011B,0010B,0001B BUF2:DB 0 BUF:DB 0 PR2:

    ;30h放平均值 40h放余数 MOV R0,#BUF1

    MOV R7,#16 ;循环16次数 MOV B,#0 MOV A,@R0 MOV R2,A LOOP1: MOV A,R2 INC R0 ADD A,@R0 MOV R2,A MOV A,B ADDC A,#0 MOV B,A DJNZ R7,LOOP1

    MOV R6,#04H MOV 30H,#BUF2 MOV 30H,A MOV 40H,#BUF MOV 40H,#0 NEX: CLR C MOV A,B RRC A MOV B,A MOV A,30H RRC A

    MOV 30H,A MOV A,40H RRC A MOV 40H,A DJNZ R6,NEX SJMP $ RET PR5:

    RET PR3:

    RET PR4:

    RET END

    三、实验截图:

    初始化:

    结果:

    四、实验小结:

    本实验中,将键码排成表,将键码表中的值和20H单元中的内容进行比较;另外编制一张转移表,存放AJMP指令,利用JMP @A+DPTR执行表内的AJMP指令,从而实现分支转移。

    “RL A”:因为每个AJMP指令占两个字节,将刚记下来的键码中的值(即:键码的序号)乘以2即为转移表的偏移地址,在利用JMP @A+DPTR执行表内的AJMP指令,从而实现分支转移。

    “movdptr ,#start Pushdpl push dph”:指定每次主程序返回到start。在单片机中,每一个子程序的返回用RET指令,而RET指令的功能正好可以使得子程序从栈顶弹出断点到PC,从而返回到主程序

    实验三

    一、实验题目:使用C语言完成,实验一,实验二。

    二、keil代码:

    实验一:

    #include #include void main() { char *p1=0x21; char *p2=0x22; int i=1;

    *p1=0x8;

    while(i

    {

    *p2=*p1&0x01;

    *p1=*p1>>1; p2++; i++;

    } } 实验二: #include void PR0(); void PR1(); void PR2(); void PR3(); void PR4(); void PR5();

    int main() { int i;//键码表code[]的下表

    int key=0; char code1[]={0xEE,0xDE,0xBE,0x7e,0xED,0xDD}; char *p0=0x20;

    //指针变量*p0指向20H这个单元

    *p0=0xDE;

    //给20H单元赋初值(20H单元里存放键码表中任一值)

    for(i=0;i

    }

    key=i; switch(key) if(*p0==code1[i]){break;}

    } {

    } return 0; case 0:PR0();break; case 1:PR1();break; case 2:PR2();break; case 3:PR3();break; case 4:break; case 5:break; default:break; void PR0() { char table1[16]={1,2,-6,7,8,9,0,-1,-2,-3,-4,-5,-6,1,4,6}; char data *p30 = 0x30; char data *p40 = 0x40; char data *p50 = 0x50; int i; int countR4=0; R4,R5,R6中

    int countR5=0;

    //分别将正数、负数和零的个数存入 int countR6=0; for(i=0;i

    //依次将table1表里的16个数据存入30H单元开始的单元里。

    {

    } for(i=0;i

    {

    if(*p30>0) {

    } else if(*p30

    } else *p50=*p30; ++p50; ++countR5;

    *p40=*p30; ++p40; ++countR4;

    p30[i]=table1[i];

    { } ++countR6;

    }

    ++p30; } }

    void PR1() { char data1[]={0x10,0x11,0x12,0x13}; int i; int j; char Cy=PSW^7; data1[0]=(~data1[0])+0x1; //while(j

    } } data1[i]=(~data1[i])+Cy; i++;

    void PR2() { char buf1[]={0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0x0A,0x0B,0x0C,0x0D,0x0E,0xF}; char buf2=0; charbuf=0; int sum=0; int i=1; while(i

    { sum=sum+buf1[i];

    ++i;

    } buf2=sum/0x10; buf=sum%0x10; }

    三、实验截图:

    实验一:

    实验二:

    四、实验小结:

    在本实验中,我们用C语言编写代码的时候,特别注意指针的使用。另外,在单片机中使用C语言,与我们之前写C语言的时候还是有一些不同的地方,尤其是在指针使用上面的不同。C语言是一种通用的程序设计语言,代码率高,数据类型丰富,且具有良好的程序结构;单片机的C语言采用C51编译器,由C51产生的目标代码短,运行速度快,所需内存空间小。

    实验中,注意:

    “for(i=0;i

    {

    p30[i]=table1[i]; }”:表示依次将table1表里的16个数据存入30H单元开始的单元里。实际上,在C中指针就相当于一个数组。

    在本实验中,我可以根据之前的汇编程序实验,较为容易的根据每个子程序编子函数模块。由于之前有C语言的基础,所以能够比较好的完成本实验。

    实验四

    五、实验题目: 当K1键按下后,首先使蜂鸣器响一声,然后使LED1- LED8完成3种闪亮的花样(自己定义),每一种花样循环 3次,然后周而复始。

    六、keil代码:

    /*当K1键按下后,首先使蜂鸣器响一声,

    然后使LED1- LED8完成3种闪亮的花样(自己定义),每一种花样循环 3次,然后周而复始。*/ #include sbit P2_0=P2^0;//接蜂鸣器 sbit P2_7=P2^7; sbit P1_0=P1^0; sbit P1_1=P1^1; sbit P1_2=P1^2; sbit P1_3=P1^3; sbit P1_4=P1^4; sbit P1_5=P1^5; sbit P1_6=P1^6; sbit P1_7=P1^7;

    void DELAY(int time)//延时 { while(time--) {} }

    void BUZ_ON() { if(P2_7==0)

    { P2_0=1; } else { P2_0=0; }

    }

    void F1(void) { int i; char data_group_mide[5]={0x00,0x18,0x24,0x42,0x81};//向两边延伸 for(i=0;i

    P1=0x00;

    } void F2(void) { int i; char data_group_left[8]={0xFF,0x7F,0x3F,0x0F,0x07,0x03,0x01,0x00};//向左延伸 for(i=0;i

    P1=0x00;

    } void F3(void) { int i; char date_group_right[8]={0x00,0x01,0x03,0x07,0x0f,0x3f,0x7f,0xff};//向右延伸 for(i=0;i

    P1=0x00;

    } void main() {

    unsigned int i; //每种花样循环三次

    P2_0=0;

    P2_7=1;

    BUZ_ON();

    P1=0x00; while(P2_7==0)

    {

    for(i=0;i

    {F1();}

    for(i=0;i

    {F2();}

    for(i=0;i

    {F3();}

    }

    }

    三、protues电路图:

    四、实验截图:

    五、实验小结:

    通过本次实验,我们熟悉了protues的编译环境,对以后的单片机学习有很大帮助。

    实验五

    一、实验题目: 程序启动后4位LED显示器滚动显示“-”,每按下1次K1键后,首先使蜂鸣器响一声。然后,依次使LED滚动显示CNT的计数值(0-9)。

    二、Keil代码:

    /*程序启动后4位LED显示器滚动显示“-”,每按下才1次K1键后,首先使蜂鸣器响一声。然后,依次使LED滚动显示CNT的计数值(0-9)。

    1、按键K1采用中断来管理。(INT0采用边沿触发)

    2、中断服务程序完成四个功能:

    1)消除按键K1抖动。

    2)CNT计数。

    3)查表将计数值转换成LED显示器的段代码。

    4)将段代码分别放入4个显示缓冲单元。*/ #include #define uchar unsigned char #define uint unsigned int sbit P2_7=P2^7; sbit P3_3=P3^3; uchar CORDING[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc0,0xf9,0xa4,}; //0,1,2,3,4....9,0,1,2的段码 intdelayms(uint t) {

    uint n; while(--t) { n=200; while(--n); }; return 0; }

    int main() { uint CNT=0;

    P2_7=0;

    P3_3=1; P1=0xF7; while(1)

    { if(P3_3==0)

    {

    uint i;

    CNT++;

    P2_7=1; delayms(100); for(i=1;i

    //4位

    {

    P1=CORDING[CNT-1];

    switch(i)

    {

    //点亮第1位

    //点亮第2位

    //点亮第3位

    //点亮第4位

    delayms(100);

    }

    case

    case

    case

    case }

    P2=0x00; 1:P2=0x01;break; 2:P2=0x02;break; 3:P2=0x04;break; 4:P2=0x08;break;

    // 熄灭

    if(CNT>10) {

    CNT=CNT-10; }

    }

    三、protues电路图:

    P2_7=0; } return 0; }

    四、实验截图:

    五、实验总结:

    通过本次实验,我们熟悉了CNT计数,学会了如何使LED灯上显示0-9数字。

    实验六

    一、实验题目:

    两个数码管,K1,K2两个按键,完成K1启动计数,K2暂停计数,每一秒钟数码管增加1,60秒钟后,数码管回归0,重新计数。

    二、keil代码:

    /*两个数码管,K1,K2两个按键,完成K1启动计数,K2暂停计数,每一秒钟数码管增加1,60秒钟后,数码管回归0,

    重新计数。按键K1,K2采用中断来管理。(INT0采用边沿触发)*/ #define uchar unsigned char #define uint unsigned int #include uchar CNT=0; uchar

    m=0; sbit P3_7=P3^7; sbit P3_2=P3^2; sbit P0_0=P0^0; uchar CORDING[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //0,1,2,3,4....9的段码 void Delay(uint a) {

    while(--a){};

    } voidintproc() interrupt 0 {

    TR0=0; }

    void Time0() interrupt 1 {

    m++;

    //中断一次,m加1

    if(m==20) {

    m=0;

    //中断次数清零 CNT++; //秒加1 if(CNT==60) { CNT=0;}

    P1=CORDING[CNT/10];//显示十位 Delay(10);

    P2=CORDING[CNT%10];//显示个位 Delay(10);

    } } voidinit() {

    TMOD=0x01;

    //使用定时器T0 使用方式1 TH0 = 0x3c;

    TL0 = 0xb0;

    ET0=1; TR0=1; EX0=1; IT0=1; EA=1; }

    void main() {

    P1=0x3f;

    P2=0x3f;

    P3_7=1; while(1)

    { if(P3_7==0) //50ms中断一次 //控制是否开启

    { init();

    } }

    三、protues电路图:

    }

    四、实验截图:

    五、实验总结:

    本次实验,我们用到了中断,按键K1,K2采用中断来管理。(INT0采用边沿触发),通过本次实验加强了中断的学习,更加有利于单片机的学习。

    实验七

    一、实验题目:晶振12MHz,波特率1200,程序启动后单片机主动发出Hello Server,PC使用串口助手应答单片机,单片机收到数据后,不做任何修改返回PC。

    二、keil代码: #include #define uchar unsigned char #define uint unsigned int

    uchar code table[]="HELLO SERVER!"; uint flag = 0; uchara,b; voidinit() {

    }

    voidSendByte(ucharch) { SBUF = ch; TMOD = 0x20; TH1 = 0xFD; TL1 = 0XFD; SCON = 0X50; TR1 = 1; EA = 1; ES = 1;

    } while(!TI); TI = 0; voidSendString(uchar code *str) {

    }

    void main() {

    init();

    SendString("HELLO SERVER!"); while(1) {

    if(flag == 1) {

    ES = 0; SBUF = a; while(!TI); TI = 0; while(*str) SendByte(*str++);

    }

    } ES = 1; flag = 0;

    }

    voidser() interrupt 4 {

    }

    if(RI == 1) {

    } RI = 0; a = SBUF; flag = 1;

    三、protues电路图:

    四、实验截图:

    六、实验总结:

    本次实验,我们利用了中断来实现,通过本次实验我们对中断有了更加深刻的了解,让我们在以后的为以后的学习之中打下了一定的基础。

    布局顺当,言之有物。

    推荐访问:单片机 按键 扫描

    • 读/观后感
    • 精美散文
    • 读书笔记
    • 演讲
    • 反思
    • 方案
    • 心得体会