标题:
去除delay()函数的4×4行列矩阵键单片机程序
[打印本页]
作者:
bhjyqjs
时间:
2018-11-30 14:19
标题:
去除delay()函数的4×4行列矩阵键单片机程序
/*************************************************************************
工程名: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
复制代码
作者:
bhjyqjs
时间:
2018-12-1 08:27
仿真板
1.png
(77.1 KB, 下载次数: 48)
下载附件
2018-12-1 08:26 上传
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1