//***********************************************************************
// 包含文件
//***********************************************************************
#include <string.h>
#include <stdio.h>
#define F_CPU 7372800 /* 单片机主频为7.3728MHz,用于延时子程序 */
#include <util/delay.h>
#include <avr/io.h>
#include <avr/iom16.h>
//***********************************************************************
// 定义变量区
// CH451各个功能命令值,根据需要写入
//***********************************************************************
#define delay_us(x) _delay_us(x) //AVR GCC延时函数 x(us)
#define delay_ms(x) _delay_ms(x) //AVR GCC延时函数 x(ms)
#define CH451_RESET 0x0201 //复位
#define CH451_LEFTMOV 0x0300 //设置移动方式-左移
#define CH451_LEFTCYC 0x0301 //设置移动方式-左循
#define CH451_RIGHTMOV 0x0302 //设置移动方式-右移
#define CH451_RIGHTCYC 0x0303 //设置移动方式-右循
#define CH451_SYSOFF 0x0400 //关显示、键盘、看门狗
#define CH451_SYSON1 0x0401 //开显示
#define CH451_SYSON2 0x0403 //开显示、键盘
#define CH451_SYSON3 0x0407 //开显示、键盘、看门狗功能
#define CH451_DSP 0x0500 //设置默认显示方式
#define CH451_BCD 0x058f //设置BCD译码方式
#define CH451_TWINKLE 0x0600 //设置闪烁控制
#define CH451_DIG0 0x0800 //数码管位0显示
#define CH451_DIG1 0x0900 //数码管位1显示
#define CH451_DIG2 0x0a00 //数码管位2显示
#define CH451_DIG3 0x0b00 //数码管位3显示
#define CH451_DIG4 0x0c00 //数码管位4显示
#define CH451_DIG5 0x0d00 //数码管位5显示
#define CH451_DIG6 0x0e00 //数码管位6显示
#define CH451_DIG7 0x0f00 //数码管位7显示
#define led0 0x0000 //数码管位0显示的数据0
#define led1 0x0001 //数码管位0显示的数据1
#define led2 0x0002 //数码管位0显示的数据2
#define led3 0x0003 //数码管位0显示的数据3
#define led4 0x0004 //数码管位0显示的数据4
#define led5 0x0005 //数码管位0显示的数据5
#define led6 0x0006 //数码管位0显示的数据6
#define led7 0x0007 //数码管位0显示的数据7
#define dclk0 PORTD &= ~(1 << PD6) //串行数据时钟,上升延激活
#define dclk1 PORTD |= (1 << PD6)
#define din0 PORTD &= ~(1 << PD5) //串行数据输出,接CH451的数据输入
#define din1 PORTD |= (1 << PD5)
#define load0 PORTD &= ~(1 << PD4) //串行命令加载,上升延激活
#define load1 PORTD |= (1 << PD4)
#define key_io PORTA //矩阵键盘与PA口相连
#define key_ior PINA //读取IO口值为PINA的值
#define uchar unsigned char
#define uint unsigned int
uchar key;
uchar table[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06, //显示用数据
0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,
0x0e,0x0f};
//*************************************************************************
// 初始化子程序
//*************************************************************************
void system_init()
{
PORTD=0x70;
DDRD=0x70;
}
void ch451_init() //先低后高,选择4线输入
{
din0;
din1;
}
//*************************************************************************
// 输出命令子程序
// 定义一无符号整型变量存储12字节的命令字
//************************************************************************
void ch451_write(unsigned int command)
{
unsigned char i;
load0; //命令开始
for(i=0;i<12;i++)
{ //送入12位数据,低位在前
if(command&1)
{
din1;
}
else
din0;
dclk0;
dclk1; //上升沿有效
command>>=1;
}
load1; //加载数据
}
//*************************************************************************
// 显示函数
//*************************************************************************
void display(uchar num)
{
system_init();
ch451_init();
ch451_write(CH451_SYSOFF); //关显示、键盘、看门狗
ch451_write(CH451_SYSON1); //开显示
ch451_write(CH451_BCD); //设置BCD译码方式
ch451_write(CH451_TWINKLE); //设置闪烁控制
ch451_write(CH451_DIG0|table[num]); //显示键值
ch451_write(CH451_DIG1|table[num]);
ch451_write(CH451_DIG2|table[num]);
ch451_write(CH451_DIG3|table[num]);
ch451_write(CH451_DIG4|table[num]);
ch451_write(CH451_DIG5|table[num]);
ch451_write(CH451_DIG6|table[num]);
ch451_write(CH451_DIG7|table[num]);
}
//**********************************************************************
// 键盘扫描子程序,采用逐键扫描的方式
//**********************************************************************
uchar keyboardscan(void)
{
uchar statevalue,key_checkin,key_check;
key_io=0xf0; //在IO口由输出方式变为输入方式时要延迟一个周期
key_io=0xf0; //采取写两次的方法延时
key_checkin=key_ior; //读取IO口状态,判断是否有键按下
if(key_checkin!=0xf0) //IO口值发生变化则表示有键按下
{
delay_ms(20); //键盘消抖,延时20MS
key_checkin=key_ior;
if(key_checkin!=0xf0)
{
key_io=0xfe; //逐行扫描开始
key_io=0xfe; //写两次延时,下同
key_check=key_ior;
switch (key_check) //根据读到的IO口值判断按键的按下情况
{
case 0xee:key=1;break;
case 0xde:key=2;break;
case 0xbe:key=3;break;
case 0x7e:key=4;break;
}
key_io=0xfd;
key_io=0xfd;
key_check=key_ior;
switch (key_check)
{
case 0xed:key=5;break;
case 0xdd:key=6;break;
case 0xbd:key=7;break;
case 0x7d:key=8;break;
}
key_io=0xfb;
key_io=0xfb;
key_check=key_ior;
switch (key_check)
{
case 0xeb:key=9;break;
case 0xdb:key=10;break;
case 0xbb:key=11;break;
case 0x7b:key=12;break;
}
key_io=0xf7;
key_io=0xf7;
key_check=key_ior;
switch (key_check)
{
case 0xe7:key=13;break;
case 0xd7:key=14;break;
case 0xb7:key=15;break;
case 0x77:key=0;break;
}
}
}
else
{
statevalue=0xff; //无按键时返回值
key=statevalue;
return(key);
}
}
//*************************************************************************
// 主程序
//*************************************************************************
void main()
{
DDRA=0x0f; //PA口上拉电阻使能
PORTA=0xf0; //PA高四位输入低四位输出
while(1)
{
keyboardscan(); //键盘扫描,看是否有按键按下
if(key!=0xff) //如果有按键按下,则显示该按键键值0~15
{
{ switch(key)
{ case 1: display(0x01);break; //根据键值显示到数码管上
case 2: display(0x02);break;
case 3: display(0x03);break;
case 4: display(0x04);break;
case 5: display(0x05);break;
case 6: display(0x06);break;
case 7: display(0x07);break;
case 8: display(0x08);break;
case 9: display(0x09);break;
case 0: display(0x00);break;
case 10: display(0x0a);break;
case 11: display(0x0b);break;
case 12: display(0x0c);break;
case 13: display(0x0d);break;
case 14: display(0x0e);break;
case 15: display(0x0f);break;
}
}
}
}
}