- /*************************************************************************
- 工程名: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
復制代碼
|