DSP

基于BF531 DSP的可编程标志口

2019-07-13 18:09发布

原文地址::http://www.analogcn.com/Article/wz3/201101/20110110084503.html   一、   可编程标志口简介     可编程标志口即所谓的通用目的I/O口,这是CPU的最基本的外设,嵌入式系统中,任何一个CPU都会有通用目的I/O口,他们的属性都基本上相似,只是叫法不一样而已。   ADSP-BF531/2/3处理器有16个双向的通用目的可编程I/O引脚(PF[15:0])。每个引脚可以通过 方向寄存器(FIO_DIR)独立配置为输入或者输出。 当配置成输出时,可以通过直接写入 数据寄存器(FIO_FLAG_D)来改变输出引脚的状态; 也可以通过置位寄存器(FIO_FLAG_S)、 清零寄存器(FIO_FLAG_C) 翻转寄存器(FIO_FLAG_T)来控制PFx 引脚的状态。 当配置成输入时,以上寄存器都可以返回PFx口的状态。   值得注意的是,部分可编程标志口与其他外设复用,使用复用功能时,我们需要设置相应的外设寄存器。复用功能如表6-1。   表6-1 可编程标志口复用功能 PF 引脚 PPI复用功能 SPI 复用功能 定时器复用 0 - SPISS 低电平有效   1   SPISEL1 输入时钟 2   SPISEL2   3 Frame Sync 3 SPISEL3   4 IO #15 SPISEL4   5 IO #14 SPISEL5   6 IO #13 SPISEL6   7 IO #12 SPISEL7   8 IO #11     9 IO #10     10 IO #9     11 IO #8     12 IO #7     13 IO #6     14 IO #5     15 IO #4         从上面我们可以看出,本来I/O口不多,偏偏又共享出去了那么多,如果我们使用PPI、SPI等外设,对用户来说,剩下的可用IO口更少了。不错,事实就是这样,作为一款 DSP芯片,较少的IO口也是可以理解的。一般情况下,如果我们的系统中控制部分如果太复杂、使用I/O口较多的情况下,则需要I/O扩展(通过74系列逻辑芯片、CPLD以及专用的I/O扩展芯片)。   二、   I / O相关寄存器 1、方向寄存器(FIO_DIR)   顾名思义,此寄存器可以设置PFx引脚的输入、输出方向。此寄存器是一个可读、写寄存器,每一位对应着一个PFx引脚。逻辑1将PFx引脚配置为输出方式,逻辑0将PFx引脚配置为输入方式。复位时,其值为0X0000,此时所有的PFx引脚均被配置为输入方式。 注意:如果PFx引脚被配置为输入方式时,一定要设置FIO_INEN中相应的位。   表6-2 FIO_DIR(地址:0XFFC0 0730 复位值0x0000) 名称 描述 15:0 FIO_DIR 可编程标志口方向寄存器,16位分别可以设置FP0~PF15的方向,为0时,为输入;为1时,为输出。   2、数值操作寄存器    处理器包含了四个数值操作相关的寄存器,他们分别为 数据寄存器(FIO_FLAG_D)、 置位寄存器(FIO_FLAG_S)、 清零寄存器(FIO_FLAG_C)和 翻转寄存器(FIO_FLAG_T)。四个寄存器通过不同的模式来操作PFx口与外界数据的交换,他们可以用来:
  • 当设置为输入时,读取PFx口上的值;
  • 当设置为输出时,设置PFx口上的值;
  • 清除相应端口产生的中断。
  我们不但可以读取PFx的状态,也可以通过设置 极性寄存器(FIO_POLAR)、 边沿寄存器(FIO_EDGE)和 双边沿寄存器(FIO_BOTH)来读取相应IO口上的电平状态、上升沿、下降沿的探测。这个功能其他处理器很少有。   表6-3 数值寄存器注释 FIO_POLAR FIO_EDGE FIO_BOTH 说明 0 0 X 引脚为高电平时,读出为1;引脚为低电平时,读出为0 0 1 0 如果上升沿发生,读出为1;否则读出为0 1 0 X 引脚为低电平时,读出为1,;引脚为高电平时,读出为0 1 1 0 如果下降沿发生,读出为1,否则读出为0 X 1 1 如果上升沿或者下降沿发生,读出为1,否则读出为0 (1)数据寄存器(FIO_FLAG_D)   当PFx引脚设置为输入方式时,FIO_FLAG_D中的每一位对应着每个PFx的输入电平或者边沿值见表6-3。当PFx引脚为输出方式时,通过向FIO_FLAG_D中写数据,从而指定每个PFx引脚的输出状态,逻辑1代表输出高电平,逻辑0代表输出低电平。相应的位写入 0 时,引脚输出低电平,写入 1 时,引脚输出高电平。 表6-4 FIO_FLAG_D(地址:0XFFC0 0700 复位值0x0000) 名称 描述 15:0 FIO_FLAG_D 当PFx引脚为输出方式时,FIO_FLAG_D中的每一位返回对应的PFx的值。 (2)置位寄存器(FIO_FLAG_S)   置位寄存器,写入1时相应的端口置位,写入 0 时端口值保持不变。这样我们就很方便的对某一位端口置位而不影响其他端口的状态。 表6-5 FIO_FLAG_S(地址:0XFFC0 0708 复位值0x0000) 名称 描述 15:0 FIO_FLAG_S 可编程标志口置位寄存器,16位分别对应FP0~PF15的置位操作,为0时,维持原值不变;为1时,设置输出为1。 (3)清零寄存器(FIO_FLAG_C)   清零寄存器,写入1时相应的端口清零,写入0是端口保持不变。这样我们就很方便的对某一位端口值单独清零而不影响其他端口的状态。 表6-6 FIO_FLAG_C(地址:0XFFC0 0704 复位值0x0000) 名称 描述 15:0 FIO_FLAG_S 可编程标志口置位寄存器,16位分别对应FP0~PF15的置位操作,为0时,维持原值不变;为1时,设置输出为1。   (4)翻转寄存器(FIO_FLAG_T)   翻转寄存器,写入1时相应的端口值翻转(原来为高则置低,原来为低则置高),写入0是端口保持不变。 表6-7 FIO_FLAG_T(地址:0XFFC0 0704 复位值0x0000) 名称 描述 15:0 FIO_FLAG_T 可编程标志口翻转寄存器,16位分别对应FP0~PF15的翻转操作,为0时,维持原值不变;为1时,对相应的端口进行翻转操作。 (5)其他寄存器   除了数据操作寄存器外,还包含了极性控制寄存器(FIO_POLAR)、边沿寄存器(FIO_EDGE)以及双边沿寄存器(FIO_BOTH)。他们用于设定读操作时,数据置1的条件。 表6-8 FIO_POLAR(地址:0XFFC0 0734 复位值0x0000) 名称 描述 15:0 FIO_POLAR 可编程标志口极性寄存器,16位分别对应FP0~PF15的极性,为0时,代表高电平或者上升沿有效;为1时,代表低电平或者下降沿有效,请参考表6-3。   表6-9 FIO_EDGE(地址:0XFFC0 0738 复位值0x0000) 名称 描述 15:0 FIO_EDGE 可编程标志口边沿寄存器,16位分别对应FP0~PF15的边沿设定,为0时,代表高电平触发;为1时,代表边沿触发,请参考表6-3。   表6-10 FIO_BOTH(地址:0XFFC0 073C 复位值0x0000) 名称 描述 15:0 FIO_BOTH 双边沿寄存器,16位分别对应FP0~PF15的双边沿设定,为0时,代表单边沿触发;为1时,代表双边沿触发(上升沿和下降沿均触发),请参考表6-3。   三、       中断     可编程标志口的每个端口都可以产生中断,他们有两个中断向量,分别为可编程标志口中断A 和可编程标志口中断B。PF0~PF15可以任意向这两个中断向量中设置。值得注意的是,每个中断向量如果多于一个触发源(例如我们把PF0和PF1都设置指向中断向量A),则他们最终是以“或”的关系触发中断   如果设置成电平中断(FIO_EDGE对应位设置成0),则只要引脚满足中断的电平条件(低电平或者高电平,取决于寄存器FIO_POLAR),就会触发中断,条件消失后,中断才不会触发;如果设置成边沿中断(FIO_EDGE对应位设置成1),边沿触发后立即触发中断,进入中断后,需要手动清除寄存器数值(可以通过写寄存器 FIO_FLAG_C的相应位清除)。   每个中断向量包含四个寄存器,他们分别为 中断掩码数据寄存器、 中断掩码设置寄存器、 中断掩码清除寄存器 中断掩码翻转寄存器。   四个寄存器设置可以达到同样的效果,如果对应位设定时,则使能中断,对应位清除时,则禁止中断。上电复位后,默认禁止所有中断。   表6-11 FIO_MASKA_D(地址:0XFFC0 0710 复位值0x0000) 名称 描述 15:0 FIO_MASKA_D 可编程标志口中断向量A数据寄存器,0~15位分别对应PF0~PF15端口,对应位写入1使能中断,写入0时禁止中断。     表6-12 FIO_MASKA_S(地址:0XFFC0 0718 复位值0x0000) 名称 描述 15:0 FIO_MASKA_S 可编程标志口中断向量A置位寄存器,0~15位分别对应PF0~PF15端口,对应位写入1使能中断,写入0时保持原数据不变。     表6-13 FIO_MASKA_C(地址:0XFFC0 0714 复位值0x0000) 名称 描述 15:0 FIO_MASKA_C 可编程标志口中断向量A清除寄存器,0~15位分别对应PF0~PF15端口,对应位写入1禁止中断,写入0时保持原数据不变。   表6-14 FIO_MASKA_T(地址:0XFFC0 071C 复位值0x0000) 名称 描述 15:0 FIO_MASKA_T 可编程标志口中断向量A翻转寄存器,0~15位分别对应PF0~PF15端口,对应位写入1数据翻转(原来使能则禁止、原来禁止则使能),写入0时保持原数据不变。   表6-15 FIO_MASKB_D(地址:0XFFC0 0720 复位值0x0000) 名称 描述 15:0 FIO_MASKB_D 可编程标志口中断向量B数据寄存器,0~15位分别对应PF0~PF15端口,对应位写入1使能中断,写入0时禁止中断。   表6-16 FIO_MASKB_S(地址:0XFFC0 0728 复位值0x0000) 名称 描述 15:0 FIO_MASKB_S 可编程标志口中断向量B置位寄存器,0~15位分别对应PF0~PF15端口,对应位写入1使能中断,写入0时保持原数据不变。   表6-17 FIO_MASKB_C(地址:0XFFC0 0724 复位值0x0000) 名称 描述 15:0 FIO_MASKB_C 可编程标志口中断向量B清除寄存器,0~15位分别对应PF0~PF15端口,对应位写入1禁止中断,写入0时保持原数据不变。   表6-18 FIO_MASKB_T(地址:0XFFC0 072C 复位值0x0000) 名称 描述 15:0 FIO_MASKB_T 可编程标志口中断向量B翻转寄存器,0~15位分别对应PF0~PF15端口,对应位写入1数据翻转(原来使能则禁止、原来禁止则使能),写入0时保持原数据不变。   -----------------------------------小马哥派来的分割线------------------------------------   附录 一、可编程标志口相关例程,包括:   1、流水灯;   2、按键测试;   3、按键边沿检测测试;   4、可编程标志口中断测试。 ADSP-BF533 GPIO初试 http://www.analogcn.com/Article/wz3/201112/20111207164842.html   ADSP-BF531处理器上有16 个Programmable Flag 接口,简称PF接口,这些接口就是通常所有的IO接口,跟51单片机的IO口类似,通过寄存器配置,可以输出电平和感知接口电平,比较特殊的是,它的每一个PF 接口都可以作为外部中断接口。 在51单片机上,通常如果设置一个IO接口输出时,直接将输出信号值付给该接口,如果作为输入时,直接通过该接口读取即可。Blackfin 处理器的IO使用与单片机略有不同,在使用前必须对该接口进行初始化,如告知接口的方向,假如配置为输出接口,则直接配置输出接口电平信号,假如配置为输入接口,需打开输入使能开关,配置输入信号触发方式,是否中断触发,是否双极性触发等等。初始化完成后,才能使用PF 接口。其实大家如果有用过AVR单片机的,就会比较容易理解一点,AVR单片机的IO口初始化也是要设置方向等属性的,但是就没有ADSP这么复杂。 感觉还是用通过实例来学习比较快,下面是通过ADSP的GPIO口来控制IO电平输出的一个实例: void init_PF0_OUT(void) {    *pFIO_DIR |= PF0;    } void main(void) {     int i;     Set_PLL(16,3);          init_PF0_OUT();     while(1){         *pFIO_FLAG_S |= PF0;         *pFIO_FLAG_C |= PF0;            *pFIO_FLAG_D |= PF0;           *pFIO_FLAG_D &= ~PF0;     }} 假如上面的程序是单片机的IO口控制程序,看到这么多寄存器的设置,我们首先一般是先查找寄存器的作用以及各个位对应的功能,只有熟悉了,才能进行应用。如下图就是从网上找到的资料:PF接口主要寄存器作用: 我又找了ADSP-BF533的DATASHEET,但是却发现在PDF文档中找不到上面所说的寄存器的具体定义,觉得很奇怪,像以前单片机的寄存器都是在DATASHEET里面就有非常详细的说明的,找不到寄存器的具体定义,很难继续学习下去,于是我就在网上搜索资料,还有跟一些之前学习过ADSP的人交流一下,最后终于被我发现寄存器的踪迹,原来它就藏身于我们的软件编译器---VisualDSP++的Help里面,如下图: 在HELP里面,我们可以找到ADSP-BF533 Hardware Reference这一项,点开这一项,可以在里面找到下面的界面:

 

