状态机编程与键盘设计方法——例9.3简单电话拨号键盘的设计....出问题啦....求助...
参照马老师的教材,写了个4X4的键盘的程序......我用的编译器是 winavr+avr studio.....
http://cache.amobbs.com/bbs_upload782111/files_30/ourdev_567448ZJJGIC.jpg
(原文件名:111.jpg)
http://cache.amobbs.com/bbs_upload782111/files_30/ourdev_567449AJBSFP.jpg
(原文件名:222.jpg)
在这边遇到了问题.....
我必须把if(key_stime_ok)这个函数判断去掉,也就是变成没有了去抖动延时程序,然后proteus才能仿真成功,
不去掉的话....矩阵键盘没法扫描......
求助求助.....我是用proteus仿真的....... #include <avr/io.h>
#define F_CPU 8000000
#include <util/delay.h>
#include <avr/interrupt.h>
#define NO_key 255
#define K1 1
#define K2 2
#define K3 3
#define K4 4
#define K5 5
#define K6 6
#define K7 7
#define K8 8
#define K9 9
#define K10 10
#define K11 11
#define K12 12
#define K13 13
#define K14 14
#define K15 15
#define K16 16
#define Key_mask 0b00001111
#define PORTX PORTD
#define DDRX DDRD
#define PINX PIND
const unsigned char led_7 = {0x3f,0x06,0x5b,0x4f,0x66,0x6d, //字型码
0x7D,0x07,0x7f,0x6f,0x77,0x7c,0x40}; //后3位为A,b,-
const unsigned char position = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
unsigned char dis_buff; //显示缓冲区,存放要显示的8个字符的段码值
static unsigned char key_stime_counter = 0; //??为什么不加voilatil
unsigned char posit = 0;
static unsigned char key_stime_ok = 0;
unsigned char display(void) //8位LED数码管动态扫描函数
{
PORTC = 0xff;
PORTA = led_7];
PORTC = position;
if(++posit >= 8) posit = 0; //?从几开始加
}
//Timer0 比较匹配中断服务,2ms定时
ISR(TIMER0_COMP_vect)
{
display();
if(++key_stime_counter >= 5)
{
key_stime_counter = 0;
key_stime_ok = 1; //定时10ms到
}
}
int main(void)
{
unsigned char i, key_temp;
PORTA = 0x00; //显示控制I/O端口初始化
DDRA = 0xff;
PORTC = 0xff;
DDRC = 0xff;
PORTD = 0x0f; //键盘端口初始化
DDRD = 0xf0; //输入方式,上拉有效
//---------T/C0初始化--------
TCCR0 |= (1 << WGM01) | (1 << CS01) | (1 << CS00); //CTC模式,64分频(8MHz/64=125KHz)
TCNT0 = 0;
OCR0 = 249; //OCR0 = 249,(249+1)/125KHz = 2ms
TIMSK |= (1 << OCIE0); //使能T/C0比较匹配中断
for(i = 0; i < 8; i++) //LED初始化显示8个“-”
{
dis_buff = 12;
}
sei();
while(1)
{
// if(key_stime_ok)
// {
key_stime_ok = 0; //10ms到
key_temp = read_keyboard(); //调用键盘接口函数读取键盘
if(key_temp != NO_key)
{
for(i = 7; i > 0; i--)
{
dis_buff = dis_buff; //LED显示左移1位
}
dis_buff = key_temp; //最右显示新按下键的键值
}
// }
}
} #include <avr/io.h>
#define NO_key 255
#define K1 1
#define K2 2
#define K3 3
#define K4 4
#define K5 5
#define K6 6
#define K7 7
#define K8 8
#define K9 9
#define K10 10
#define K11 11
#define K12 12
#define K13 13
#define K14 14
#define K15 15
#define K16 16
#define Key_mask 0b00001111
#define PORTX PORTD
#define DDRX DDRD
#define PINX PIND
unsigned char read_keyboard(void)
{
static unsigned char key_state = 0, //状态
key_value, //
key_line; //行线
unsigned char key_return = NO_key, i;
switch(key_state)
{
case 0:
key_line = 0b00010000;
for (i = 1; i <= 4; i++) //扫描键盘
{
PORTX = ~key_line; //输出行线电平
PORTX = ~key_line; //必须送2次
key_value = Key_mask & PINX; //读列电平
if(key_value == Key_mask)
{
key_line <<= 1; //没有按键继续扫描
}
else
{
key_state++; //有按键,停止扫描
break; //转消扯抖确认状态
}
}
break;
case 1:
if(key_value == (Key_mask & PINX)) //再次读列电平
{
switch (key_line | key_value) //与状态0的相同,确认按键
{ //键盘编码,返回编码值
case 0b00011110:
key_return = K1;
break;
case 0b00011101:
key_return = K2;
break;
case 0b00011011:
key_return = K3;
break;
case 0b00010111:
key_return = K4;
break;
case 0b00101110:
key_return = K5;
break;
case 0b00101101:
key_return = K6;
break;
case 0b00101011:
key_return = K7;
break;
case 0b00100111:
key_return = K8;
break;
case 0b01001110:
key_return = K9;
break;
case 0b01001101:
key_return = K10;
break;
case 0b01001011:
key_return = K11;
break;
case 0b01000111:
key_return = K12;
break;
case 0b10001110:
key_return = K13;
break;
case 0b10001101:
key_return = K14;
break;
case 0b10001011:
key_return = K15;
break;
case 0b10000111:
key_return = K16;
break;
}
key_state++; //转入等待按键释放状态
}
else
{
key_state--; //两次列电平不同,返回状态0(消抖处理)
}
break;
case 2: //等待按键释放状态
PORTX = 0b00001111; //行线全部输出低电平
PORTX = 0b00001111; //重复送一次
if((Key_mask & PINX) == Key_mask)
{
key_state = 0; //列线全部为高电平,返回状态0
}
break;
}
return key_return;
} 上面是我写的程序.......... 听我的劝告:proteus不是给初学人用的。当你有了一定的基础,回过来再考虑是否学习使用proteus。 我也遇到这问题,顶起 我总觉得这个return key_return; 放错地方了。。。 machao 发表于 2010-7-17 14:59 static/image/common/back.gif
听我的劝告:proteus不是给初学人用的。当你有了一定的基础,回过来再考虑是否学习使用proteus。 ...
马老师,你的状态机资料在哪里呢?能否发个链接 proteus很多问题……特别是涉及到时间,简单到数码管的动态扫描,硬件上能跑的程序proteus不一定能出效果,proteus出效果的硬件上未必能跑…… dongfo 发表于 2013-7-28 23:06 static/image/common/back.gif
proteus很多问题……特别是涉及到时间,简单到数码管的动态扫描,硬件上能跑的程序proteus不一定能出效果, ...
同意你的说法,表示经历过这样的事情
页:
[1]