zywh 发表于 2010-7-13 10:47:52

状态机编程与键盘设计方法——例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仿真的.......

zywh 发表于 2010-7-13 10:48:31

#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;                        //最右显示新按下键的键值       
                        }
//                }
        }
}

zywh 发表于 2010-7-13 10:48:58

#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;
}

zywh 发表于 2010-7-13 10:49:23

上面是我写的程序..........

machao 发表于 2010-7-17 14:59:18

听我的劝告:proteus不是给初学人用的。当你有了一定的基础,回过来再考虑是否学习使用proteus。

jiege0119 发表于 2010-7-31 20:56:27

我也遇到这问题,顶起

XMLK 发表于 2010-9-23 13:47:44

我总觉得这个return key_return; 放错地方了。。。

wt418995874 发表于 2013-7-28 22:57:45

machao 发表于 2010-7-17 14:59 static/image/common/back.gif
听我的劝告:proteus不是给初学人用的。当你有了一定的基础,回过来再考虑是否学习使用proteus。 ...

马老师,你的状态机资料在哪里呢?能否发个链接

dongfo 发表于 2013-7-28 23:06:30

proteus很多问题……特别是涉及到时间,简单到数码管的动态扫描,硬件上能跑的程序proteus不一定能出效果,proteus出效果的硬件上未必能跑……

hongkong 发表于 2013-7-29 10:59:18

dongfo 发表于 2013-7-28 23:06 static/image/common/back.gif
proteus很多问题……特别是涉及到时间,简单到数码管的动态扫描,硬件上能跑的程序proteus不一定能出效果, ...

同意你的说法,表示经历过这样的事情
页: [1]
查看完整版本: 状态机编程与键盘设计方法——例9.3简单电话拨号键盘的设计....出问题啦....求助...