DSP之一:GPIO概述(F28335)

初学DSP(F28335芯片),玩了玩GPIO点了个灯,赶紧对GPIO相关知识进行一个梳理记录。(因为初学,肯定有很多地方理解的有偏差,如若各位大哥大姐们发现错误之处,还请不吝赐教,感谢感谢!)

一、GPIO知识点

1、F28335芯片GPIO一共有88个GPIO口:GPIO0 - GPIO87。

2、分为ABC三组:

组名GPIO范围写法
A组GPIO0 - GPIO31GPA
B组GPIO32 - GPIO63GPB
C组GPIO64 - GPIO87GPC

3、寄存器:(x为组名,可取值A、B、C

寄存器名功能含义
GPxMUXn复用功能寄存器决定GPIO口是否复用。每2bit表示一个GPIO,故可取值00/01/10/11,即:0/1/2/3。
0:关闭复用功能,当做普通IO口使用
1/2/3:打开复用功能,对应具体复用功能,请查看数据手册

注意:n可以取值1 or 2
原因:mux为32位寄存器,每2bit表示一个GPIO,故一个mux寄存器只能表示16个GPIO口。而每组GPIO有32个GPIO,故要全部表示需要2个MUX寄存器,即:MUX1和MUX2
MUX1:每组GPIO的前半部分,如:GPIO0 ~GPIO15
MUX2:每组GPIO的后半部分,如:GPIO16~GPIO31
GPxDIRIO方向寄存器配置IO方向:
0:输入
1:输出
GPxDAT独立读写IO口寄存器当IO方向为输入时为只读寄存器;
当IO方向为输出时,可以通过GPxSET设置该寄存器值
GPxSET置1寄存器写1有效,写0无效
GPxCLEAR清0寄存器写1有效,写0无效
GPxTOOGLE翻转寄存器写1有效,写0无效
GPAPUD是否上拉寄存器0:上拉
1:不上拉

二、代码

要点亮led灯,需要关注以下几个方面:

  • 1、电路图找到led所在GPIO,看是否需要上拉
  • 2、所对应GPIO口需要关闭复用功能,作为普通IO口使用
  • 3、配置GPIO口为输出口
  • 4、将该GPIO配置为低电平或高电平

代码如下(详细代码结构体解析见下章)

/* 设置GPIO口为输出口,并输出低电平 */
GpioCtrlRegs.GPCPUD.bit.GPIO64 = 0;    /* 上拉 */
GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0;   /* GPIO64属于C组前半部分GPIO,故为GPCMUX1 */
GpioCtrlRegs.GPCDIR.bit.GPIO64 = 1;    /* 1:表示方向为输出 */
GpioDataRegs.GPCCLEAR.bit.GPIO64 = 1;  /* 清零该bit */

三、代码结构体解析

关于上述代码赋值解析,也可以从手册中查看寄存器详细描述,也可以从代码中窥探一二。

如下,以上述代码第二行赋值语句【GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0;】为例进行解析,为什么GPIO64赋值就要这么表示?

将该结构体变量层层剥开:

变量名为:GpioCtrlRegs

第一级成员为:GPCMUX1

第二级成员为:bit

最后一级成员为:GPIO64

1、结构体变量:GpioCtrlRegs

示例语句:GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0;

在代码中可以找到变量GpioCtrlRegs的定义与结构体类型定义如下:

volatile struct GPIO_CTRL_REGS GpioCtrlRegs;
struct GPIO_CTRL_REGS {
   union  GPACTRL_REG  GPACTRL;   // GPIO A Control Register (GPIO0 to 31)
   union  GPA1_REG     GPAQSEL1;  // GPIO A Qualifier Select 1 Register (GPIO0 to 15)
   union  GPA2_REG     GPAQSEL2;  // GPIO A Qualifier Select 2 Register (GPIO16 to 31)
   union  GPA1_REG     GPAMUX1;   // GPIO A Mux 1 Register (GPIO0 to 15)
   union  GPA2_REG     GPAMUX2;   // GPIO A Mux 2 Register (GPIO16 to 31)
   union  GPADAT_REG   GPADIR;    // GPIO A Direction Register (GPIO0 to 31)
   union  GPADAT_REG   GPAPUD;    // GPIO A Pull Up Disable Register (GPIO0 to 31)
   Uint32              rsvd1;
   union  GPBCTRL_REG  GPBCTRL;   // GPIO B Control Register (GPIO32 to 63)
   union  GPB1_REG     GPBQSEL1;  // GPIO B Qualifier Select 1 Register (GPIO32 to 47)
   union  GPB2_REG     GPBQSEL2;  // GPIO B Qualifier Select 2 Register (GPIO48 to 63)
   union  GPB1_REG     GPBMUX1;   // GPIO B Mux 1 Register (GPIO32 to 47)
   union  GPB2_REG     GPBMUX2;   // GPIO B Mux 2 Register (GPIO48 to 63)
   union  GPBDAT_REG   GPBDIR;    // GPIO B Direction Register (GPIO32 to 63)
   union  GPBDAT_REG   GPBPUD;    // GPIO B Pull Up Disable Register (GPIO32 to 63)
   Uint16              rsvd2[8];
   union  GPC1_REG     GPCMUX1;   // GPIO C Mux 1 Register (GPIO64 to 79)
   union  GPC2_REG     GPCMUX2;   // GPIO C Mux 2 Register (GPIO80 to 95)
   union  GPCDAT_REG   GPCDIR;    // GPIO C Direction Register (GPIO64 to 95)
   union  GPCDAT_REG   GPCPUD;    // GPIO C Pull Up Disable Register (GPIO64 to 95)
};

可以看到定义中将所有的寄存器都封装到该结构体中,并且将所有的寄存器封装成ABC三组:

​ 前三分之一为A组,中间的为B组,后面的为C组,寄存器名字风格大都一致。

深追下一级成员:GPCMUX1

2、第一级成员:GPCMUX1

示例语句:GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0;

上面结构体中倒数第四行可以看到该成员定义:union GPC1_REG GPCMUX1; ,是一个union类型GPC1_REG,追进去可以看到定义如下:

union GPC1_REG {
   Uint32              all;
   struct GPC1_BITS    bit;
};

可以看到有两个成员,一个all,一个bit,bit也是一个结构体GPC1_BITS,为第二级成员

疑问:为什么要用union呢?留个疑问下一小节回答。

3、第二级成员:bit

示例语句:GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0;

第二级成员bit定义如下:struct GPC1_BITS bit;是一个结构体类型,追进去如下:

struct GPC1_BITS {            // bits   description
   Uint16 GPIO64:2;           // 1:0    GPIO64   
   Uint16 GPIO65:2;           // 3:2    GPIO65
   Uint16 GPIO66:2;           // 5:4    GPIO66
   Uint16 GPIO67:2;           // 7:6    GPIO67   
   Uint16 GPIO68:2;           // 9:8    GPIO68
   Uint16 GPIO69:2;           // 11:10  GPIO69
   Uint16 GPIO70:2;           // 13:12  GPIO70   
   Uint16 GPIO71:2;           // 15:14  GPIO71 
   Uint16 GPIO72:2;           // 17:16  GPIO72 
   Uint16 GPIO73:2;           // 19:18  GPIO73   
   Uint16 GPIO74:2;           // 21:20  GPIO74 
   Uint16 GPIO75:2;           // 23:22  GPIO75       
   Uint16 GPIO76:2;           // 25:24  GPIO76 
   Uint16 GPIO77:2;           // 27:26  GPIO77 
   Uint16 GPIO78:2;           // 29:28  GPIO78 
   Uint16 GPIO79:2;           // 31:30  GPIO79 
};

可以看到,该结构体表示了GPIO64~GPIO79,且内部用了C语言中【位域】的语法,每2bit表示一个GPIO,所以一个32bit寄存器可以表示16个GPIO口。

所以不难发现,上一级成员中,有两个子成员(【32位的all】和【结构体GPC1_BITS】)。

(1)当代码使用第一个成员all的时候,表示所有的bit即:结构体中所有的GPIO口(GPIO64~GPIO79),

(2)当使用子成员bit的时候,可以继续具体到内部成员,具体到每一个GPIO口。

4、最后一级成员:GPIO64

示例语句:GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0;

所以整个语句需要表示GPIO64,则可以计算出来64是属于C组GPIO的前半部分,

(1)C组,则应该是GPC

(2)前半部分GPIO,则应该是MUX1

故合起来是GPCMUX1。其他各个成员则都一样。

同理,要表示GPIO82,则完整表达是应该是:GpioCtrlRegs.GPCMUX2.bit.GPIO82

5、GPCMUX1与GPCMUX2区别

所以一级一级追下来,可以发现GPIO64,就属于C组的GPIO,因为2bit表示一个GPIO,所以一个32bit的寄存器只能表示16个GPIO,所以只能表示到GPIO64~GPIO79,

那么猜想后16个GPIO应该也有一个寄存器表示,回到最开始的结构体变量定义中,可以找到相邻的两个语句:

struct GPIO_CTRL_REGS {
   ...
   union  GPC1_REG     GPCMUX1;   // GPIO C Mux 1 Register (GPIO64 to 79)
   union  GPC2_REG     GPCMUX2;   // GPIO C Mux 2 Register (GPIO80 to 95)
   ...
};

其实GPCMUX1与GPCMUX2,是一模一样的定义,只是GPCMUX2恰好表示后面16个GPIO口,应该是GPIO80~GPIO95,可以看到官方代码中注释也是(GPIO80 to 95),但是,由于F28335芯片总共只有88个GPIO,所以GPIO最大应该是GPIO87。

追到代码中可以验证,代码如下:

struct GPC2_BITS {            // bits   description
   Uint16 GPIO80:2;           // 1:0    GPIO80   
   Uint16 GPIO81:2;           // 3:2    GPIO81 
   Uint16 GPIO82:2;           // 5:4    GPIO82 
   Uint16 GPIO83:2;           // 7:6    GPIO83   
   Uint16 GPIO84:2;           // 9:8    GPIO84
   Uint16 GPIO85:2;           // 11:10  GPIO85 
   Uint16 GPIO86:2;           // 13:12  GPIO86    
   Uint16 GPIO87:2;           // 15:14  GPIO87
   Uint16 rsvd:16;            // 31:16  reserved
};
  • 50
    点赞
  • 192
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
DSP(数字信号处理器)是一种专用的微处理器,用于处理数字信号。GPIO(通用输入/输出)则是一种用于与外部设备通信的接口。DSP GPIO教程就是介绍如何使用DSP芯片上的GPIO口,进行输入输出操作的指南。 在DSP GPIO教程中,首先会介绍DSP芯片上的GPIO端口的基本特性和功能。这些GPIO端口可以用于将外部设备连接到DSP芯片上,实现与外界的通信。通常,GPIO端口可以配置为输入模式或输出模式,通过配置寄存器来设置GPIO的工作模式。 接下来,教程会解释如何配置DSP芯片上的GPIO端口。配置GPIO端口需要设置寄存器的各个位,包括设置GPIO口的方向、电平状态、中断使能等。配置完毕后,GPIO口就可以用于读取外部设备的状态或向外部设备发送信号。 然后,教程会介绍如何通过编程来控制DSP芯片上的GPIO端口。这包括如何读取外部设备的输入信号,和如何向外部设备发送输出信号。编程可以使用特定的DSP开发环境或编程语言,根据GPIO的寄存器编程接口进行操作。 最后,教程会提供一些GPIO的示例应用,以帮助读者更好地理解如何使用DSP GPIO。这些示例包括控制LED灯、读取按钮状态、与传感器进行通信等。 通过学习DSP GPIO教程,读者可以了解到如何使用DSP芯片上的GPIO口与外部设备进行通信。这对于设计和开发使用DSP的项目非常重要,例如嵌入式系统、音频处理和图像处理等领域。同时,理解DSP GPIO教程也有助于提高对数字信号处理的理解和应用能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值