|
最近在论坛上看到有前辈说用一片74HC164控制1602和8个按键。发现思路可行,自己也画了个,如图1所示。但是编程时候遇到困难,就是按键按下,单片机能识别按键的值,但是一放开后就很奇怪的编程0值(0也是我的一个按键值),现在程序如下,能驱动1602,主要按键这块有点问题,我觉得思路没有任何错误,其中按键扫描的思路就是输出00000001,看按键返回口是否为高电平,在输出00000010,看按键返回口是否为高电平,依次循环,直到检测完毕为止,(目前没加消抖措施,直接是按键识别)。单片机是ATMEGA48,我主要是为了节省单片机IO口
程序如下:按键识别的:
#include <iom48v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define kongzhi PORTB
#define EN 3
#define CLK 0
#define DQ 1
#define KEY 2
void LCD_INIT(void);
void LCD_STRING(uchar x,uchar y,uchar *p);
void LCDSHOW_CHAR(uchar x,uchar y,uchar ch);
void LCDSHOW_DATA(uchar x,uchar y,uchar num);
void HC164_SEND(uchar byte);
void write_com(uchar com);
void write_dat(uchar dat);
void delayms(uint z);
void delayus(uint z);
uchar KEY_TEST(void);
uchar keyvalue;
void main()
{
LCD_KEY_INIT();
LCDSHOW_CHAR(1,1,'A');
LCDSHOW_DATA(1,2,6);
while(1)
{
keyvalue=KEY_TEST();
// if(keyvalue<=7)
LCDSHOW_DATA(5,1,keyvalue);
}
}
/******************************************************************
函数名称:LCD_KEY_INIT()
入口参数:无
函数功能:LCD函数初始化,包括控制端口的初始化、液晶屏的初始化、按键检测口的初始化
******************************************************************/
void LCD_KEY_INIT(void)
{
DDRB|=BIT(CLK)|BIT(DQ)|BIT(EN);
DDRB&=~BIT(KEY); //按键检测口设置成输入
write_com(0x38);
delayms(1);
write_com(0x0c);
delayms(1);
write_com(0x06);
delayms(1);
write_com(0x01);
delayms(5);
}
/*****************************************************************
函数名称:LCD_STRING(uchar x,uchar y,uchar *p)
函数参数: 坐标(x,y),字符串指针p
函数功能:定点写字符串函数
******************************************************************/
void LCD_STRING(uchar x,uchar y,uchar *p)
{
if(y==1)
write_com(0x80+x);
else if(y==2)
write_com(0xc0+x);
while(*p)
{
write_dat(*p);
p++;
}
}
/******************************************************************
函数名称:LCDSHOW_DATA(uchar x,ucahr y,uchar j)
入口参数:坐标(x,y),数字j
函数功能:定坐标显示数字j
******************************************************************/
void write_com(uchar com)//写命令函数
{
HC164_SEND(com); //先写数据
kongzhi&=~BIT(CLK);//RS与CLK复用,时序上需注遥不能再拉高了,否则数据会变
kongzhi&=~BIT(EN);
delayus(1);
kongzhi|=BIT(EN);
delayus(1);
kongzhi&=~BIT(EN);
}
/******************************************************************
函数名称:LCDSHOW_DATA(uchar x,ucahr y,uchar j)
入口参数:坐标(x,y),数字j
函数功能:定坐标显示数字j
******************************************************************/
void write_dat(uchar dat)//写数据函数
{
HC164_SEND(dat);
kongzhi|=BIT(CLK);
//RS与CLK复用,此时其实不必拉高,因为之前在输入数据完毕的时候已经是拉高了
kongzhi&=~BIT(EN);
delayus(1);
kongzhi|=BIT(EN);
delayus(1);
kongzhi&=~BIT(EN);
}
/******************************************************************
函数名称:LCDSHOW_CHAR(uchar x,ucahr y,uchar ch)
入口参数:坐标(x,y),字母ch
函数功能:定坐标显示字母ch
******************************************************************/
void LCDSHOW_CHAR(uchar x,uchar y,uchar ch)
{
if(y==1)
write_com(0x80+x);
else if(y==2)
write_com(0xc0+x);
write_dat(ch);
}
/******************************************************************
函数名称:LCDSHOW_DATA(uchar x,ucahr y,uchar num)
入口参数:坐标(x,y),数字num
函数功能:定坐标显示数字num
******************************************************************/
void LCDSHOW_DATA(uchar x,uchar y,uchar num)
{
if(y==1)
write_com(0x80+x);
else if(y==2)
write_com(0xc0+x);
write_dat(0x30+num);
}
/******************************************************************
函数名称:HC164_SEND(uchar byte )
入口参数:byte
函数功能:将一个数据输入到74hc164的输出端,数据的低位对应Q0,数据高位对应Q7
******************************************************************/
void HC164_SEND(uchar byte )
{
signed char i; //这里不能使用 char ,因为char 默认为unsigned char,没有负数
for(i=7;i>=0;i--)
{
kongzhi&=~BIT(CLK); //时钟拉低N拉高做准备
if(byte & (1<<i))
kongzhi|=BIT(DQ);
else
kongzhi&=~BIT(DQ); //若byte的某位为1,则输出1,否则输出0
kongzhi|=BIT(CLK); //时钟拉高,移入数据
}
}
/******************************************************************
函数名称:delayms(uint z)
入口参数:z
函数功能:粗略延时z ms
******************************************************************/
void delayms(uint z)
{
uint i,j;
for( i=0;i<z;i++)
for(j=0;j<1141;j++); //1141是在8MHz晶振下,通过软件仿真反复实验得到的数值
}
/******************************************************************
函数名称:delayus(uint z)
入口参数:z
函数功能:粗略延时z us
******************************************************************/
void delayus(uint z)
{
uint i;
z=z*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
for( i=0;i<z;i++);
}
/******************************************************************
函数名称: KEY_TEST(void)
入口参数:无
函数功能:只读一个按键的值函数
******************************************************************/
uchar KEY_TEST(void)
{
uchar i;
for(i=0;i<=7;i++)
{
HC164_SEND(BIT(i));
if(PINB&BIT(KEY))
{
LCDSHOW_DATA(9,1,i);//检测有没有一直进这个if语句,果然进了,但不知为何
return i; //检测到第i个键被按下了 ,返回相应键值
}
}
return 8;
} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
|