搜索
bottom↓
回复: 70

74HC164键扫+显示实例,已经过项目验证

[复制链接]

出0入0汤圆

发表于 2008-1-25 10:25:38 | 显示全部楼层 |阅读模式
点击此处打开Key & Display Board.pdf(文件大小:205K)

源代码:

/*****************************************************
* main.c 中如此这般:
*****************************************************/

        kd_init();

        // ......

        while (1)
        {
                if( should_update_kd )
                {
                        kd_update();
                }

                // Other code
                // ......
        }
       

再看显示、键扫源代码:

/******************************************************
* key_disp-config.h
******************************************************/

#ifndef _KEY_DISP_CFG_H_
#define _KEY_DISP_CFG_H_

#define DIGIT1        B, 0
#define DIGIT2        B, 1
#define DIGIT3        B, 2
#define DIGIT4        B, 3

#define KEY_FB        D, 6

#define KD_CLR        D, 7
#define KD_CLK        B, 5
#define KD_DAT        B, 4


#define KEY_NONE        (uint8_t)(0xFF)
#define KEY_S1                (uint8_t)(0x01<<0)
#define KEY_S2                (uint8_t)(0x01<<1)
#define KEY_S3                (uint8_t)(0x01<<2)
#define KEY_S4                (uint8_t)(0x01<<3)
#define KEY_S5                (uint8_t)(0x01<<4)
#define KEY_S6                (uint8_t)(0x01<<5)
#define KEY_S7                (uint8_t)(0x01<<6)
#define KEY_S8                (uint8_t)(0x01<<7)


#endif /*_KEY_DISP_CFG_H_*/



/******************************************************
* key_disp.h
******************************************************/

#ifndef _KEY_DISP_H_
#define _KEY_DISP_H_

#include <inttypes.h>

#include "key_disp-config.h"


#define KD_CODE_NONE                        10
#define KD_CODE_PAUSED                        11
#define KD_CODE_CW                                12
#define KD_CODE_CCW                                13
#define KD_CODE_SET_RUN                        14
#define KD_CODE_SET_SLEEP                15
#define KD_CODE_TIMER_RUN                16
#define KD_CODE_TIMER_SLEEP                17
#define KD_CODE_EXTERN_TRIG                18
#define KD_CODE_EXTERN_CTRL                19
#define KD_CODE_H                                20
#define KD_CODE_M                                21
#define KD_CODE_S                                22



// Initialize key & display
void kd_init();

// Update key & display, MUST be called periodically, eg., in timer
void kd_update();

// Get key code
uint8_t kd_get_key();

// Set mode to display
void kd_display_code(uint8_t digit_id, uint8_t code_id);

// Set display digits, dp_pos=-1 means no dp displayed
void kd_display(uint16_t value, uint8_t max_digits, const int8_t dp_pos);


#endif /*_KEY_DISP_H_*/



/******************************************************
* key_disp.c
******************************************************/

#include "avr/io.h"

#include "key_disp.h"
#include "config.h"

#include "util.h"

#define NOP() asm volatile ("nop")


static const uint8_t seg_code[] =
{
        0x3F/*0*/, 0x06/*1*/, 0x5B/*2*/, 0x4F/*3*/, 0x66/*4*/,
        0x6D/*5*/, 0x7D/*6*/, 0x07/*7*/, 0x7F/*8*/, 0x6F/*9*/,
        0x00/*KD_CODE_NONE*/,
        0x73/*KD_CODE_PAUSED*/,
        0x21/*KD_CODE_CW*/,
        0x03/*KD_CODE_CCW*/,
        0x50/*KD_CODE_SET_RUN*/,
        0x6D/*KD_CODE_SET_SLEEP*/,
        0x09/*KD_CODE_TIMER_RUN*/,
        0x36/*KD_CODE_TIMER_SLEEP*/,
        0x79/*KD_CODE_EXTERN_TRIG*/,
        0x39/*KD_CODE_EXTERN_CTRL*/,
        0x76/*KD_CODE_H*/,
        0x20/*KD_CODE_M*/,
        0x22/*KD_CODE_S*/,
};

