- /*************************************************************************
- 工程名:4×4行列矩阵键盘
- 作 者:老芹
- 用定时器0设置一个基准计时器,代替CPU软件延时,从而解放CPU,避免空耗时
- *************************************************************************/
- #include<STC15F2K60S2.h>
- #include"LCD1602.h"
- #include"hardware.h"
- #include"intrins.h"
- #define uchar unsigned char
- #define uint unsigned int
- uchar code tab[4][4] = { {'1','2','3','A'}, //0~9,A~D,*,#的键值
- {'4','5','6','B'},
- {'7','8','9','C'},
- {'*','0','#','D'}
- };
- uchar temp;
- uchar Timer_10ms_con=0; //10ms定时计数控制
- uchar Timer_10ms=0; //10ms定时计数
- extern LCD_int(); //初始化LCD
- void Timer0_Init(); //定时器0初始化
- void LCD_write_com(uchar com); //写一个字节数据到LCD
- uchar keyscan() //键盘扫描
- {
- uchar key_H,key_L,key_temp,key,row,column;
- key_data = 0xf0; //高四位做输入
- if(key_data == 0xf0) //没有按键动作
- {
- key = 0;
- return(key);
- }
- while(1)
- {
- if(Timer_10ms<5) //替代常规10ms软件延时,如delay(10)类;
- {
- Timer_10ms_con=1;
- key = 0;
- return(key);
- }
- Timer_10ms=0; //10ms到
- Timer_10ms_con=0; //定时计数控制复位
- if(key_data==0xf0) //是干扰,退出
- {
- key = 0;
- return(key);
- }
- key_H = key_data;
- key_data = 0x0f; //低四位做输入
- _nop_(); //STC等高速51单片机,在端口置"1",后,如果立即读数据,会读出不确定值,所以加入短暂延时
- _nop_();
- key_L = key_data;
- while(key_data!=0x0f); //按键是否放开
- key_temp = key_H|key_L;
- switch(key_temp)
- {
- case 0x7e:row=3;column=0;break; //显示"*"
- case 0x7b:row=3;column=2;break; //显示"#"
- case 0xe7:row=0;column=3;break; //显示"A"
- case 0xd7:row=1;column=3;break; //显示"B"
- case 0xb7:row=2;column=3;break; //显示"C"
- case 0x77:row=3;column=3;break; //显示"D"
- case 0x7d:row=3;column=1;break; //显示"0"
- case 0xee:row=0;column=0;break; //显示"1"
- case 0xed:row=0;column=1;break; //显示"2"
- case 0xeb:row=0;column=2;break; //显示"3"
- case 0xde:row=1;column=0;break; //显示"4"
- case 0xdd:row=1;column=1;break; //显示"5"
- case 0xdb:row=1;column=2;break; //显示"6"
- case 0xbe:row=2;column=0;break; //显示"7"
- case 0xbd:row=2;column=1;break; //显示"8"
- case 0xbb:row=2;column=2;break; //显示"9"
- }
- key=tab[row][column];
- return (key);
- }
- }
- void main()
- {
- uchar i; //定时器初始化
- Timer0_Init();
- LCD_int(); //1602液晶模块初始化
- LCD_prints("Welcome");
- P0=0xff;
- while(1)
- {
- temp=keyscan();
- if(temp!=0)
- {
- P0=temp;
- LCD_set_position(0x40+i);
- LCD_printc(temp);
- i++;
- if(i==17)
- {
- i=0;
- LCD_write_com(0x01);
- LCD_prints("Welcome");
- LCD_set_position(0x40+i);
- LCD_printc(temp);
- }
- }
-
- }
- }
- void Timer0_Init() //定时器初始化
- { //2毫秒@11.0592MHz
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD &= 0xF0; //设置定时器模式
- TL0 = 0x9A; //设置定时初值
- TH0 = 0xA9; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- ET0 =1;
- EA = 1;
- }
- void Timer0() interrupt 1 //定时器中断
- { //16位自动重装模式,无需重赋初值
- if(Timer_10ms_con==1) Timer_10ms++;
- }
复制代码
//LCD1602.C
- #include<STC15F2K60S2.h>
- #include "hardware.h"
- #include "lcd1602.h"
- #define uchar unsigned char
- #define uint unsigned int
- void LCD_check_busy() //检测LCD状态
- {
- while(1)
- {
- LCD_EN=0;
- LCD_RS=0;
- LCD_RW=1;
- LCD_DATA=0xff;
- LCD_EN=1;
- if(!LCD_BUSY) break;
- }
- LCD_EN=0;
- }
- void LCD_cls() //LCD清屏
- {
- //LCD_check_busy(); //仿真时该语句可以屏蔽
- LCD_RS=0;
- LCD_RW=0;
- LCD_DATA=1;
- LCD_EN=1;
- LCD_EN=0;
- }
- void LCD_write_com(uchar com) //写指令到LCD
- {
- LCD_check_busy();
- LCD_RS=0;
- LCD_RW=0;
- LCD_DATA=com;
- LCD_EN=1;
- LCD_EN=0;
- }
- void LCD_write_data(uchar LCD_data) //写一个字节数据到LCD
- {
- LCD_check_busy();
- LCD_RS=1;
- LCD_RW=0;
- LCD_DATA=LCD_data;
- LCD_EN=1;
- LCD_EN=0;
- }
- void LCD_set_position(uchar x) //LCD光标定位到x处
- {
- LCD_write_com(0x80+x);
- }
- /*
- void LCD_go_home(void) //LCD光标归位
- {
- LCD_write_instruction(LCD_GO_HOME);
- }
- */
- void LCD_printc(uchar lcd_data) //输出一个字符到LCD
- {
- LCD_write_data(lcd_data);
- }
- void LCD_prints(uchar *lcd_string) //输出一个字符串到LCD
- {
- uchar i=0;
- while(lcd_string[i]!=0x00)
- {
- LCD_write_data(lcd_string[i]);
- i++;
- }
- }
- void LCD_int() //初始化LCD
- {
- LCD_write_com(LCD_AC_AUTO_INCREMENT|LCD_MOVE_DISENABLE);
- LCD_write_com(LCD_DISPLAY_ON|LCD_CURSOR_OFF);
- LCD_write_com(LCD_DISPLAY_DOUBLE_LINE);
- LCD_cls();
- LCD_write_com(LCD_AC_AUTO_INCREMENT|LCD_MOVE_DISENABLE);
- }
复制代码
//LCD1602.H
- #ifndef __LCD_H__
- #define __LCD_H__
- #define LCD_GO_HOME 0x02 //AC=0,光标、画面回HOME位
- //输入方式设置
- #define LCD_AC_AUTO_INCREMENT 0x06 //数据读、写操作后,AC自动增一
- #define LCD_AC_AUTO_DECREASE 0x04 //数据读、写操作后,AC自动减一
- #define LCD_MOVE_ENABLE 0x05 //数据读、写操作,画面平移
- #define LCD_MOVE_DISENABLE 0x04 //数据读、写操作,画面不动
- //设置显示、光标及闪烁开、关
- #define LCD_DISPLAY_ON 0x0C //显示开
- #define LCD_DISPLAY_OFF 0x08 //显示关
- #define LCD_CURSOR_ON 0x0A //光标显示
- #define LCD_CURSOR_OFF 0x08 //光标不显示
- #define LCD_CURSOR_BLINK_ON 0x09 //光标闪烁
- #define LCD_CURSOR_BLINK_OFF 0x08 //光标不闪烁
- //光标、画面移动,不影响DDRAM
- #define LCD_LEFT_MOVE 0x18 //LCD显示左移一位
- #define LCD_RIGHT_MOVE 0x1C //LCD显示右移一位
- #define LCD_CURSOR_LEFT_MOVE 0x10 //光标左移一位
- #define LCD_CURSOR_RIGHT_MOVE 0x14 //光标右移一位
- //工作方式设置
- #define LCD_DISPLAY_DOUBLE_LINE 0x38 //两行显示
- #define LCD_DISPLAY_SINGLE_LINE 0x30 //单行显示
- void LCD_cls(void);
- void LCD_write_data(unsigned char);
- void LCD_initial(void);
- void LCD_set_position(unsigned char);
- void LCD_prints(unsigned char *);
- void LCD_printc(unsigned char);
- #endif
- //hardware.h
- #include<STC15F2K60S2.h>
- #ifndef __HARDWAR_H__
- #define __HARDWAR_H__
- /*---------------------------------------------------------
- LCD数据、控制口定义
- ---------------------------------------------------------*/
- #define LCD_DATA P1 //LCD的数据口
- #define key_data P3 //矩阵键盘的数据口
- sbit LCD_BUSY=LCD_DATA^7; //LCD忙信号位
- sbit LCD_RW=P2^0; //LCD读写控制
- sbit LCD_RS=P2^1; //LCD寄存器选择
- sbit LCD_EN=P2^2; //LCD使能信号*/
- #endif
复制代码
|