欣欣学习网,老工程师带你学习单片机技术,欢迎来坐坐。
首  页 | 学习NIOSII | 学习C51 | 学习CPLD | 51+CPLD实验板 | | | MY-RTOS

本栏目的实验需在 WinXp 上操作。建议在 Virtual Box 虚机上安装WinXp系统,使用更方便。

 学习板概述
 安装keil C51软件
 在线烧写程序
 keil C51使用入门
 使用keil C51仿真调试
 使用标准输入输出设备
 点灯程序
 跑马灯程序
 LED数码管扫描显示程序
 键盘扫描程序
 键盘数码管联合扫描
 计时秒表程序
 蜂鸣器发声程序
 产生音阶程序
 字符LCD控制程序
 Flash读写程序
 使用ADC检测模拟量程序
 相关软件与文档


单片机/C51学习板

键盘数码管联合扫描


本实验演示的是一个键盘、数码管联合扫描程序,通过该程序,示例如何实现数码管和键盘的联合扫描。

1.

点击 这里 下载示例工程,保存并解压到 D: 盘根目录下。

2.

启动 ISP 软件,将 D:\ledkey 下的 mon51.hex 文件烧写到实验板上,关闭 ISP 软件。如果实验板上已有调试代理程序,可略过这一步。ISP 软件的使用方法参见:在线烧写程序

3.

启动 Keil uVision2 集成开发软件,打开 D:\ledkey 下的 ledkey.Uv2 工程,重新编译。Keil uVision2 软件的使用方法见:keil C51使用入门

4.

设置好 Monitor-51 Driver 所使用的串口号后,在 Debug 菜单下,点击 Start/Stop Debug session 命令,启动调试界面。如何设置串口号,请参阅:使用keil C51仿真调试

5.

在命令行窗口里,输入 pc = 0x2000 命令,然后按 F5 键,执行该程序。

程序代码如下:

#include <reg52.h>       /* special function register declarations   */
#include <absacc.h>      /* for the intended 8051 derivative         */

#include <stdio.h>       /* prototype declarations for I/O functions */

/***************************************************
 * A型板,定义 model 为 1,B型板,定义 model 为 2。*
 ***************************************************/

#define model 2

#if model == 1
sbit SCC=P3^2;
#else
sbit SCC=P1^7;
#endif

sbit SCR=P3^3;
sbit SCI0=P3^5;
sbit SCI1=P3^4;

unsigned int i;

char j;

unsigned char k=0;

unsigned keyin;

unsigned dis[8];

unsigned char timer1=0;


                             /*                 a                   */
                             /*            ------------             */
                             /*            |          |             */
                             /*          f |          | b           */
                             /*            |    g     |             */
                             /*             ----------              */
                             /*            |          |             */
                             /*          e |          | c           */
                             /*            |    d     |             */
                             /*             ----------   。dp       */  

                             /*     dp  g   f   e   d   c   b   a   */
unsigned char tab[]={ 0x3f,  /* 0:  0   0   1   1   1   1   1   1   */
                      0x06,  /* 1:  0   0   0   0   0   1   1   0   */
                      0x5b,  /* 2:  0   1   0   1   1   0   1   1   */
                      0x4f,  /* 3:  0   1   0   0   1   1   1   1   */
                      0x66,  /* 4:  0   1   1   0   0   1   1   0   */
                      0x6d,  /* 5:  0   1   1   0   1   1   0   1   */
                      0x7d,  /* 6:  0   1   1   1   1   1   0   1   */
                      0x27,  /* 7:  0   0   1   0   0   1   1   1   */
                      0x7f,  /* 8:  0   1   1   1   1   1   1   1   */
                      0x6f,  /* 9:  0   1   1   0   1   1   1   1   */
                      0x77,  /* a:  0   1   1   1   0   1   1   1   */
                      0x7c,  /* b:  0   1   1   1   1   1   0   0   */
                      0x39,  /* c:  0   0   1   1   1   0   0   1   */
                      0x5e,  /* d:  0   1   0   1   1   1   1   0   */
                      0x79,  /* e:  0   1   1   1   1   0   0   1   */
                      0x71,  /* f:  0   1   1   1   0   0   0   1   */
                      0x00,  /*  :  0   0   0   0   0   0   0   0   */
                      0x40   /* -:  0   1   0   0   0   0   0   0   */
                    };