#define SEG_DP 0x80


static volatile uint8_t _key_code = 0xFF;
static volatile uint8_t _digits[4];

void kd_init()
{
        PORT_DDR_SET(DIGIT1);
        PORT_DDR_SET(DIGIT2);
        PORT_DDR_SET(DIGIT3);
        PORT_DDR_SET(DIGIT4);
        PORT_DDR_CLR(KEY_FB);        // Input
        PORT_DDR_SET(KD_CLR);

        PORT_PIN_CLR(DIGIT1);
        PORT_PIN_CLR(DIGIT2);
        PORT_PIN_CLR(DIGIT3);
        PORT_PIN_CLR(DIGIT4);
        PORT_PIN_SET(KEY_FB);        // Internal pull-up
        PORT_PIN_SET(KD_CLR);

        _digits[0] = _digits[1] = _digits[2] = _digits[3] = 0;
}


/* Takes about 50 us @ 8MHz */
void kd_update()
{
        static uint8_t turn = 0;

        uint8_t i;

        if( turn++ & 0x01 )
                return;

        // Disable all digits first
        PORT_PIN_CLR(DIGIT1);
        PORT_PIN_CLR(DIGIT2);
        PORT_PIN_CLR(DIGIT3);
        PORT_PIN_CLR(DIGIT4);


        if( turn++ & 0x02 )
        {
                //
                // trun for key scan
                //

                uint8_t shift_data;
                static uint8_t last_scan_code = 0;
                static uint8_t last_code_count = 0;

                //
                // Scan key

                PORT_PIN_CLR(KD_CLK);
                PORT_PIN_CLR(KD_CLR);
                PORT_PIN_SET(KD_CLR);

                //
                // All output 1
                shift_data = 0xFF;
                PORT_PIN_SET(KD_DAT);

                while( shift_data )
                {
                        // Pulse out
                        PORT_PIN_SET(KD_CLK);
                        PORT_PIN_CLR(KD_CLK);

                        shift_data >>= 1;
                }

                shift_data = 0x01;

                while( shift_data )
                {
                        if( (~shift_data) & 0x01 )
                                PORT_PIN_SET(KD_DAT);
                        else
                                PORT_PIN_CLR(KD_DAT);

                        // Pulse out
                        PORT_PIN_SET(KD_CLK);
                        PORT_PIN_CLR(KD_CLK);

                        // Delay
                        for( i=0; i<16; i++ )
                                NOP();

                        // Check feedback
                        if( PORT_PIN_VALUE(KEY_FB) == 0 )
                        {
                                if( last_scan_code == shift_data )
                                {
                                        // Same as last scan result, that's the key!
                                        if( last_code_count > 4 )
                                                _key_code = shift_data;

                                        if( last_code_count < 255 )
                                                last_code_count++;
                                }
                                else
                                {
                                        last_scan_code = shift_data;
                                        last_code_count = 1;
                                        _key_code = KEY_NONE;
                                }

                                break;
                        }

                        shift_data <<= 1;
                }

                if( shift_data == 0 )
                {
                        _key_code = KEY_NONE;
                        last_scan_code = KEY_NONE;
                        last_code_count = 1;
                }
        }
        else
        {
                //
                // Turn for display
                //
               
                static uint8_t curr_digit = 0;
                uint8_t curr_code = 0;

                //
                // Display digits

                PORT_PIN_CLR(KD_CLK);
                PORT_PIN_CLR(KD_CLR);
                PORT_PIN_SET(KD_CLR);

                curr_code = _digits[curr_digit];

                for( i=0; i<8; i++ )
                {
                        // MSB first
                        if( curr_code & 0x80 )
                                PORT_PIN_SET(KD_DAT);
                        else
                                PORT_PIN_CLR(KD_DAT);

                        curr_code <<= 1;
               
                        // Pulse out
                        PORT_PIN_SET(KD_CLK);
                        PORT_PIN_CLR(KD_CLK);
                }

                switch( curr_digit ) // 位控制pin可能不连续,所以不能够用移位之类的
                {
                case 0:
                        PORT_PIN_SET(DIGIT4);
                        break;

                case 1:
                        PORT_PIN_SET(DIGIT3);
                        break;

                case 2:
                        PORT_PIN_SET(DIGIT2);
                        break;

                case 3:
                        PORT_PIN_SET(DIGIT1);
                        break;
                }

                // For next trun
                curr_digit++;
                curr_digit %= 4;
        }
}


