/*---------------------------------------------------*/
/* */
/* MPC82G516键盘显示测试程序 之四 */
/* */
/* 功能 :使用中断方式动态扫描显示,并加入了 */
/* 键盘扫描程序,将16个按键键值以2进制 */
/* 型式,在LED显示器最末二位上显示。 */
/* 输出驱动电流以软件模拟PWM调制控制, */
/* 省略了8个LED段限流电阻 */
/* */
/* 按1#(S9)键可增加显示亮度,按0#(S1))键 */
/* 可减小显示亮度。 */
/* */
/* CPU : MPC82G516 */
/* 晶振 : 24MHz */
/* 作者 : 许意义 */
/* 版本 : V1.0 */
/* 日期 : 2010.4.20 */
/* */
/*---------------------------------------------------*/
#include "REG_MPC82G516.h"
#define PT0H 3
#define LED_Bright_Level 8 // LED亮度调节级数
#define LED_Bright_Preference 6 // 预置LED亮度级数
#define LED_Bright_max 1 // LED最大亮度(数值越小亮度越大,但不能小于1)
#define CtKmin LED_Bright_max // Ct值最小,LED亮度最大
#define CtKmax CtKmin+LED_Bright_Level // Ct值最大,LED亮度最小
#define CtK_Preference CtKmin+(LED_Bright_Level-LED_Bright_Preference) // 预置Ct值
bit LED_bit;
volatile unsigned char Ci;
volatile unsigned char CtK=CtK_Preference;
unsigned char code TAB1[19]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0,0xff}; // 0123456789abCdEF-8.
unsigned char code TAB2[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; // 键扫描位地址
unsigned char BUFF[8]; // 显示缓冲区
unsigned char KEY[2]; // 输入的键值缓存区,高在前,低在后,P3.4、P3.5为键盘扫描输入口
unsigned char KEY_bak[2]; // 上一次输入的键值缓存区备份,用于键盘消抖动
/********************************************** 子程序入口 ****************************************/
/* 低4位LED为共阴,高4位LED为共阳 */
void out_D0(void)
{ P0 = 0;
P1 = 0;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P1M0 &= 0xf0; // 配置P1.3-P1.0为推挽输出口
P1M1 |= 0x0f;
P0 = BUFF[0];
}
void out_D1(void)
{ P0 = 0;
P1 = 0;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P1M0 &= 0x0f; // 配置P1.7-P1.4为推挽输出口
P1M1 |= 0xf0;
P0 = BUFF[1];
}
void out_D2(void)
{ P0 = 0;
P2 = 0;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P2M0 &= 0xf0; // 配置P2.3-P2.0为推挽输出口
P2M1 |= 0x0f;
P0 = BUFF[2];
}
void out_D3(void)
{ P0 = 0;
P2 = 0;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P2M0 &= 0x0f; // 配置P2.7-P2.4为推挽输出口
P2M1 |= 0xf0;
P0 = BUFF[3];
}
void out_D4(void)
{ P0 = 0xff;
P1 = 0xff;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P1M0 &= 0xf0; // 配置P1.3-P1.0为推挽输出口
P1M1 |= 0x0f;
P0 = ~BUFF[4];
}
void out_D5(void)
{ P0 = 0xff;
P1 = 0xff;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P1M0 &= 0x0f; // 配置P1.7-P1.4为推挽输出口
P1M1 |= 0xf0;
P0 = ~BUFF[5];
}
void out_D6(void)
{ P0 = 0xff;
P2 = 0xff;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P2M0 &= 0xf0; // 配置P2.3-P2.0为推挽输出口
P2M1 |= 0x0f;
P0 = ~BUFF[6];
}
void out_D7(void)
{ P0 = 0xff;
P2 = 0xff;
P0M0 = 0; // 配置P0为推挽输出口
P0M1 = 0xff;
P2M0 &= 0x0f; // 配置P2.7-P2.4为推挽输出口
P2M1 |= 0xf0;
P0 = ~BUFF[7];
}
void off_outLED(void) reentrant
{
P0M0 = 0xff; // 配置P0为输入口
P0M1 = 0;
P1M0 = 0xff; // 配置P1为输入口
P1M1 = 0;
P2M0 = 0xff; // 配置P2为输入口
P2M1 = 0;
}
void ms20(void)
{ volatile unsigned int Ia;
for (Ia=0; Ia<20000; Ia++) { ; }
}
/********************************************** 散转子函数表 ****************************************/
code void (*out_list[8])()={
out_D0 , // D0(最低)位显示子程序
out_D1 , // D1位显示子程序
out_D2 , // D2位显示子程序
out_D3 , // D3位显示子程序
out_D4 , // D4位显示子程序
out_D5 , // D5位显示子程序
out_D6 , // D6位显示子程序
out_D7}; // D7(最高)位显示子程序
/********************************************** 中断程序入口 ****************************************/
void time0() interrupt 1 using 1 // 定时中断0, 模拟PWM控制LED亮度
{ static unsigned char Ct;
// 自动重装定时器0 定时常数,定时时间20us,晶振频率24MHz
if (LED_bit == 1) // 执行扫描显示
{
if ((Ct++) >= CtK)
{ Ct = 0;
(*out_list[Ci])();
}
else
{
off_outLED();
}
}
}
void time1() interrupt 3 // 定时中断1
{ unsigned char Cj[2];
TL1 = 0x30; // 设定定时器1 中断定时时间1ms,晶振频率24MHz
TH1 = 0xf8;
LED_bit = 0; // 关扫描显示
off_outLED();
if (++Ci >= 8)
{ Ci = 0;
KEY_bak[0] = KEY[0];
KEY_bak[1] = KEY[1];
KEY[0] = 0;
KEY[1] = 0;
}
P0 = 0xff;
P0M0 = 0; // 配置P0为准双向端口
P0 = TAB2[Ci]; // 输出键扫描位地址
Cj[1] = P3; // 读入键值
P0M0 = 0xff; // 配置P0为输入口
Cj[1] = (~(Cj[1] >> 4)) & 0x03;
Cj[0] = 0;
*((unsigned int *)KEY) |= (*((unsigned int *)Cj)) << (Ci<<1);
LED_bit = 1; // 开扫描显示
}
/********************************************** 主程序入口 ****************************************/
void main(void)
{
off_outLED();
BUFF[0] = TAB1[17];
BUFF[1] = TAB1[16];
BUFF[2] = TAB1[15];
BUFF[3] = TAB1[14];
BUFF[4] = TAB1[13];
BUFF[5] = TAB1[12];
BUFF[6] = TAB1[11];
BUFF[7] = TAB1[10];
TMOD = 0x12; // 设定T0为模式2:8 位自动加载, T1为模式1:16位定时器
TL0 = 0xd8; // 自动重装定时器0 定时常数,定时时间20us,晶振频率24MHz
TH0 = 0xd8;
TL1 = 0x30; // 设定定时器1 中断定时时间1ms,晶振频率24MHz
TH1 = 0xf8;
PT0 = 1; // 设定定时器0 为最高中断级
IPH |= 1<<PT0H;
ET0 = 1; // 开定时器0 中断
ET1 = 1; // 开定时器1 中断
EA = 1; // 开中断总使能
TR0 = 1; // 开定时器0
TR1 = 1; // 开定时器1
while(1)
{ BUFF[0] = TAB1[CtKmax-CtK];
if (((KEY[1]&0x01) != 0) && ((KEY_bak[1]&0x01) != 0)) // '+'
{ if (CtK >= CtKmax) CtK = CtKmax;
else CtK++;
do{ BUFF[0] = TAB1[CtKmax-CtK];
}while(((KEY[1]&0x01) != 0) && ((KEY_bak[1]&0x01) != 0));
}
if (((KEY[1]&0x02) != 0) && ((KEY_bak[1]&0x02) != 0)) // '-'
{ if (CtK <= CtKmin) CtK = CtKmin;
else CtK--;
do{ BUFF[0] = TAB1[CtKmax-CtK];
}while(((KEY[1]&0x02) != 0) && ((KEY_bak[1]&0x02) != 0));
}
ms20();
}
}
/********************************************** 主程序结束 ****************************************/ |