DSPTMS320F28335系列1、GPIO和点亮LED
一、C语言基础
结构体
struct_ strframe str.fra_datal; //定义了一个结构体变量,变量名为str_fra_datal
结构体是一种复合数据类型,它定义的变量中有三种不同性质的元素,它和其他的基本数据类型功能是一样的。对这种类型的变量的赋值方法,如str_fra_data1.sh_fra1=Ox04;还可以定义指针或是数组,如struct str.frame*str_fra_data2;,这时的赋值方法为:str_fra_datal -> sh_fra1=Ox04;。所有的C语句都以“﹔”结尾。
声明描述了一个short、一个long和一个float变量组成的结构体。但是注意,它并没有创建一个实际的数据对象,而是描述了一个组成这类对象的元素。因此,我们有时候也将结构体声明叫做模板,因为它勾勒出数据该如何存储,并没有实例化数据对象。
1、首先使用关键字struct,它表示接下来是一个结构体。
2、后面是一个可选的标志(str_fra1),它是用来引用该结构体的快速标记。因此我们以后就可以这样创建数据对象。
struct str_fra1 str_fra_data1;//把str_fra_data1设为一个可以使用str_fra1结构体的结构体变量,则str_fra_data1这个变量就包含了其str_fra1结构体中的所有元素。
2、接下来就是一个花括号,括起了结构体成员列表,及每个成员变量,使用的都是其自己的声明方式来描述,用分号来结束描述;
3、例如:char title[MAXTITL];字符数组就是这样声明的,用分号结束;
注意:其中每个成员可以使用任何一种C数据结构甚至是其他的结构体,也是可以的;
在结束花括号后的分号表示结构体设计定义的结束。
4、关于其struct声明的位置,也就是这段代码要放到哪里。同样这也是具有作用域的。
5、这种声明如果放在任何函数的外面,那么则可选标记可以在本文件中,该声明的后面的所有函数都可以使用。如果这种声明在某个函数的内部,则它的标记只能在内部使用,并且在其声明之后;
6、一般格式就是:
struct 结构体名(也就是可选标记名){ 成员变量;};//使用分号表示定义结束。
定义结构体变量
之前我们结构体类型的定义(结构体的声明)只是告诉编译器该如何表示数据,但是它没有让计算机为其分配空间。我们要使用结构体,那么就需要创建变量,也就是结构体变量; 创建一个结构体变量;
struct book library;
看到这条指令,编译器才会创建一个结构体变量library,此时编译器才会按照book模板为该变量分配内存空间,并且这里存储空间都是以这个变量结合在一起的。这也是后面访问结构体变量成员的时候,我们就要用到结构体变量名来访问。
struct book的作用:
在结构体声明中,struct book所起到的作用就像int,,,,等基础数据类型名作用一样。
struct book s1,s2,*ss;
定义两个struct book结构体类型的结构体变量,还定义了一个指向该结构体的指针,其ss指针可以指向s1,s2,或者任何其他的book结构体变量。struct book library;等效于;struct book{ char … …. …… }librar;这两种是等效的,只是第一种可以减少代码的。
二、GPIO的知识
CPU 要处理外界二进制信息(数字量),要将其存放在存储器中,就需要外界信息源与CPU或存储器进行交换,这样的交换接口若用来进行通用目的数字量的输入输出,就被称为通用数字量输入/输出接口,简称GPIO。F28335有88个 GPIO,F28335将这88个 GPIO口分成了A、B、C这3大组,A组包括 GPIO0~GPIO31,B组包括GPIO32~GPIO63,C组包括GPIO64~GPIO87,每个引脚都复用了多个功能,同一时刻,每个引脚只能用该引脚的一个功能。
88个GPIO分为3组:
组名 | GPIO范围 | 写法 |
---|---|---|
A组 | GPIO0 - GPIO31 | GPA |
B组 | GPIO32 - GPIO63 | GPB |
C组 | GPIO64- GPIO88 | GPC |
2、寄存器及其配置。
控制寄存器名 | 功能 | 含义 |
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和MUX2MUX1:每组GPIO的前半部分,如:GPIO0 ~GPIO15MUX2:每组GPIO的后半部分,如:GPIO16 |
GPxDIR | IO方向寄存器 | 配置IO方向 0:输入 1:输出 |
GPAPUD | 是否上拉寄存器 | 0:上拉 1:不上拉 |
数据寄存器名 | 功能 | 含义 |
GPxDAT | 独立读写IO口寄存器 | 当IO方向为输入时为只读寄存器; 当IO方向为输出时,可以通过GPxSET设置该寄存器值 |
GPxSET | 置1寄存器 | 写1有效,写0无效 |
GPxCLEAR | 清0寄存器 | 写1有效,写0无效 |
GPxTOOGLE | 翻转寄存器 | 写1有效,写0无效 |
三、结构体代码
为了实现需要了解GPIO的设置。
3.1、结构体变量:GpioCtrlRegs
#ifdef __cplusplus
#pragma DATA_SECTION("GpioCtrlRegsFile")
#else
#pragma DATA_SECTION(GpioCtrlRegs,"GpioCtrlRegsFile");
#endif
volatile struct GPIO_CTRL_REGS GpioCtrlRegs;
这段代码定义了一个名为GpioCtrlRegs的全局变量,它是一个指向GPIO_CTRL_REGS结构体的volatile指针。使用volatile关键字的作用是告诉编译器在访问该变量时不要进行优化,因为该变量可能会在程序运行期间被其他代码修改。需要注意的是,在这段代码之前可能存在#idef和#pragma DATA_SECTION等预处理指令,它们的作用是控制变量存储的位置和方式。该代码的具体实现可能会因编译器和平台而异。
3.2、第一级成员:GPCMUX1
1 volatile struct GPIO_CTRL_REGS GpioCtrlRegs;
2 struct GPIO_CTRL_REGS {
3 union GPACTRL_REG GPACTRL; // GPIO A Control Register (GPIO0 to 31)
4 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)
6 union GPA1_REG GPAMUX1; // GPIO A Mux 1 Register (GPIO0 to 15)
7 union GPA2_REG GPAMUX2; // GPIO A Mux 2 Register (GPIO16 to 31)
8 union GPADAT_REG GPADIR; // GPIO A Direction Register (GPIO0 to 31)
9 union GPADAT_REG GPAPUD; // GPIO A Pull Up Disable Register (GPIO0 to 31)
10 Uint32 rsvd1;
11 union GPBCTRL_REG GPBCTRL; // GPIO B Control Register (GPIO32 to 63)
12 union GPB1_REG GPBQSEL1; // GPIO B Qualifier Select 1 Register (GPIO32 to 47)
13 union GPB2_REG GPBQSEL2; // GPIO B Qualifier Select 2 Register (GPIO48 to 63)
14 union GPB1_REG GPBMUX1; // GPIO B Mux 1 Register (GPIO32 to 47)
1 union GPB2_REG GPBMUX2; // GPIO B Mux 2 Register (GPIO48 to 63)
16 union GPBDAT_REG GPBDIR; // GPIO B Direction Register (GPIO32 to 63)
17 union GPBDAT_REG GPBPUD; // GPIO B Pull Up Disable Register (GPIO32 to 63)
18 Uint16 rsvd2[8];
19 union GPC1_REG GPCMUX1; // GPIO C Mux 1 Register (GPIO64 to 79)
20 union GPC2_REG GPCMUX2; // GPIO C Mux 2 Register (GPIO80 to 95)
21 union GPCDAT_REG GPCDIR; // GPIO C Direction Register (GPIO64 to 95)
22 union GPCDAT_REG GPCPUD; // GPIO C Pull Up Disable Register (GPIO64 to 95)
};
23 union GPACTRL_REG
{
24 Uint32 all;
26 struct GPACTRL_BITS bit;
};
第一行是对第一行GpioCtrlRegs的解释,定义了GpioCtrlRegs是一个GPIO_CTRL_REGS结构体类型的变量.
第2到26行是解释了GPIO_CTRL_REGS 结构体类型的变量具有哪些成分,即,GpioCtrlRegs内有哪些成员,比如,选出其中一个成员(第3行) union GPACTRL_REG GPACTRL; ,这个成员的类型是共用体第23行是针对共用体成员GPACTRL的共用体类型 GPACTRL_REG进行了定义。24、26行表示了这个共用体类型里面有两个成员,一个是all,一个是bit,总的来说就是结构体内有共用体成员,共用体内有结构体成员,这个结构体内的成员就是all和bit。
volatile是一个类型修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
简单地说就是防止编译器对代码进行优化。
3.3第二级成员:bit
struct GPA1_BITS { // bits description
Uint16 GPIO0:2; // 1:0 GPIO0
Uint16 GPIO1:2; // 3:2 GPIO1
Uint16 GPIO2:2; // 5:4 GPIO2
Uint16 GPIO3:2; // 7:6 GPIO3
Uint16 GPIO4:2; // 9:8 GPIO4
Uint16 GPIO5:2; // 11:10 GPIO5
Uint16 GPIO6:2; // 13:12 GPIO6
Uint16 GPIO7:2; // 15:14 GPIO7
Uint16 GPIO8:2; // 17:16 GPIO8
Uint16 GPIO9:2; // 19:18 GPIO9
Uint16 GPIO10:2; // 21:20 GPIO10
Uint16 GPIO11:2; // 23:22 GPIO11
Uint16 GPIO12:2; // 25:24 GPIO12
Uint16 GPIO13:2; // 27:26 GPIO13
Uint16 GPIO14:2; // 29:28 GPIO14
Uint16 GPIO15:2; // 31:30 GPIO15
};
第二级成员bit定义如下:struct GPC1_BITS bit;是一个结构体类型,追进去如下:可以看到,该结构体表示了GPIO0~GPIO15,且内部用了C语言中【位域】的语法,每2bit表示一个GPIO,所以一个32bit寄存器可以表示16个GPIO口。所以不难发现,上一级成员中,有两个子成员(【32位的all】和【结构体GPC1_BITS】)。
(1)当代码使用第一个成员all的时候,表示所有的bit即:结构体中所有的GPIO口(GPIO0~GPIO15),
(2)当使用子成员bit的时候,可以继续具体到内部成员,具体到每一个GPIO口。
3.4结构体展示
GpioCtrlRegs.GPAMUX1.bit.GPIO7=0;
变量名为:GpioCtrlRegs
第一级成员为:GPCMUX1
第二级成员为:bit
第三级成员为:GPIO7
结构体是用.来完成访问的,所以一级一级追下来,可以发现GPIO7,就属于A组的GPIO,因为2bit表示一个GPIO,所以一个32bit的寄存器只能表示16个GPIO,所以只能表示到GPIO0~GPIO15。
四、代码GPIO点亮LED灯
不论是51单片机,还是STM32,还是DSP28335点灯是必不可少的,今天经过上述GPIO的配置完成点亮LED。因为在原理图中因为LED与GPIO7相连接,并且是低电平点亮,读者可以根据原理图自行改变!
1、LED点亮和闪烁(最后三行不注释完成闪烁).
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"
void GIOP_Init(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO7=0;//
GpioCtrlRegs.GPADIR.bit.GPIO7 =1;
GpioCtrlRegs.GPAPUD.bit.GPIO7 =0;
EDIS;
}
void main(void)
{
InitSysCtrl();
GIOP_Init();
while(1)
{
GpioDataRegs.GPACLEAR.bit.GPIO7=1;
//DELAY_US (1000*500); 这是是用来延迟的
// GpioDataRegs.GPASET.bit.GPIO7=1;
//DELAY_US (1000*500); 这是是用来延迟的
}
}
2 运用GPIO翻转寄存器.
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"
void GIOP_Init(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO7=0;//
GpioCtrlRegs.GPADIR.bit.GPIO7 =1;
GpioCtrlRegs.GPAPUD.bit.GPIO7 =0;
GpioDataRegs.GPACLEAR.bit.GPIO7=1;
// GpioCtrlRegs.GPAMUX1.bit.GPIO6=0;
// GpioCtrlRegs.GPADIR.bit.GPIO6 =1;
// GpioCtrlRegs.GPAPUD.bit.GPIO6 =0;
EDIS;
}
void main(void)
{
InitSysCtrl();
GIOP_Init();
while(1)
{
DELAY_US (1000*500);
GpioDataRegs.GPATOGGLE.bit.GPIO7=1;
}
}
DSP28335运行。
LED闪烁