uint8_t kd_get_key()
{
        return _key_code;
}


void kd_display_code(uint8_t digit_id, uint8_t code_id)
{
        _digits[digit_id] = seg_code[code_id];
}


void kd_display(uint16_t value, uint8_t max_digits, const int8_t dp_pos/*=-1*/)
{
        //
        // Prepare seg code for LED
       
        _digits[0] = seg_code[value % 10];
        value /= 10;

        _digits[1] = seg_code[value % 10];

        if(max_digits > 2)
        {
                value /= 10;
                _digits[2] = seg_code[value % 10];
       
                if(max_digits > 3)
                {
                        value /= 10;
                        _digits[3] = seg_code[value % 10];
                }
        }

        if( dp_pos >=0 && dp_pos<3 )
                _digits[dp_pos] |= SEG_DP;
}



另外,为了养家糊口,承接工控项目。
我不会无聊地灌水顶贴,请大家有空帮忙顶顶哦。

出0入0汤圆

发表于 2008-1-25 10:41:19 | 显示全部楼层
好东西,我顶! 我拆过电磁炉里面就是用这种方案的。

出0入0汤圆

 楼主| 发表于 2008-1-25 10:52:26 | 显示全部楼层
哦,裤子来了

出0入0汤圆

发表于 2008-2-2 14:03:16 | 显示全部楼层
我纯属灌水来了!

出0入0汤圆

发表于 2008-2-2 14:12:37 | 显示全部楼层
我有空帮忙顶顶

出0入0汤圆

发表于 2008-2-2 17:01:20 | 显示全部楼层
初学者,哈哈~

出0入0汤圆

发表于 2008-2-2 18:25:48 | 显示全部楼层
顶一下

出0入0汤圆

发表于 2008-2-3 08:27:10 | 显示全部楼层
这样弄的话在扫描按键时是不是要关掉显示?是不是要影响亮度问题?
不过在显示的基础上只用1根线,就弄了8个按键还是很合算的。

出0入0汤圆

 楼主| 发表于 2008-2-3 10:54:48 | 显示全部楼层
回楼上,扫描按键时的确需要关掉显示
// Disable all digits first
PORT_PIN_CLR(DIGIT1);
PORT_PIN_CLR(DIGIT2);
PORT_PIN_CLR(DIGIT3);
PORT_PIN_CLR(DIGIT4);

最近增加了一片74HC138,可以支持到8位显示
头像被屏蔽

出0入0汤圆

发表于 2008-2-15 17:51:25 | 显示全部楼层
非常不错,不过现在大部分电磁炉的面板显示方案已经逐渐被如下方案代替,付上原理图和范例程序,以飨广大需要的朋友
1
点击此处打开ourdev_214536.pdf(文件大小:15K)
点击此处打开ourdev_214537.pdf(文件大小:156K)

出0入0汤圆

 楼主| 发表于 2008-2-15 19:26:38 | 显示全部楼层
楼上的大哥,谢谢你的样片。
现在的方案是6位显示,74HC138+74HC164,已经超出了贵公司的芯片方案价格。
早知道客户会由4位改成6位,就直接用你的方案了……

出0入0汤圆

发表于 2008-3-6 09:58:30 | 显示全部楼层
dind ding

出0入0汤圆

发表于 2008-3-6 10:05:03 | 显示全部楼层
呵呵 原来我用中颖69P20C做项目是时也是这么连的

出0入0汤圆

