这个也是在暑假电子设计竞赛培训时自己做的,运行结果还可以。
引脚是交叉的,因为用的是P2口,硬件设计时P2的0,2,4,6为行,1,3,5,7为纵(错了就反过来)。
因为从示例程序复制了不少东西,所以有些量是不用的,大家自己斟酌吧。
// 键盘程序,通过P2口接4*4键盘,用扫描法得键值
// 最后通过串口发送该键值。
// EDIT by lineter
// QQ:542375845
#include <c8051f410.h> // SFR declarations
#include <stdio.h>
#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define BAUDRATE 9600 // Baud rate of UART in bps
#define keyport P2
void SYSCLK_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void Timer2_Init (int);
void delay(unsigned int m);
void uart_send(unsigned char m);
unsigned char read_key(void); //返回0xff则表示没有按键按下
void key_up(void); //检测是否按键松开
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
#define UART_BUFFERSIZE 64
unsigned char UART_Buffer[UART_BUFFERSIZE];
unsigned char UART_Buffer_Size = 0;
unsigned char UART_Input_First = 0;
unsigned char UART_Output_First = 0;
unsigned char TX_Ready =1;
static char Byte;
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void)
{
unsigned char key_value;
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
PORT_Init(); // Initialize Port I/O
SYSCLK_Init (); // Initialize Oscillator
UART0_Init();
EA = 1;
while(1)
{
key_value=read_key();
if(key_value!=0xff) //若有按键按下发送
{
key_up();
uart_send(key_value);
}
}
}
void PORT_Init (void)
{
P0MDOUT |= 0x10; // Enable UTX as push-pull output
P2MDIN = 0xFF;
P2MDOUT = 0x00;
P2SKIP = 0xFF;
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}
void SYSCLK_Init (void)
{
OSCICN = 0x87; // configure internal oscillator for
// 24.5MHz
RSTSRC = 0x04; // enable missing clock detector
}
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON |= 0x08; // T1M = 1; SCA1:0 = xx
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x01;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else if (SYSCLK/BAUDRATE/2/256 < 48) {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
} else {
while (1); // Error. Unsupported baud rate
}
TL1 = TH1; // init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TX_Ready = 1; // Flag showing that UART can transmit
IP |= 0x10; // Make UART high priority
ES0 = 1; // Enable UART0 interrupts
}
void UART0_Interrupt (void) interrupt 4
{
if (TI0 == 1) // Check if transmit flag is set
{
TI0 = 0; // Clear interrupt flag
}
}
void delay(unsigned int m)
{
while(m--);
}
//
// 行列对应P2口的偶数位和奇数位,通过反转法得键值。
// 对应返回值为00~0f,若返回0xff则无按键按下。
// 注,若有按键按下,则必须立刻调用key_up()函数等待按键松开。
/
unsigned char read_key(void)
{
unsigned char p,q;
unsigned char tmp1,tmp2;
P2MDOUT = ~0x55;
keyport=0x55;
p=keyport;
if(p!=0x55)
{
delay(10000);
P2MDOUT = ~0x55;
keyport=0x55;
delay(100);
p=keyport;
if (p == 0x55)
return 0xff;
P2MDOUT = ~0xaa;
keyport=0xaa;
delay(100);
q=keyport;
if (q == 0xaa)
return 0xff;
P2MDOUT = 0x00;
tmp1=0;
tmp2=0;
while(q%4)
{
tmp1++;
q/=4;
}
while(p%4)
{
tmp2++;
p/=4;
}
return tmp1+tmp2*4;
}
return 0xff;
}
void key_up(void)
{
unsigned char p;
keyport=0x55;
p=keyport;
while(p!=0x55)
{
p=keyport;
}
delay(10000);
}
void uart_send(unsigned char m)
{
while(TI0==1);
SBUF0=m;
}