unsigned char const xchgtab[]={ 0x01, 0x02, 0x04, 0x05, 0x07, 0x08, 0x00, 0x0f, 
                               0x03, 0x0a, 0x06, 0x0b, 0x09, 0x0c, 0x0e, 0x0d };

/***************************************************
 * 主程序入口。                                    *
 ***************************************************/
void main (void)  
{ 

/***************************************************
 * 设置 T0 定时器的工作模式为16位计数              *
 ***************************************************/
  TMOD |= 0x01;

/***************************************************
 * 设置 TH0 寄存器的初值,因为在中断处理程序里还要 *
 * 对其付值,所以这里所付的数值对定时长度没有影响。* 
 ***************************************************/        
  TH0   = 0xff;

/***************************************************
 * 起动 T0 定时器。                                *
 ***************************************************/
  TR0   = 1;       

/***************************************************
 * 允许 T0 定时器中断,并将全局中断控制位置为允许。*
 ***************************************************/
  IE   |= 0x82; 

/***************************************************
 * 向显示缓冲区填充空格。                          *
 ***************************************************/
  for(i=0;i<8;i++){
    dis[i] = tab[16];
  }                        

  while(1){

/***************************************************
 * 键盘缓冲区为0,则表示没按键按下,向0位数码管和1 *
 * 位数码管的显示缓冲区写入"-"的段码。             *
 ***************************************************/
    if(keyin==0){ 
      dis[0] = tab[17];
      dis[1] = tab[17];
    } else {

/***************************************************
 * 有按键按下,则将扫描码转成显示码,化成十进制后  *
 * 分别将十位数的段码和个位数的段码送到1号数码管的 *
 * 显示缓冲区和0号数码管的显示缓冲区。             *
 ***************************************************/
      dis[0] = tab[xchgtab[keyin-1]%10];
      dis[1] = tab[xchgtab[keyin-1]/10];
    }
  } 
}                               

/***************************************************
 * T0 的中断处理程序,每1毫秒执行一次,做键盘扫描,*
 * 给变量 timer1 加 1。                            *
 ***************************************************/

dir() interrupt 1
{
  static unsigned char i,k;
/***************************************************
 * 给定时器T0付初值。                              *
 ***************************************************/
  TL0=0x67;
  TH0=0xfc;

/***************************************************
 * 向数码管的段驱动口写入0x00,关闭LED显示,用以消 *
 * 除影子显示。                                    *
 ***************************************************/
  XBYTE[0xb000] = 0x00;

/***************************************************
 * 键盘扫描是按2行8列进行的,i代表列号。 加1使其指 *
 * 向下一列。                                      *
 ***************************************************/
  i++;

  if(i>7){
/***************************************************
 * 如果i大于7,则要归0。同时复位4017,使其送出第1列*
 * 的扫描信号。将上一次完整扫描得出的结果送入键盘缓*
 * 冲区(keyin)。临时变量k清0。                     *
 ***************************************************/
    i=0;
    SCR=1;
    SCR=0;
    keyin=k;
    k=0;
  }else{
/***************************************************
 * 如果i不大于7,则向4017送一个时钟脉冲,使其送出下*
 * 一列的扫描信号。                                *
 ***************************************************/
    SCC=1;
    SCC=0;
  }

/***************************************************
 * 向数码管的段驱动口写入对应位的段值。            *
 ***************************************************/
  XBYTE[0xb000]=dis[i];

/***************************************************
 * 检测行线 SCI0 是否有效,如果有效,计算对应的键值*
 * 保存在临时变量k中。                             *
 ***************************************************/
  if(SCI0){
    if(k==0){
      k=i+1;
    }
  }

/***************************************************
 * 检测行线 SCI1 是否有效,如果有效,计算对应的键值*
 * 保存在临时变量k中。                             *
 ***************************************************/
  if(SCI1){
    if(k==0){
      k=i+9;
    }
  }

/***************************************************
 * 时间变量 timer1 加1,该变量用定时。             *
 ***************************************************/
  timer1++;
}




管理员信箱: stonewayqi@hotmail.com

欣 欣 学 习 网

粤ICP备2023138008号