发表于 2008-8-8 16:35:33 | 显示全部楼层
楼主的程序有问题吗?
   if( PORT_PIN_VALUE(KEY_FB) == 0 ) 是否改成while( PORT_PIN_VALUE(KEY_FB) == 0 )

出0入0汤圆

发表于 2009-10-8 17:15:08 | 显示全部楼层
M

出0入0汤圆

发表于 2009-10-8 20:49:02 | 显示全部楼层
哈,我家电磁炉三星单片机坏了,我拆开后根据控制板PCB把原理图画出来了,也是用164控制键盘扫描、LED灯、LED数码管,我现在改用AVR16控制,已经可以炒菜了并且能调功率,在软件控制上确实要非常注意,如果谁有兴趣我可以把资料传上来,

出0入0汤圆

发表于 2009-10-8 20:52:49 | 显示全部楼层
【15楼】 xianfen928
哈,我家电磁炉三星单片机坏了,我拆开后根据控制板PCB把原理图画出来了,也是用164控制键盘扫描、LED灯、LED数码管,我现在改用AVR16控制,已经可以炒菜了并且能调功率,在软件控制上确实要非常注意,如果谁有兴趣我可以把资料传上来,
————————————————————
(改后)调温是靠间歇的还是………………?

出0入0汤圆

发表于 2009-10-8 21:43:05 | 显示全部楼层

(原文件名:未命名.JPG)

楼主这个电路和我用的如出一辙,只是我用了两个164,5个口线,驱动4个LED,16个按键

出0入4汤圆

发表于 2009-10-8 21:50:48 | 显示全部楼层
如果两个按键被同时按下呢?

出0入0汤圆

发表于 2009-10-9 09:17:18 | 显示全部楼层
有用

出0入0汤圆

发表于 2009-10-9 16:22:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-10-10 11:01:00 | 显示全部楼层

(原文件名:164.jpg)

