|
点击此处打开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;
}
另外,为了养家糊口,承接工控项目。
我不会无聊地灌水顶贴,请大家有空帮忙顶顶哦。 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|