硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
硬件设计原理图
实现原理
ADSP-EDU-BF53x 开发板上的按键连接到了 CPLD,通过 CPLD 将按键信号与 EBIU 总线和中断管脚 PF0 连接,并将中断数据地址映射在 CPLD 的当有按键按下后,会触发 PF0 中断信号,同时可以通过 EBIU 总线访问中断功能映射到 CPLD 寄存器中的 INTERRUPT_DAT 寄存器,通过访问该寄存器,可以获取键盘的中断源数据,通过读取CPLD 的 KEYBOARD_DAT 寄存器,可以获取当前触发中断的按键的键值。
其寄存器映射如下:
DEVICE_OE 寄存器(读/写):
DEVICE_OE 寄存器地址:0x20320000
DEVICE_OE 寄存器设置硬件设备上一些控制管脚的电平状态。
DEVICE_OE 寄存器位功能
PF0_SET:PF0 模拟 IIC 总线 SCL 接口或 PF0 中断功能使能
1:关闭 I2C_SCL 输入信号, 使能 PF0 中断信号
0:使能 I2C_SCL 输入信号,关闭 PF0 中断信号
使用中断时,将 PF0_SET 位设置为1。
KEYBOARD_DAT 寄存器(读唯一):
KEYBOARD_DAT 寄存器地址:0x20380000
KEYBOARD_DAT 寄存器是按键数据寄存器,通过该寄存器可以读取当前按键键值,通过键值判断当前哪个按键按下。
KEYBOARD_DAT 寄存器位:
INTERRUPT_DAT 寄存器(读唯一):
INTERRUPT_DAT 寄存器地址:0x20360000
INTERRUPT_DAT 寄存器是板卡上所有中断资源的中断源数据寄存器,可以通过该寄存器数据判断出当前中断是哪一个设备产生的。
INTERRUPT_DAT 寄存器位功能:
当中断未触发时,读取的 Bit 位值为 1,当中断触发时,读取的 Bit 位值为 0,根据 Bit 位数据,获取中断设备。SD_INF 为 SD 卡插入查询位,该 bit 位不会触发中断,只能通过读取该寄存器来查询 SD 卡是否插入。
硬件连接示意图
代码实现功能
代码实现了查询法和中断法两种读取按键键值的方式,并将读到键值与按键对应,打印出按键信息。
查询法:
需要将 key.c 文件中的宏开关“#define KEY_INT_ENABLE”注释掉,运行代码后,程序会不停地扫描按键,等待按键触发,按下按键后,则读取键值并打印出按键信息。
中断法:
需要将 key.c 文件中的宏开关“#define KEY_INT_ENABLE”打开,运行代码后,程序会等待中断触发,中断触发后,判断是否为按键中断,如果为按键中断,则读取键值并打印出按键信息,否则退出中断等待下次中断触发。
测试步骤
测试结果
代码会打印出触发按键的信息。
程序源码
#include
#include
#include “cpld.h”
//#define KEY_INT_ENABLE
EX_INTERRUPT_HANDLER(FlagA_ISR);
void Set_PLL(unsigned int pmsel,unsigned int pssel)
{
unsigned int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}
void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc07bb0;
*pEBIU_AMGCTL = 0x000f;
}
void Init_Flags(void)
{
*pFIO_INEN = 0x0001;
*pFIO_DIR = 0x0000;
*pFIO_EDGE = 0x0001;
*pFIO_POLAR = 0x0001;
*pFIO_MASKA_D = 0x0001;
}
void Init_Interrupts(void)
{
*pSIC_IAR0 = 0xffffffff;
*pSIC_IAR1 = 0xffffffff;
*pSIC_IAR2 = 0xffff5fff;
register_handler(ik_ivg12, FlagA_ISR);
*pSIC_IMASK = 0x00080000;
}
EX_INTERRUPT_HANDLER(FlagA_ISR)
{
unsigned char interrupt=0;
unsigned char keydata;
if(~*pINTERRUPT_DAT & KEY_INT)
{
keydata = ~*pKEYBOARD_DAT; //读键值
switch(keydata)
{
case LUK: printf(“The key is left->up\n\r”); break;
case LLK: printf(“The key is left->left\n\r”); break;
case LDK: printf(“The key is left->down\n\r”); break;
case LRK: printf(“The key is left->right\n\r”); break;
case RUK: printf(“The key is right->up\n\r”); break;
case RLK: printf(“The key is right->left\n\r”); break;
case RDK: printf(“The key is right->down\n\r”); break;
case RRK: printf(“The key is right->right\n\r”); break;
default:
}
}
*pFIO_FLAG_C = 0x0001;
}
void main(void)
{
Set_PLL(16,4);
Init_EBIU();
printf(“Please press the Keyboard!\n”);
#ifdef KEY_INT_ENABLE
Init_Interrupts();
ExtIO_Interrupt_Enable();
Interrupt_Enable();
Init_Flags();
#else
unsigned char keydata;
while(1)
{
keydata = ~*pKEYBOARD_DAT; //读键值
if(keydata & LUK)
printf(“The key is left->up\n\r”);
if(keydata & LLK)
printf(“The key is left->left\n\r”);
if(keydata & LDK)
printf(“The key is left->down\n\r”);
if(keydata & LRK)
printf(“The key is left->right\n\r”);
if(keydata & RUK)
printf(“The key is right->up\n\r”);
if(keydata & RLK)
printf(“The key is right->left\n\r”);
if(keydata & RDK)
printf(“The key is right->down\n\r”);
if(keydata & RRK)
printf(“The key is right->right\n\r”);
}
#endif
while(1);
}