我都贴一个,1/4 duty+24Key(方便摆放导入PCB再手动连。

出0入0汤圆

发表于 2009-10-10 11:13:58 | 显示全部楼层
支持两个按钮同时按下,
按钮数据是串入的,8个都同时按下,也能检测到。

出0入0汤圆

发表于 2009-10-10 11:15:59 | 显示全部楼层
LS的,问题是在不检测时两个同时按下会影响显示,我图上加4148就是为了解决这个的。

出0入0汤圆

发表于 2009-10-10 21:14:02 | 显示全部楼层
在按下按键是显示会不会闪烁?

出0入0汤圆

发表于 2009-11-6 20:24:00 | 显示全部楼层
顶!

出0入0汤圆

发表于 2009-11-10 20:14:32 | 显示全部楼层
顶啊

出0入0汤圆

发表于 2010-1-7 14:32:59 | 显示全部楼层
顶顶!

出50入4汤圆

发表于 2010-9-14 10:36:05 | 显示全部楼层
发现大家怎么都不把完整的东西发上来,而且发上来的也有很多问题,不明白是否真的能用?,,这程序我试了不行,turn清0都没有,能用吗?

出0入0汤圆

发表于 2010-9-24 11:16:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-4 14:32:43 | 显示全部楼层
标记学习

出0入0汤圆

发表于 2011-1-6 16:37:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-6 16:40:37 | 显示全部楼层
不错!~

出0入0汤圆

发表于 2011-1-6 16:53:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-1-6 17:51:38 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-2-21 14:30:28 | 显示全部楼层
mark

出0入112汤圆

发表于 2011-2-21 17:56:36 | 显示全部楼层
回复【楼主位】ghost2
-----------------------------------------------------------------------

不错!顶一下

出0入0汤圆

发表于 2011-3-13 22:16:23 | 显示全部楼层
我们也这样用啊

出0入0汤圆

发表于 2011-3-13 22:47:17 | 显示全部楼层
直接用100o的上拉或者推挽模式,不就解决了吗。stc12c5a32s2才7块一个。

出0入0汤圆

发表于 2011-3-14 01:55:20 | 显示全部楼层
记号

出0入0汤圆

发表于 2011-3-14 08:44:51 | 显示全部楼层
mark

出0入4汤圆

发表于 2011-3-14 08:51:01 | 显示全部楼层
mark

出50入0汤圆

发表于 2011-3-14 11:20:40 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-6 22:11:38 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-4-25 16:35:00 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-4-25 20:30:59 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-4-25 21:01:36 | 显示全部楼层
学习

出0入0汤圆

发表于 2011-4-26 12:30:55 | 显示全部楼层
m

出0入0汤圆

发表于 2011-4-27 22:06:22 | 显示全部楼层
学习!

出0入0汤圆

发表于 2011-4-28 16:02:03 | 显示全部楼层
回复【15楼】xianfen928
-----------------------------------------------------------------------

资料传上来吧

出0入0汤圆

发表于 2011-4-28 19:00:47 | 显示全部楼层
好!!!!!!!!!

出0入0汤圆

发表于 2011-4-28 19:06:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-28 20:18:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-28 07:10:24 | 显示全部楼层
74HC164单行多列键盘扫描并显示

出0入0汤圆

发表于 2011-5-28 08:24:43 | 显示全部楼层
mark

出100入143汤圆

发表于 2011-5-28 11:10:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-28 12:17:39 | 显示全部楼层
留名

出0入0汤圆

发表于 2011-9-1 11:20:10 | 显示全部楼层
可能对我有用,先看看

出0入0汤圆

发表于 2011-9-1 11:33:52 | 显示全部楼层
经典!~

出0入0汤圆

发表于 2011-9-2 08:02:38 | 显示全部楼层
非常不错,

出0入0汤圆

发表于 2011-9-2 09:41:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-9 17:32:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-8-29 16:33:03 | 显示全部楼层
Stitch 发表于 2009-10-8 20:52
【15楼】 xianfen928
哈,我家电磁炉三星单片机坏了,我拆开后根据控制板PCB把原理图画出来了,也是用1 ...

哥们,你还有164控制的资料没,很好奇哦,你居然能够控制了,厉害啊

出0入0汤圆

发表于 2013-8-29 16:43:16 | 显示全部楼层
hkap 发表于 2009-10-8 21:43
(原文件名:未命名.JPG)

楼主这个电路和我用的如出一辙,只是我用了两个164,5个口线,驱动4个LED,16个 ...

74hc164这东西好厉害的说,我在研究这个东西,哈哈,我用2个74hc164驱动4个数码管和4个按键,我在按键加减数字时遇到难题了,因为是动态显示,要在按按键的时候,数码管是显示的。好纠结啊

出0入0汤圆

发表于 2013-8-29 16:45:10 | 显示全部楼层
Heavin 发表于 2009-10-10 11:01
(原文件名:164.jpg)

我都贴一个,1/4 duty+24Key(方便摆放导入PCB再手动连。

好牛逼啊  能把资料给看看么 我的扣扣是326103151,求资料有莫有

出0入0汤圆

发表于 2013-8-29 22:48:09 | 显示全部楼层
很久没来AVR论坛,过来顶一下

出0入0汤圆

发表于 2013-8-29 22:54:29 | 显示全部楼层
记号下,用164扩展IO用的也挺多的

出0入0汤圆

发表于 2015-6-7 20:27:54 | 显示全部楼层
学习,这个对于IO口少的MCU来说,太有用了

出0入0汤圆

发表于 2015-6-7 21:14:00 | 显示全部楼层
我也有过类似的经历,但是不用164了,因他是动态的占用定时器,并且电路又复杂,现在的专用显示IC才两三毛钱,两线通信,发个数给显示寄存器什么都不用管,然后再读一下寄存器看一下有没有键按下,就是那个TM的什么东东。

出0入0汤圆

发表于 2015-8-5 21:52:51 | 显示全部楼层
谁能普及下原理

出0入0汤圆

发表于 2015-8-6 08:52:09 | 显示全部楼层
不错不错。顶一下、
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-8 17:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表