凌阳十六位单片机电子时钟程序
//==========================================================================
// The information contained herein is the exclusive property of // Sunnnorth Technology Co. And shall not be distributed, reproduced, // or disclosed in whole in part without prior written permission. // (C) COPYRIGHT 2003 SUNNORTH TECHNOLOGY CO.
// ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorized copies. //============================================================================
//============================================================================
// 工程名称: ex3_Clock
// 功能描述: 《实验指导书》综合实验
// 电子时钟
// 通过按键设置时钟,按确认键后,时钟运行。
// IDE环境: SUNPLUS u'nSPTM IDE 1.8.0(or later)
// 涉及的库: CMacro1016.lib
// 组成文件: main.c
// isr.asm/Dig.asm/Key.asm/system.asm
// Dig.inc/SPCE061A.inc/Key.inc
// Dig.h/SPCE061A.h/Key.h
// 硬件连接: IOA口低8位连接1*8数码管的段选
// IOB口IOB15 、IOB14、IOB13、IOB12、IOB2、IOB1、IOB0连接位选
// IOA口高8位连接4*4键盘
// 日期: 2005-10-14 v1.0
//============================================================================
//======================================================== // 文件名称: main.c
// 功能描述: 时钟时间设置和显示
// 维护
记录
混凝土 养护记录下载土方回填监理旁站记录免费下载集备记录下载集备记录下载集备记录下载
: 2005-10-14 v1.0
//======================================================== #include "Key.h"
#include "Dig.h"
#include "SPCE061A.h"
typedef unsigned char uchar;
#define KEY_DEL 11
#define KEY_ENT 12
#define YESCarryFlag 1
#define ClearCarryFlag 0
#define YESIntFlag 1
#define ClearIntFlag 0
#define true 1
#define false 0
unsigned int INTflag; unsigned int KeyVal;
unsigned int KeyDownTimes; //保存按键次数 unsigned int KeycodeLED[6] ; //保存显示的LED数字 unsigned int EnterFg ; //按确认键标识1、有确认键按下0无确认键按下
unsigned int secFlag,minFlag,hourFlag; void clockPro(void); //时钟处理函数 unsigned int SetKeyValPro(void); //设置时钟值的合法性检测函数 unsigned int KeyDataChange(unsigned int Key_Data); //键值转换子程序,把4X4键盘的键值转换成程序所需要的
unsigned int g_Data[11] =
{0x003f,0x0006,0x005b,0x004f,0x0066,0x006d,0x007d,0x0007,0x007f,0x006f};
//0, 1, 2, 3, 4, 5, 6, 7,
8, 9
//========================================================
// 语法格式: int main(void)
// 实现功能: 时钟设置及显示
// 参数: 无
// 返回值: 无
//========================================================
int main()
{
unsigned int i;
KeyDownTimes = 0;
INTflag = 0;
EnterFg = 0;
i = 0;
Key_Init(); //键盘扫描初始化,包括IRQ6的TMB2 128Hz中断
DIG_Init(); //显示初始化,初始端口以及IRQ4的1KHz中断
while(1)
{
if(EnterFg == 0)//判断是否已按下过"确认"键,
{
KeyVal = Key_Get(); //获取键值
KeyVal = KeyDataChange(KeyVal); //转换键值,无键按下或对于本程序无用的键按下时
//返回0xff
switch(KeyVal)
{
case KEY_DEL: //删除键处理
if(KeyDownTimes>0) KeyDownTimes--;
break;
case 0xff: //无效的键值
break;
case KEY_ENT: //确认键处理
if(KeyDownTimes==6)
{
SP_INT_IRQ5();
EnterFg = true;
}
break;
default: //数字键处理
if(KeyDownTimes<6)
{
KeycodeLED[KeyDownTimes] = KeyVal;
if(SetKeyValPro()== true)
{
KeyDownTimes++;
}
}
break;
}
}
for(i=0;i<6;i++) //显示所有键值即时钟
DIG_Set(i+1,g_Data[KeycodeLED[i]]);
clockPro(); //时钟数据处理
F_ClearWatchdog(); //清看门狗
}
}
//=====================================================================
=======================
//语法格式:unsigned int KeyDataChange(unsigned int Key_Data)
//实现功能:键值转换子程序
//参数: Key_Data--机器码
//返回值: 0~12,其中0~9为数字键,10、11、12为功能键;
// 0xff,不合法的键输入
//=====================================================================
=======================
unsigned int KeyDataChange(unsigned int Key_Data)
{
switch(Key_Data)
{
case KEY_0: Key_Data = 7;break;
case KEY_1: Key_Data = 8;break;
case KEY_2: Key_Data = 9;break;
case KEY_3: Key_Data = 0xff;break;
case KEY_4: Key_Data = 4;break;
case KEY_5: Key_Data = 5;break;
case KEY_6: Key_Data = 6;break;
case KEY_7: Key_Data = 0xff;break;
case KEY_8: Key_Data = 1;break;
case KEY_9: Key_Data = 2;break;
case KEY_A: Key_Data = 3;break;
case KEY_B: Key_Data = 0xff;break;
case KEY_C: Key_Data = 11;break;
case KEY_D: Key_Data = 0;break;
case KEY_E: Key_Data = 0xff;break;
case KEY_F: Key_Data = 12;break;
default: Key_Data = 0xff;break;
}
return Key_Data;
}
//=====================================================================
=======================
//语法格式:void SetKeyValPro(void)
//实现功能:设置时钟数据和发行检测函数名称
//参数: 无
//返回值: 1-合法;
// 0-不合法;
//=====================================================================
========================
unsigned int SetKeyValPro(void) {
uchar flag;
switch(KeyDownTimes){
case 0 : if(KeycodeLED[KeyDownTimes]<3)
{ //小时高位
flag = true;
}
else flag = false;
break;
case 1: if(KeycodeLED[KeyDownTimes-1]==2 )
{
if(KeycodeLED[KeyDownTimes]<5) //小时低位
flag = true;
else
flag = false;
}
else
flag = true;
break;
case 2:
case 4:
if(KeycodeLED[KeyDownTimes]<6)
{ //秒和分的高位
flag = true;
}
else flag = false;
break;
case 3:
case 5:
flag = true;
break; //秒和分的地位
default: flag = false;
break;
}
return(flag);
}
//=====================================================================
=======================
//语法格式:void clockPro()
//描述功能:时钟处理函数
//参数: 无
//返回值: 无
//=====================================================================
========================
void clockPro(void)
{
//秒处理
while(INTflag==1)
{
INTflag = ClearIntFlag;
if(KeycodeLED[4] == 5 && KeycodeLED[5] == 9)
{ //判断秒是否需回零
KeycodeLED[4] = 0; //如果为59回零
KeycodeLED[5] = 0;
secFlag = YESCarryFlag; //设置秒进位标识
}
else
{
if(KeycodeLED[5]==9)
{
KeycodeLED[5]= 0;
KeycodeLED[4]++;
}
else KeycodeLED[5]++; //否则秒加一
}
}
//分处理
while(secFlag==1)
{
secFlag = ClearCarryFlag;
if(KeycodeLED[2] == 5 && KeycodeLED[3] ==9)
{ //判断分是否需回零
KeycodeLED[2] = 0; //如果为59回零
KeycodeLED[3] = 0;
minFlag = YESCarryFlag; //设置分进位标识
}
else
{
if(KeycodeLED[3]==9)
{
KeycodeLED[3]= 0;
KeycodeLED[2]++;
}
else KeycodeLED[3]++; //否则分加一
}
}
//时处理
while(minFlag==1)
{
minFlag = ClearCarryFlag;
if(KeycodeLED[0]==2 && KeycodeLED[1] ==3)
{ //判断时是否需回零
KeycodeLED[0] = 0; //如果为23 回零
KeycodeLED[1] = 0;
hourFlag = YESCarryFlag; //设置时进位标识
}
else
{ //否则时加一
if(KeycodeLED[1]==9)
{
KeycodeLED[1]= 0;
KeycodeLED[0]++;
}
else KeycodeLED[1]++;
}
}
}
中断服务函数
.INCLUDE SPCE061A.inc
.INCLUDE key.inc
.INCLUDE Dig.inc
.IRAM
.PUBLIC sum;
.VAR sum=0 // 进入中断的计数器
.TEXT
.PUBLIC _IRQ5;
.PUBLIC _IRQ6;
//.external sum;
.external _INTflag;
.external F_Key_Scan
//=====================================================================
=======================
//函数: FIQ(),IRQ0(),IRQ1(),IRQ2(),IRQ3(),IRQ4(),IRQ5(),IRQ6(),IRQ7()
//语法:void FIQ(void ),void IRQ0(void ),void IRQ1(void ),void IRQ2(void ),void IRQ3(void ),
// void IRQ4(void ),void IRQ5(void ),void IRQ6(void ),void IRQ7(void )
//描述:FIQ(),IRQ0(),IRQ1(),IRQ2(),IRQ3(),IRQ4(),IRQ5(),IRQ6(),IRQ7()中断服务子程序 //参数:无
//返回:无
//=====================================================================
======================== .PUBLIC _IRQ4
_IRQ4:
push r1,r5 to [sp]
r1 = C_IRQ4_1KHz
test r1,[P_INT_Ctrl]
jnz ?L_IRQ4_1KHz
r1 = C_IRQ4_2KHz
test r1,[P_INT_Ctrl]
jnz ?L_IRQ4_2KHz
?L_IRQ4_4KHz:
call F_DIG_Drive //数码管显示,F_DIG_Drive函数在Dig.asm中定义
r1 = C_IRQ4_4KHz
[P_INT_Clear] = r1
pop r1,r5 from [sp]
reti
?L_IRQ4_2KHz:
[P_INT_Clear] = r1
pop r1,r5 from [sp]
reti
?L_IRQ4_1KHz:
[P_INT_Clear] = r1
pop r1,r5 from [sp]
reti
//////////////////////////////
_IRQ5: //定时1秒的中断程序
push r1,r4 to [sp];
r1 =0x0008;
test r1,[P_INT_Ctrl];
jnz L_4Hz; // Timer A FIQ entrence
r1 = 0x0004;
[P_INT_Clear] = r1; //清中断
r1 = [sum] //取时基信号量
r1 += 1;
cmp r1,2;
je loop0;
[sum]=r1 //保存时基信号量
pop r1,r4 from [sp];
reti;
loop0:
r1 = 0x0001;
[_INTflag] = r1; //设置中断标识
r1 = 0
[sum] = r1
pop r1,r4 from [sp];
reti;
L_4Hz:
r1 = 0x0008;
[P_INT_Clear] = r1; //清中断
pop r1,r4 from [sp];
reti;
////////////////////////////// _IRQ6:
push r1,r4 to [sp];
r1=0x0001;
test r1,[P_INT_Ctrl];
jnz _IRQ6_TMB2;
r1=0x0002;
[P_INT_Clear]=r1;
pop r1,r4 from [sp];
reti; _IRQ6_TMB2:
[P_INT_Clear]=r1;
call F_Key_Scan; //扫描键盘
pop r1,r4 from [sp];
reti;
//=====================================================================
=================== // isr.asm结束
//=====================================================================
===================
//====================================================== // The information contained herein is the exclusive property of // Sunnnorth Technology Co. And shall not be distributed, reproduced, // or disclosed in whole in part without prior written permission. // (C) COPYRIGHT 2003 SUNNORTH TECHNOLOGY CO. // ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorized copies. //========================================================
//============================================================ // 文件名称:Dig.asm
// 实现功能:共阴数码管显示驱动程序,使用IRQ4_4KHz中断
// 日期: 2005/12/2
//============================================================
//================================================ // LED段控制端口设定
//================================================
.DEFINE SEG_IO_Port 0 // 若LED段选使用IOA口则采用该行定义
//.DEFINE SEG_IO_Port 1 // 若LED段选使用IOB口则采用该行定义
.DEFINE SEG_IO_HighByte 0 // 若LED段选使用IO口低8位则采用该行定义
//.DEFINE SEG_IO_HighByte 1 // 若LED段选使用IO口高8位则采用该行
定义
//================================================ // LED位控制端口设定
//================================================ //.DEFINE DIG_IO_Port 0 // 若LED位选使用IOA口则采用该行定义
.DEFINE DIG_IO_Port 1 // 若LED位选使用IOB口则采用该行定义
/////----- 数码管的位数 -----/////
.DEFINE DIG_Count 6
/////----- 数码管每一位的控制脚设定 -----/////
.DATA
PIN_DIG:
.DW 0x8000,0x4000,0x2000,0x1000,0x0004,0x0002,0x0001
/////----- 数码管所有位的控制脚设定,应等于PIN_DIG所有数之和 -----///// .DEFINE PIN_DIG_ALL 0xf007
//================================================
// 不必修改下面的定义
//================================================
.IF SEG_IO_Port==0
.DEFINE P_SEG_Data 0x7000
.DEFINE P_SEG_Buf 0x7001
.DEFINE P_SEG_Dir 0x7002
.DEFINE P_SEG_Attrib 0x7003
.ELSE
.DEFINE P_SEG_Data 0x7005
.DEFINE P_SEG_Buf 0x7006
.DEFINE P_SEG_Dir 0x7007
.DEFINE P_SEG_Attrib 0x7008
.ENDIF
.IF SEG_IO_HighByte==0
.DEFINE PIN_SEG_ALL 0x00ff
.ELSE
.DEFINE PIN_SEG_ALL 0xff00
.ENDIF
.IF DIG_IO_Port==0
.DEFINE P_DIG_Data 0x7000
.DEFINE P_DIG_Buf 0x7001
.DEFINE P_DIG_Dir 0x7002
.DEFINE P_DIG_Attrib 0x7003
.ELSE
.DEFINE P_DIG_Data 0x7005
.DEFINE P_DIG_Buf 0x7006
.DEFINE P_DIG_Dir 0x7007
.DEFINE P_DIG_Attrib 0x7008
.ENDIF
//================================================
// 中断常量定义
//================================================
.DEFINE P_INT_Mask 0x702d .DEFINE C_IRQ4_4KHz 0x0040
//================================================
// 变量定义
//================================================
.RAM
R_DIG_Buf: .DW DIG_Count DUP (?) // 数码管显示缓冲区 .IRAM
R_CurDIG: .DW 0xffff // 当前显示的数码管位,0xffff表示不显示
//================================================
// 公有函数声明
//================================================
.PUBLIC F_DIG_Init
.PUBLIC _DIG_Init
.PUBLIC F_DIG_Set
.PUBLIC _DIG_Set
.PUBLIC F_DIG_SetAll
.PUBLIC _DIG_SetAll
.PUBLIC F_DIG_Get
.PUBLIC _DIG_Get
.PUBLIC F_DIG_GetAll
.PUBLIC _DIG_GetAll
.PUBLIC F_DIG_Clear
.PUBLIC _DIG_Clear
.PUBLIC F_DIG_Drive
.PUBLIC _DIG_Drive
.PUBLIC F_DIG_Off
.PUBLIC _DIG_Off
.PUBLIC F_DIG_On
.PUBLIC _DIG_On
.code
//======================================================
// 函数名称: DIG_Init
// C调用: void DIG_Init(void)
// 汇编调用: F_DIG_Init
// 实现功能: 数码管显示初始化,该函数将开启IRQ4_4KHz中断 // 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_Init:
F_DIG_Init:
push r1,bp to [sp]
INT Off
r1 = DIG_Count
r2 = 0x0000
bp = R_DIG_Buf
?DIG_InitBuf: // 清除显示缓冲区
[bp++] = r2
r1 -= 1
jnz ?DIG_InitBuf
[R_CurDIG] = r2 // 当前显示的位设置为0
r1 = [P_SEG_Attrib] // 初始化段选IO
r1 |= PIN_SEG_ALL
[P_SEG_Attrib] = r1
r1 = [P_SEG_Buf]
r1 &= ~PIN_SEG_ALL
[P_SEG_Data] = r1
r1 = [P_SEG_Dir]
r1 |= PIN_SEG_ALL
[P_SEG_Dir] = r1
r1 = [P_DIG_Attrib] // 初始化位选IO
r1 |= PIN_DIG_ALL
[P_DIG_Attrib] = r1
r1 = [P_DIG_Buf]
r1 &= ~PIN_DIG_ALL
[P_DIG_Buf] = r1
r1 = [P_DIG_Dir]
r1 |= PIN_DIG_ALL
[P_DIG_Dir] = r1
r1 = [P_INT_Mask] // 开启IRQ4_4KHz中断
r1 |= C_IRQ4_4KHz
[P_INT_Mask] = r1
INT FIQ,IRQ
pop r1,bp from [sp] retf
//======================================================
// 函数名称: DIG_Set
// C调用: void DIG_Set(unsigned DigPos, unsigned DigBuffer)
// 汇编调用: F_DIG_Set
// 实现功能: 设置数码管某一位的显示内容
// 入口参数: DigPos(r1) - 设置的数码管位(1~DIG_Count) // DigBuffer(r2) - 数码管的显示内容 // 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_Set:
push r1,r2 to [sp]
r1 = sp + 5
r1 = [r1]
r2 = sp+6
r2 = [r2]
call F_DIG_Set
pop r1,r2 from [sp]
retf
F_DIG_Set:
push bp to [sp]
.IF SEG_IO_HighByte==1
r2 = r2 lsl 4
r2 = r2 lsl 4
.ENDIF
r1 -= 1
cmp r1,DIG_Count // 如果"位"值超出范围则退出
ja ?Exit
bp = R_DIG_Buf // 将R_DIG_Buf的相应元素修改为设定值
bp += r1
[bp] = r2
?Exit:
pop bp from [sp]
retf
//======================================================
// 函数名称: DIG_SetAll
// C调用: void DIG_SetAll(unsigned *DigBuffer)
// 汇编调用: F_DIG_SetAll
// 实现功能: 设置所有数码管的显示内容
// 入口参数: DigBuffer(r1) - 数码管显示内容的起始地址 // 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_SetAll:
push bp to [sp]
bp = sp
r1 = [bp+4]
call F_DIG_SetAll
pop bp from [sp] retf
F_DIG_SetAll:
push r2,bp to [sp]
bp = r1
r2 = DIG_Count
r3 = R_DIG_Buf
?DIG_Set_Loop:
r1 = [bp++] // 将R_DIG_Buf修改为设定值
.IF SEG_IO_HighByte==1
r1 = r1 lsl 4
r1 = r1 lsl 4
.ENDIF
[r3++] = r1
r2 -= 1
jnz ?DIG_Set_Loop
pop r2,bp from [sp] retf
//======================================================
// 函数名称: DIG_Get
// C调用: unsigned DIG_Get(unsigned DigPos)
// 汇编调用: F_DIG_Get
// 实现功能: 获取所有数码管的显示内容 // 入口参数: DigPos(r1) - 要获取显示内容的位 // 出口参数: 该位数码管的显示内容 // 破坏寄存器: 无
//======================================================
_DIG_Get:
push bp to [sp]
bp = sp
r1 = [bp+4]
call F_DIG_Get
pop bp from [sp] retf
F_DIG_Get:
push r2 to [sp]
r2 = R_DIG_Buf
r2 += r1
r1 = [r2]
.IF SEG_IO_HighByte==1
r1 = r1 lsr 4
r1 = r1 lsr 4
.ENDIF
pop r2 from [sp] retf
//======================================================
// 函数名称: DIG_GetAll // C调用: unsigned *DIG_GetAll(unsigned *DigBuffer)
// 汇编调用: F_DIG_GetAll // 实现功能: 获取所有数码管的显示内容 // 入口参数: DigBuffer(r1) - 保存数码管显示内容的起始地址
// 出口参数: 保存数码管显示内容的起始地址 // 破坏寄存器: 无
//======================================================
_DIG_GetAll:
push bp to [sp]
bp = sp
r1 = [bp+4]
call F_DIG_GetAll
pop bp from [sp] retf
F_DIG_GetAll:
push r2,bp to [sp]
bp = r1
r2 = DIG_Count
r3 = R_DIG_Buf
?DIG_Get_Loop:
r4 = [r3++]
.IF SEG_IO_HighByte==1
r4 = r4 lsr 4
r4 = r4 lsr 4
.ENDIF
[bp++] = r4
r2 -= 1
jnz ?DIG_Get_Loop
pop r2,bp from [sp] retf
//======================================================
// 函数名称: DIG_Clear
// C调用: void DIG_Clear(void) // 汇编调用: F_DIG_Clear
// 实现功能: 清空所有数码管显示内容
// 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_Clear:
F_DIG_Clear:
push r1, r2 to [sp]
r1 = R_DIG_Buf
r2 = 0x00
?L:
[r1] = r2
r1 += 1
cmp r1, R_DIG_Buf+DIG_Count
jb ?L
pop r1, r2 from [sp]
retf
//======================================================
// 函数名称: DIG_Drive
// C调用: void DIG_Drive(void) // 汇编调用: F_DIG_Drive
// 实现功能: 数码管显示函数,由IRQ4_4KHz中断服务程序调用 // 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_Drive:
F_DIG_Drive:
push r1,r4 to [sp]
r1 = [R_CurDIG] // 如果不显示则直接退出
cmp r1,0xffff
je ?DIG_Exit
r2 = r1 + R_DIG_Buf
r2 = [r2]
r2 &= PIN_SEG_ALL
r3 = [P_DIG_Buf] // 清除当前位显示
r3 &= ~PIN_DIG_ALL
[P_DIG_Data] = r3
r4 = [P_SEG_Buf] // 段数据设置
r4 &= ~PIN_SEG_ALL
r4 |= r2
[P_SEG_Data] = r4
r3 = [P_DIG_Buf] // 位数据设置
r4 = r1 + PIN_DIG
r3 |= [r4]
[P_DIG_Data] = r3
r1 += 1
cmp r1,DIG_Count
jb ?DIG_Next // R_CurDIG指向下一位 ?DIG_Reverse:
r1 = 0 // 若已显示到最后一位则R_CurDIG指向第一位
?DIG_Next:
[R_CurDIG] = r1
?DIG_Exit:
pop r1,r4 from [sp] retf
//======================================================
// 函数名称: DIG_Off
// C调用: void DIG_Off(void) // 汇编调用: F_DIG_Off
// 实现功能: 停止数码管显示
// 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_Off:
F_DIG_Off:
push r1 to [sp]
r1 = [P_DIG_Buf]
r1 &= ~PIN_DIG_ALL
[P_DIG_Buf] = r1
r1 = 0xffff
[R_CurDIG] = r1
pop r1 from [sp]
retf
//======================================================
// 函数名称: DIG_On
// C调用: void DIG_On(void) // 汇编调用: F_DIG_On
// 实现功能: 恢复数码管显示
// 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
_DIG_On:
F_DIG_On:
push r1 to [sp]
r1 = 0
[R_CurDIG] = r1
pop r1 from [sp]
retf
//====================================================== // The information contained herein is the exclusive property of // Sunnnorth Technology Co. And shall not be distributed, reproduced, // or disclosed in whole in part without prior written permission. // (C) COPYRIGHT 2003 SUNNORTH TECHNOLOGY CO. // ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorized copies. //========================================================
//============================================================ // 文件名称:Key.asm
// 实现功能:4*4按键扫描程序,使用IRQ6_TMB2中断(128Hz)
// 日期: 2005/6/18
//============================================================
//================================================ // 按键去抖动时间设定,单位为1/128秒
//================================================ .DEFINE Key_Debounce 4 //(4/128)秒=31ms
//================================================ // 持续按键时间间隔设定,单位1/128秒
//================================================ .DEFINE Key_TimeOut 64 //(64/128)秒=0.5s
//================================================ // 按键使用端口设定
//================================================ .DEFINE Key_IO_Port 0 // 若按键使用IOA口则采用该行定义
//.DEFINE Key_IO_Port 1 // 若按键使用IOB口则采用该行定义
//.DEFINE Key_IO_HighByte 0 // 若按键使用IO口低8位则采用该行定义
.DEFINE Key_IO_HighByte 1 // 若按键使用IO口高8位则采用该行定义
/////----- 不必修改下面的定义 -----/////
.IF Key_IO_HighByte==0
.DEFINE Key_ALL 0x00ff
.define Key_NibbleL 0x000f
.define Key_NibbleH 0x00f0 .ELSE
.DEFINE Key_ALL 0xff00
.define Key_NibbleL 0x0f00
.define Key_NibbleH 0xf000 .ENDIF
/////----- 不必修改下面的定义 -----///// .IF Key_IO_Port==0
.DEFINE P_Key_Data 0x7000
.DEFINE P_Key_Buf 0x7001
.DEFINE P_Key_Dir 0x7002
.DEFINE P_Key_Attrib 0x7003 .ELSE
.DEFINE P_Key_Data 0x7005
.DEFINE P_Key_Buf 0x7006
.DEFINE P_Key_Dir 0x7007
.DEFINE P_Key_Attrib 0x7008 .ENDIF
.DEFINE P_INT_Mask 0x702d .DEFINE P_TimeBase_Setup 0x700e .DEFINE C_IRQ6_TMB2 0x0001 .DEFINE C_TMB2_128Hz 0x0000
.PUBLIC F_Key_Init
.PUBLIC _Key_Init
.PUBLIC F_Key_Scan
.PUBLIC _Key_Scan
.PUBLIC F_Key_Get
.PUBLIC _Key_Get
.RAM
.VAR KeyCode // 存储获得的键值 .VAR ScanCnt // 该变量用来表示按键持续时间 .VAR KeyUp // 按键是否处于抬起状态
.CODE
//======================================================
// 函数名称: Key_Init
// C调用: void Key_Init(void) // 汇编调用: F_Key_Init
// 实现功能: 初始化按键扫描程序,该函数将开启IRQ6_TMB2中断
// 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
F_Key_Init:
_Key_Init:
push r1 to [sp]
INT Off
r1 = [P_Key_Dir] // 初始化IO, 低4位下拉输入,高4位输出高
r1 |= Key_NibbleH
r1 &= ~Key_NibbleL
[P_Key_Dir] = r1
r1 = [P_Key_Attrib]
r1 |= Key_NibbleH
r1 &= ~Key_NibbleL
[P_Key_Attrib] = r1
r1 = [P_Key_Buf]
r1 |= Key_NibbleH
r1 &= ~Key_NibbleL
[P_Key_Data] = r1
r1 = 0
[ScanCnt] = r1 // 初始化变量
[KeyCode] = r1
[KeyUp] = r1
r1 = C_TMB2_128Hz // 开启IRQ6_TMB2(128Hz)中断
[P_TimeBase_Setup] = r1
r1 = [P_INT_Mask]
r1 |= C_IRQ6_TMB2
[P_INT_Mask] = r1
INT FIQ,IRQ
pop r1 from [sp]
retf
//======================================================
// 函数名称: Key_Scan
// C调用: void Key_Scan(void) // 汇编调用: F_Key_Scan
// 实现功能: 按键扫描,该函数被IRQ6_TMB2中断服务程序调用
// 入口参数: 无
// 出口参数: 无
// 破坏寄存器: 无
//======================================================
F_Key_Scan:
_Key_Scan:
push r1,r4 to [sp]
r2 = [P_Key_Data] // 获取IO端口状态
r2 &= Key_NibbleL
jnz ?L_ScanKey_Down // 判断当前是否有键按下
?L_ScanKey_Up:
r1 = 1 // 如果按键处于抬起状态则KeyUp置1
[KeyUp] = r1
goto ?L_ScanKey_Exit ?L_ScanKey_Down:
r1 = 0 // KeyUp置0
[KeyUp] = r1
r4 = [P_Key_Buf]
r3 = Key_NibbleH & 0x1010
r1 = r4 & ~Key_NibbleH // 扫描第1列(将第1列IO输出置高,检测输入口
状态是否变化)
r1 |= r3
[P_Key_Data] = r1
r1 = [P_Key_Data]
r1 &= Key_NibbleL
jnz ?L_GetCode
r3 = Key_NibbleH & 0x2020 // 扫描第2列
r1 = r4 & ~Key_NibbleH
r1 |= r3
[P_Key_Data] = r1
r1 = [P_Key_Data]
r1 &= Key_NibbleL
jnz ?L_GetCode
r3 = Key_NibbleH & 0x4040 // 扫描第3列
r1 = r4 & ~Key_NibbleH
r1 |= r3
[P_Key_Data] = r1
r1 = [P_Key_Data]
r1 &= Key_NibbleL
jnz ?L_GetCode
r3 = Key_NibbleH & 0x8080 // 扫描第4列
r1 = r4 & ~Key_NibbleH
r1 |= r3
[P_Key_Data] = r1
r1 = [P_Key_Data]
r1 &= Key_NibbleL
jnz ?L_GetCode
jmp ?L_ScanKey_Up // 如果未扫描到按键 ?L_GetCode:
r1 = [P_Key_Buf] // 重新初始化IO
r1 |= Key_NibbleH
[P_Key_Data] = r1
r2 |= r3
.if Key_IO_HighByte
r2 = r2 lsr 4
r2 = r2 lsr 4
.endif
cmp r2,[KeyCode] // 本次得到的键值与上次得到的键值比较
je ?L_ScanKey_Cont
?L_ScanKey_New: // 如果与上次键值不同则重置键值
[KeyCode] = r2
r1 = 1 // 重新记录键持续按下的时间
[ScanCnt] = r1
jmp ?L_ScanKey_Exit
?L_ScanKey_Cont: // 如果此次键值与上次键值相同
r1 = [ScanCnt] // 更新按键持续时间(ScanCnt加1)
r1 += 1
[ScanCnt] = r1
?L_ScanKey_Exit:
pop r1,r4 from [sp]
retf
//======================================================
// 函数名称: Key_Get
// C调用: unsigned Key_Get(void) // 汇编调用: F_Key_Get
// 实现功能: 获取键值
// 入口参数: 无
// 出口参数: r1 - 获得的键值
// 破坏寄存器: r1
//======================================================
F_Key_Get:
_Key_Get:
INT OFF
push r2 to [sp]
r2 = [ScanCnt]
cmp r2,Key_Debounce // 如果按键持续时间小于Key_Debounce
jb ?L_GetKey_NoKey // 则认为当前没有键按下
cmp r2,Key_TimeOut // 如果按键持续时间大于Key_TimeOut
jnb ?L_GetKey // 则认为发生了一次按键
r2 = [KeyUp] // 如果按键持续时间在Key_Debounce与Key_TimeOut
之间
jnz ?L_GetKey // 如果按键处于抬起状态则认为发生了一次按键 ?L_GetKey_NoKey:
r1 = 0 // 没有按键则返回0
jmp ?L_GetKey_Exit
?L_GetKey:
r1 = [KeyCode] // 有按键则返回键值
r2 = 0
[KeyCode] = r2 // 重新初始化变量
[ScanCnt] = r2
[KeyUp] = r2
?L_GetKey_Exit:
INT FIQ,IRQ
pop r2 from [sp]
retf
//============================================================ // 文件名称: system.asm
// 功能描述: 开中断函数
// 维护记录: 2005-10-14 v1.0
//============================================================ .INCLUDE SPCE061A.inc
.RAM
.CODE
//============================================================================================
// C格式: void SP_INT_IRQ5()
// 实现功能:初始化中断为2HZ定时中断源
// 参数:无
// 返回值:无
// 破坏寄存器:r1
//=============================================================================================
.PUBLIC _SP_INT_IRQ5; //初始化中断为2HZ定时中断源
_SP_INT_IRQ5: .PROC
r1 = [P_INT_Ctrl_New]
r1 |= 0x0004;
[P_INT_Ctrl] = r1;
INT IRQ; //开中断
RETF
.ENDP;
//============================================================================================
// C格式: void F_ClearWatchdog(void)
// 实现功能: 清看门狗
// 参数: 无
// 返回值: 无
// 破坏寄存器:r1
//=============================================================================================
.PUBLIC _F_ClearWatchdog; _F_ClearWatchdog: .PROC
r1 = 1;
[P_Watchdog_Clear] = r1;
RETF;
.ENDP