7 通用数字量输入输出GPIO

文章目录

  • [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);
	}
}
相关推荐
Wallace Zhang4 小时前
STM32F103_Bootloader程序开发11 - 实现 App 安全跳转至 Bootloader
stm32·嵌入式硬件·安全
GodKK老神灭4 小时前
STM32 CCR寄存器
stm32·单片机·嵌入式硬件
杰克逊的日记9 天前
MCU编程
单片机·嵌入式硬件
Python小老六9 天前
单片机测ntc热敏电阻的几种方法(软件)
数据库·单片机·嵌入式硬件
HX科技10 天前
STM32给FPGA的外挂FLASH进行升级
stm32·嵌入式硬件·fpga开发·flash·fpga升级
Suagrhaha10 天前
驱动入门的进一步深入
linux·嵌入式硬件·驱动
国科安芯10 天前
基于ASP4644多通道降压技术在电力监测系统中集成应用与发展前景
嵌入式硬件·硬件架构·硬件工程
Li Zi10 天前
STM32 ADC(DMA)双缓冲采集+串口USART(DMA)直接传输12位原始数据到上位机显示并保存WAV格式音频文件 收藏住绝对实用!!!
经验分享·stm32·单片机·嵌入式硬件
进击的程序汪10 天前
触摸屏(典型 I2C + Input 子系统设备)从设备树解析到触摸事件上报
linux·网络·嵌入式硬件
damo王10 天前
Zephyr 系统深入解析:SoC 支持包结构与中断调度器调优实践
单片机·嵌入式硬件·zephyr