74HC164 key scan + display example

Publisher:风轻迟Latest update time:2016-10-29 Source: eefocusKeywords:74HC164 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Source code: 

/***************************************************** 
 * main.c In it: 
 *****************************************************/ 

        kd_init(); 

        // ...... 

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

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

Look at the display and key scan source 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  

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

Keywords:74HC164 Reference address:74HC164 key scan + display example

Previous article:Super simple coding switch (single-button shuttle switch) decoding program
Next article:24c256 operation function, continuous read and write

Recommended ReadingLatest update time:2024-11-15 15:59

C51 dynamic display method of digital tube
Code: #include reg52.h #define uchar unsigned char #define uint unsigned int sbit dula=P2^6; sbit wela=P2^7; uchar num,dunum,wenum; uchar code table_du ={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71}; //Digital tube segment selection code uchar code table_we ={ 0xfe,0xfd,0xfb
[Microcontroller]
Samsung Display will build a new 6th generation OLED production line to produce IT panels
According to Korean media reports, in order to respond to the market demand for IT products, Samsung Display plans to build a laptop OLED production line at the A4 factory in Asan, Chungnam City. It is understood that the production line is planned to have a monthly production capacity of 30,000 glass substrates, ma
[Mobile phone portable]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号