我们从最基础的GPIO开始,先讲外设,这玩意不管是单片机,还是ARM,又或是FPGA,甚至SOC的芯片,都有GPIO,有共性,就好理解,让我们看看在ADI的DSP里头,GPIO是怎么一回事吧。
硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
接口功能介绍
ADSP-BF53x 处理器上有 16 个 Programmable Flag 接口,简称 PF 接口,这些接口就是通常所有的 IO 接口,通过寄存器配置,可以输出电平和感知接口电平,每一个 PF 接口都可以作为外部中断接口。
在单片机上,通常如果设置一个 IO 接口输出时,直接将输出信号值付给该接口,如果作为输入时,直接通过该接口读取即可。
而Blackfin 处理器的 IO 使用与单片机不同,在使用前必须对该接口进行初始化,如告知接口的方向,如配置为输出接口,则直接配置输出接口电平信号,如配置为输入接口,需打开输入使能开关,配置输出信号触发方式,是否中断触发,是否双极性触发等等。初始化完成后,才能使用 PF 接口。
接口寄存器说明
核心代码分析
输入接口配置:
将 PF0 接口配置为输入接口,并且读出接口电平状态。
*pFIO_DIR &= ~PF0; //设置 PF0 为输入
*pFIO_INEN |= PF0; //输入使能
i = *pFIO_FLAG_D; //读取数据
输出接口配置:
将 PF0 接口配置为输出接口,使用两种方式设置 PF0 输出高低电平。
*pFIO_DIR |= PF0; //设置 PF0 为输出
*pFIO_FLAG_S |= PF0; //PF0 脚置高
*pFIO_FLAG_C |= PF0; //PF0 脚置低
*pFIO_FLAG_D |= PF0; //PF0 脚置高
*pFIO_FLAG_D &= ~PF0; //PF0 脚置低
代码实现功能
工程 BF53x_GPIO_IN.dpj 实现了读取 PF0 接口状态并打印出 PF 接口状态数据。
工程 BF53x_GPIO_OUT.dpj 实现了通过 PF0 接口不断的输出高低变化的电平。
完整源码展示
这里有两个工程,一个工程是IN,一个工程是OUT:
IN:
#include <cdefBF533.h>
#define pDEVICE_OE (volatile unsigned short *)0x20320000
#define PF0_SET 0x40
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_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}
void Init_PF0_IN(void)
{
*pFIO_DIR &= ~PF0;
*pFIO_INEN |= PF0;
}
void Set_CPLD(void)
{
*pDEVICE_OE &= ~PF0_SET ; //设置CPLD释放PF0接口
}
void main(void)
{
int i;
Set_PLL(16,4);
Init_EBIU();
Init_SDRAM();
Set_CPLD();
Init_PF0_IN();
while(1)
{
i = *pFIO_FLAG_D;
printf("PF data is %d\n",i);
}
}
OUT:
#include <cdefBF533.h>
#define pDEVICE_OE (volatile unsigned short *)0x20320000
#define PF0_SET 0x40
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_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}
void Init_PF0_OUT(void)
{
*pFIO_DIR |= PF0;
}
void Set_CPLD(void)
{
*pDEVICE_OE &= ~PF0_SET ; //设置CPLD释放PF0接口
}
void main(void)
{
int i;
Set_PLL(16,4);
Init_EBIU();
Init_SDRAM();
Set_CPLD();
Init_PF0_OUT();
while(1)
{
*pFIO_FLAG_S |= PF0; //PF0脚置高
*pFIO_FLAG_C |= PF0; //PF0脚置低
*pFIO_FLAG_D |= PF0; //PF0脚置高
*pFIO_FLAG_D &= ~PF0; //PF0脚置低
}
}
关于ADI的DSP GPIO的原理以及源代码有任何问题均可以随时问我,本人很懂。