文章目录
- [7.0 GPIO概念](#7.0 GPIO概念)
- [7.1 GPIO工作原理](#7.1 GPIO工作原理)
- [7.2 GPIO寄存器以及编程](#7.2 GPIO寄存器以及编程)
-
- [7.2.5 GPIO寄存器编程设置与应用](#7.2.5 GPIO寄存器编程设置与应用)
- [7.3 GPIO跑马灯](#7.3 GPIO跑马灯)
-
- [7.3.1 LED 输出初始化](#7.3.1 LED 输出初始化)
- [7.3.2 跑马灯输出实验](#7.3.2 跑马灯输出实验)
- [7.3.3 按键输入实验](#7.3.3 按键输入实验)
7.0 GPIO概念
GPIO(general purpose intput output)是通用输入输出端口的简称,可以通过软件来控制其输入和输出。
- F28335有88个GPIO口,对应着芯片的88个引脚
- 88个引脚多是复用的,既可作为输入引脚也可作为输出引脚,即可作为通用IO引脚,也可作为特殊功能口(外设)
- 可以通过GPIO MUX(输入输出多路选择器)寄存器进行相关配置。
7.1 GPIO工作原理
F28335的88个GPIO分为3组,分为A、B、C。
- A组包括GPIO0-GPIO31
- B组包括GPIO32-GPIO63
- C组包括GPIO64-GPIO87
每个引脚都复用了多个功能,GPIO MUX寄存器用来配置每个引脚的具体功能。
- 00 为通用IO引脚
- 01 10 11分别为外设1 2 3引脚
如果某个引脚选择了数字量IO模式
- 可以通过方向寄存器GPxDIR配置IO方向,既可作为输入引脚也可以作为输出引脚。
- 可以通过量化寄存器GPxQUAL对输入信号进行量化限制,从而消除数字量IO引脚的早上干扰。
有以下四种方式对GPIO引脚进行读写操作:
- 可以通过GPxDAT寄存器独立读写IO
- 可以通过GPxSET寄存器写1对IO进行置位
- 可以通过GPxCLEAR寄存器写1对IO进行清除
- 可以通过GPxTOGGLE寄存器写1翻转IO的输出电平
如7.1图所示,最左侧为GPIO0-27,上方有个PU,代表是否上拉。
- 控制寄存器为GPAPUD,0的时候上拉有效,反之无效。
两个三角形控制GPIO作为输入还是输出,上边输入,下边输出。
- GPIO输入后经过滤波电路。
GPIO输入
- 数据进入GPADAT寄存器,此时该寄存器为读寄存器,对其进行置位是无效的。
- GPADAT上方为PIE中断。
GPIO输出
- 下方三角为输出通道,输出值为GPADAT内的值。
- GPA-SET可以设置GPADAT的值
GPIO输入受到可编程滤波器的限制。用户可以通过配置GPAQSEL1、GPAQSEL2、GPBQSEL2寄存器选择GPIO引脚的输入限制类型。
7.2 GPIO寄存器以及编程
7.2.5 GPIO寄存器编程设置与应用
GPIO的数据寄存器一共有4类,分别是GPIODAT、GPIOSET、GPIOCLEAR、GPIOTOGGLE。
如果某个GPIO输出设置为输出状态,那么通过GPIODAT相应位写0或者1,此时GPIO就会输出相应的状态。
F28335的88个GPIO分为3组,分为A、B、C。
- A组GPIO可以通过软件配置为外部中断1、2以及NMI功能。
- B组GPIO可以通过软件配置为外部中断3、4、5、6、7功能。
- C组GPIO不可以配置为中断功能。
如果要将某GPIO配置为外部中断功能,下面是设置步骤。
7.3 GPIO跑马灯
7.3.1 LED 输出初始化
c
void LED_Init(void)
{
EALLOW;//关闭写保护
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // 开启GPIO时钟
//LED1端口配置
GpioCtrlRegs.GPCMUX1.bit.GPIO68=0;//设置为通用GPIO功能 0-通用输出 1-外设1输出 2-外设2输出 3-外设3输出
GpioCtrlRegs.GPCDIR.bit.GPIO68=1;//设置GPIO方向为输出 1-输出 0-输入
GpioCtrlRegs.GPCPUD.bit.GPIO68=0;//使能GPIO上拉电阻 0-使能上拉 1-禁止上拉
GpioDataRegs.GPCSET.bit.GPIO68=1;//设置GPIO输出高电平
//GpioDataRegs.GPCCLEAR.bit.GPIO68 = 1; //设置GPIO输出为低电平
EDIS;//开启写保护
}
7.3.2 跑马灯输出实验
使用DSP的引脚GPIO0-GPIO5,共阴极连接,当高电平时,LED被点亮;当为低电平时,LED熄灭。
初始化代码:
c
void LED_GPIO_Config(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO0=0;//普通IO模式
GpioCtrlRegs.GPAPUD.bit.GPIO0=0;//使能内部上拉
GpioCtrlRegs.GPADIR.bit.GPIO0=1;//配置成输出
GpioCtrlRegs.GPAMUX1.bit.GPIO1=0;//普通IO模式
GpioCtrlRegs.GPAPUD.bit.GPIO1=0;//使能内部上拉
GpioCtrlRegs.GPADIR.bit.GPIO1=1;//配置成输出
GpioCtrlRegs.GPAMUX1.bit.GPIO2=0;//普通IO模式
GpioCtrlRegs.GPAPUD.bit.GPIO2=0;//使能内部上拉
GpioCtrlRegs.GPADIR.bit.GPIO2=1;//配置成输出
GpioCtrlRegs.GPAMUX1.bit.GPIO3=0;//普通IO模式
GpioCtrlRegs.GPAPUD.bit.GPIO3=0;//使能内部上拉
GpioCtrlRegs.GPADIR.bit.GPIO3=1;//配置成输出
GpioCtrlRegs.GPAMUX1.bit.GPIO4=0;//普通IO模式
GpioCtrlRegs.GPAPUD.bit.GPIO4=0;//使能内部上拉
GpioCtrlRegs.GPADIR.bit.GPIO4=1;//配置成输出
GpioDataRegs. GPASET.bit.GPIO0=1; //输出高电平
GpioDataRegs. GPASET.bit.GPIO1=1; //输出高电平
GpioDataRegs. GPASET.bit.GPIO2=1;
GpioDataRegs. GPASET.bit.GPIO3=1;
GpioDataRegs. GPASET.bit.GPIO4=1;
EDIS;
}
7.3.3 按键输入实验
DSP GPIO作为输入时,硬件自带滤波功能,通过设置指定寄存器达到3次或6次采样滤波
c
#define KEY_L1_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO48=1)
#define KEY_L2_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO49=1)
#define KEY_L3_SetL (GpioDataRegs.GPBCLEAR.bit.GPIO50=1)
#define KEY_L1_SetH (GpioDataRegs.GPBSET.bit.GPIO48=1)
#define KEY_L2_SetH (GpioDataRegs.GPBSET.bit.GPIO49=1)
#define KEY_L3_SetH (GpioDataRegs.GPBSET.bit.GPIO50=1)
#define KEY_H1 (GpioDataRegs.GPADAT.bit.GPIO12)
#define KEY_H2 (GpioDataRegs.GPADAT.bit.GPIO13)
#define KEY_H3 (GpioDataRegs.GPADAT.bit.GPIO14)
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY5_PRESS 5
#define KEY6_PRESS 6
#define KEY7_PRESS 7
#define KEY8_PRESS 8
#define KEY9_PRESS 9
#define KEY_UNPRESS 0
void KEY_Init(void)
{
EALLOW;
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟
//KEY端口配置
/*GPIO输入端*/
GpioCtrlRegs.GPAMUX1.bit.GPIO12=0;
GpioCtrlRegs.GPADIR.bit.GPIO12=0; // GPIO设置为输入
GpioCtrlRegs.GPAPUD.bit.GPIO12=0;
GpioCtrlRegs.GPAMUX1.bit.GPIO13=0;
GpioCtrlRegs.GPADIR.bit.GPIO13=0; // GPIO设置为输入
GpioCtrlRegs.GPAPUD.bit.GPIO13=0;
GpioCtrlRegs.GPAMUX1.bit.GPIO14=0;
GpioCtrlRegs.GPADIR.bit.GPIO14=0; // GPIO设置为输入
GpioCtrlRegs.GPAPUD.bit.GPIO14=0;
/*GPIO输出端*/
GpioCtrlRegs.GPBMUX2.bit.GPIO48=0;
GpioCtrlRegs.GPBDIR.bit.GPIO48=1; // GPIO设置为输出
GpioCtrlRegs.GPBPUD.bit.GPIO48=0;
GpioCtrlRegs.GPBMUX2.bit.GPIO49=0;
GpioCtrlRegs.GPBDIR.bit.GPIO49=1; // GPIO设置为输出
GpioCtrlRegs.GPBPUD.bit.GPIO49=0;
GpioCtrlRegs.GPBMUX2.bit.GPIO50=0;
GpioCtrlRegs.GPBDIR.bit.GPIO50=1; // GPIO设置为输出
GpioCtrlRegs.GPBPUD.bit.GPIO50=0;
GpioDataRegs.GPBSET.bit.GPIO48=1;
GpioDataRegs.GPBSET.bit.GPIO49=1;
GpioDataRegs.GPBSET.bit.GPIO50=1;
EDIS;
}
char KEY_Scan(char mode) //mode=0 单次扫描 mode=1 循环扫描
{
static char keyl1=1;
static char keyl2=1;
static char keyl3=1;
//第1列扫描
KEY_L1_SetL;
KEY_L2_SetH;
KEY_L3_SetH;
if(keyl1==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0))
{
DELAY_US(10000); //消抖
keyl1=0;
if(KEY_H1==0)
{
return KEY1_PRESS;
}
else if(KEY_H2==0)
{
return KEY4_PRESS;
}
else if(KEY_H3==0)
{
return KEY7_PRESS;
}
}
else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1)
{
keyl1=1;
}
if(mode)
keyl1=1;
//第2列扫描
KEY_L2_SetL;
KEY_L1_SetH;
KEY_L3_SetH;
if(keyl2==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0))
{
DELAY_US(10000);//消抖
keyl2=0;
if(KEY_H1==0)
{
return KEY2_PRESS;
}
else if(KEY_H2==0)
{
return KEY5_PRESS;
}
else if(KEY_H3==0)
{
return KEY8_PRESS;
}
}
else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1)
{
keyl2=1;
}
if(mode)
keyl2=1;
//第3列扫描
KEY_L3_SetL;
KEY_L1_SetH;
KEY_L2_SetH;
if(keyl3==1&&(KEY_H1==0||KEY_H2==0||KEY_H3==0))
{
DELAY_US(10000);//消抖
keyl3=0;
if(KEY_H1==0)
{
return KEY3_PRESS;
}
else if(KEY_H2==0)
{
return KEY6_PRESS;
}
else if(KEY_H3==0)
{
return KEY9_PRESS;
}
}
else if(KEY_H1==1&&KEY_H2==1&&KEY_H3==1)
{
keyl3=1;
}
if(mode)
keyl3=1;
return KEY_UNPRESS;
}
void main()
{
int i=0;
char key=0;
InitSysCtrl();
LED_Init();
KEY_Init();
while(1)
{
key=KEY_Scan(0);
switch(key)
{
case KEY1_PRESS: LED2_TOGGLE;break;
case KEY2_PRESS: LED3_TOGGLE;break;
case KEY3_PRESS: LED4_TOGGLE;break;
case KEY4_PRESS: LED5_TOGGLE;break;
case KEY5_PRESS: LED6_TOGGLE;break;
case KEY6_PRESS: LED7_TOGGLE;break;
}
i++;
if(i%2000==0)
{
LED1_TOGGLE;
}
DELAY_US(100);
}
}