呵呵,在Programmable Flag Registers (MMRs) 里面就可以看到所有关于IO口的寄存器的具体定义啦,就以FIO_DIR Register 为例,如下图就是该寄存器的具体定义:

 

 GPIO 部分 二 ::   http://www.analogcn.com/Article/wz3/201112/20111207164927.html 通过上面的说明,我们可以知道FIO_DIR是一个16位的读写寄存器,每一个位控制一个PFx的IO口。当PFx被设置为1时,对应的端口被设置为输出;当PFx被设置为0时,对应的端口被设置成输入端口。而且该寄存器的复位值为0x0000,标志所有的IO口在复位时都会被设置成输入属性。
我们可以继续查找其他寄存器的内容,对照寄存器的各个位的说明,我们可以对一开始的程序进行以下的解释:
 
  void init_PF0_OUT(void) {     *pFIO_DIR |= PF0; //设置PF0口的端口方向为输出:设置为1表示输出,为0表示输入 } void main(void) {     int i;     Set_PLL(16,3);   //设置系统运行速度,25MHZ*16/3=133MHZ         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脚置低      }}

 

呵呵,现在看起来是不是好解析很多呢,我们再把程序下载到芯片中去,通过示波器就能看到PF0口在不断地电平高低变化。   今天跟着前面的思路学习ADSP GPIO的输入功能的,打开开发板附带光盘中的bf53x_gpio_in项目,连接了之前建立的Session,然后看一下程序,如下语句: void init_PF0_IN(void) {        *pFIO_DIR &= ~PF0;   //设置PF0口的方向属性为输入        *pFIO_INEN |= PF0;    //开启PF0口的输入使能 } void main(void) {        int i;        Set_PLL(16,3);           //设置系统运行速度        init_PF0_IN();         //初始化端口        while(1)        {            i = *pFIO_FLAG_D;  //在while循环中不断地读取PF端口的值            printf("PF data is %d ",i);   //把i值通过仿真器读回来显示在编译器上 }} 跟输出功能的学习类似,也就是查找相应寄存器的内容和功能,记得加上*pFIO_INEN |= PF0语句,如果没有开启输入使能,器件是读不到端口电平的,程序看完,按下编译图标, 不知道为什么,却出现了如下图中的错误提示: 错误提示中写着:The file “E:ADSPADSP-EDU-BF53x资料光盘ADSP-EDU-BF53x_CODEInterfaceCodef53x_gpio_inBF53x_GPIO_IN.mak”could not be created. 意思是说,我打开的这个项目的Makefile文件不能被建立,真的很奇怪,几天前我刚刚打开GPIO_OUT的项目,编译跟下载都没问题啊,于是我又重新打开了之前打开的GPIO_OUT的项目,但是还是出现了同样的问题,编译不通过。怎么那么奇怪,明明是同样的程序,怎么过几天就不行了呢。我把错误的说明拷到百度上搜索了一下,不过ADSP的中文资料有点少,搜不到。于是我细想了之前学习的过程,突然让我想起这两个项目的存放路径不同,一个是之前让我拷到电脑硬盘中,一个在光盘中直接打开,难道跟这个有关,好像之前也曾遇到过类似的情景,对,难道VisualDSP++跟Quartus II软件一样,项目不能存放在中文目录下,于是我赶紧打开了存放在电脑中的英文目录下的项目进行编译,呵呵,“Load complete.”原来VisualDSP++也是不支持中文目录的,浪费了我不少时间,不过算,就当是积累经验,谁叫我刚入门呢,呵呵。解决完编译错误的问题,我又对上面的程序进行仿真,点击全速运行,得到了下面的结果: 从程序中我们可以看到,从仿真器中读回来的数值应该就是PF整个端口16位的数据,于是我把程序中的PF0都改成了PF2,然后再编译仿真,呵呵,结果果真如此,从仿真器中读回来的数据如下图:   那么应该没错,PF=0b0000_0000_0000_0100,也就是4 。对于GPIO口学习到此为止,呵,写得不好,仅供参考。