敏矽微电子Cortex-M0学习笔记04——GPIO详解及应用实例

cathy的头像
cathy 发布于:周三, 11/30/2022 - 14:19 ,关键词:

相关文章:

敏矽微电子Cortex-M0学习笔记01——芯片简介

敏矽微电子Cortex-M0学习笔记02——Cortex-M0开发环境的建立及调试

敏矽微电子Cortex-M0学习笔记03——时钟系统设计例程

前面我们已经对敏矽微电子的基于cortex m0内核的ME32F030R8T6的基本功能做了介绍,然后详细讲解了开发环境MDK的安装,pack包的安装,工程的建立及程序的仿真,紧接着讲解了ME32F030R8T6的时钟系统。

如果说前面都是基础知识介绍和理论讲解,那么从本篇开始,我们不但会有理论介绍,还会结合敏矽微电子提供的ME32F030R8T6开发板进行实例验证,让大家看到实例运行的结果。

1、敏矽微电子Cortex-M0学习笔记04-GPIO详解及实例

首先我们对ME32F030R8T6芯片的I/O端口做一个大致的了解。

1.1. ME32F030R8T6的GPIO 概述

ME32F030R8T6提供多达 57个 GPIO 管脚。主要的特点有:

• 数字管脚可以用软件定义为输入或输出

• 管脚读写可以被屏蔽

• 多个管脚的置位、清零位用一条指令实现

• 管脚的输出取反

• 每一个管脚可作为外部中断信号

• 可编程的中断触发条件及中断优先级

• 所有GPIO管脚在复位后被配置成带上拉电阻的输入管脚

MCU的端口除了灵活易用的特点之外,其外设功能也十分强大。管脚功能由IO控制寄存器配置,除电源管脚,其余管脚均可复用。

系统复位后,管脚功能将被设置成默认值。

GPIO可以复用的功能如下:LED/LCD 驱动、触摸按键、ADC、定时器6输出、定时器7输出、PWM输出、UART0、UART1、SPI、I2C。

在使用端口复用功能时,通过 I/O 配置寄存器IOCON对端口进行功能设置,每个引脚对应的复用功能,请参照官方数据手册的详细说明。

1.2. ME32F030R8T6的GPIO 寄存器详解

对于使用过单片机开发产品的人来说,功能繁多、名称各异的寄存器应该是最重要也是最令人头疼的地方,但是没办法,想要开发出功能稳定、性能可靠的产品,就必须来硬着头皮查看各个寄存器的功能和配置方法。

当然,对于ME32F030R8T6来说,官方推出了库函数,利用这些库函数可以不必关心具体的寄存器就能编写出合适的程序。但是对于想要深入了解的话,还是要看看寄存器的。

1.2.1. GPIO功能配置寄存器

MCU有一系列的GPIO 控制寄存器来实现对I/O口的灵活控制。

首先我们对 I/O 配置寄存器IOCON做一个介绍,因为它决定着I/O端口的功能选择和电气特性。所以需要拿出来单独进行介绍,该寄存器的每一位的功能如下:

1.png

2.png

①、管脚功能:

IOCON 寄存器中的 FUNC 位可设为 GPIO (FUNC = 000) 或外设功能。如果将管脚配置为 GPIO 管脚,则 DIR 寄存器决定管脚是配置为输入还是输出。对于任何外设功能,会根据管脚的功能自动控制管脚方向。GPIO 的 DIR 寄存器此时对外设功能无效。

②、管脚模式:

IOCON 寄存器的 MODE 位允许为每个管脚使能或禁止片内上拉电阻。默认情况下,所有管脚的上拉电阻都被使能。

③、管脚驱动

对于每个正常驱动管脚,可以选择两种电流的输出驱动,即低电流模式和高电流模式。用户可以根据自己的实际需求进行选择。

④、开漏模式

所有数字 I/O 管脚都可为开漏模式。但是请注意,该模式并不是真正的开漏模式。输入上拉至不能超过VDD。

⑤、模式功能

I/O 管脚可以配置为模拟功能,作为模拟信号的输出和输入管脚,例如复用为AD口的时候,可以作为检测电压的模拟信号输入口。

⑤、电压转换速率模式

在作用AD转换口的时候,可以设置端口转换速率为快速模式或慢速模式,默认为快速模式。相对于快速模式,慢速模式转满时间会变长,随之电流功耗也增大,但时精度会更加精确,根据应用场景和自身需求,选择适合的模式。

1.2.2. GPIO控制寄存器总览

MCU所有的GPIO被分布到4个端口: PA,、PB、PC、PD。每个端口都拥有自己独立的控制寄存器去管理 GPIO 的功能。下面的表列出了所有的寄存器以供参考。接下来会对每个寄存器做出详解。

3.png

4.png

1.2.3. GPIO屏蔽寄存器

GPIO屏蔽寄存器可屏蔽下列寄存器的读和写操作:PIN、OUT、SET、CLR和 NOT,相当于给这些寄存器上了个“锁”,只有当MASK寄存器相应的BIT位被置 0,被屏蔽的寄存器才能进行读和写操作。该寄存器上电后默认为0,即不进行GPIO屏蔽。当配置1启动屏蔽功能后,对处于输出功能的端口进行任何写操作都无效,不会改变其当前的输出状态。对处于输入功能的端口进行读操作,无论此时端口处于何种电平,都会返回0.

1.2.4. GPIO管脚值寄存器

对配置为数字功能的端口,对该寄存器进行读操作将返回管脚的当前逻辑值,不管该管脚是配置为输入还是输出,也不管它是配置为 GPIO 还是任何其它适用的备用数字功能,都可以直接进行读取。但也有例外,在以下两种情况中, PIN 寄存器中读出的管脚值无效:①、如果选择了管脚的模拟功能(如适用),则不能读取管脚状态,例如将管脚选作 ADC 输入会断开管脚的数字功能。②、该引脚被GPIO屏蔽寄存器MASK给屏蔽了。

1.2.5. GPIO管脚输出寄存器

在没有被GPIO屏蔽寄存器MASK屏蔽的情况下,向该寄存器写0或1将在相应端口管脚产生低电平或高电平。但是对于所有其他配置(输入、非GPIO功能),OUT 寄存器位的值对管脚输出电平无效。读取该寄存器将返回 GPIO 输出寄存器的内容,不管数字管脚配置和方向如何。

通过SET、CLR和NOT寄存器可以对OUT 寄存器执行写操作,允许按位对单个端口管脚进行置位、清除、取反操作。以此来控制OUT 寄存器的输出内容。

1.2.6. GPIO管脚输出置位寄存器

在没有被GPIO屏蔽寄存器MASK屏蔽,端口DIR为输出方向且端口功能为数字GPIO功能的情况下,写1会将相应端口管脚设为高电平。写0对GPIO输出电平无效。另外该寄存器为只写寄存器,对其进行读操作是无效的。

1.2.7. GPIO管脚输出清除寄存器

在没有被GPIO屏蔽寄存器MASK屏蔽,端口DIR为输出方向且端口功能为数字GPIO功能的情况下,写1会将相应端口管脚设为低电平。写0对GPIO输出电平无效。另外该寄存器为只写寄存器,对其进行读操作是无效的。

1.2.8. GPIO管脚输出取反寄存器

在没有被GPIO屏蔽寄存器MASK屏蔽,端口DIR为输出方向且端口功能为数字GPIO功能的情况下,写1会将相应端口的输出状态进行反转。写0对GPIO输出电平无效。另外该寄存器为只写寄存器,对其进行读操作是无效的。

1.2.9. GPIO数据方向寄存器

在使用数字GPIO前,首先要确定的就是端口的数据方向。向该寄存器写1会将端口设置为输出模式,写0设置为输入模式。上电后端口默认为输入状态。

1.2.10. GPIO中断感应寄存器

在文章开头的介绍中,我们就说过MCU的每一个管脚是可以作为外部中断信号。因此会有一系列与之对应的中断管理寄存器,来对每个端口的中断进行管理。这就是接下来要介绍的中断寄存器。在使用端口中断前,需要明确需要触发中断的条件。向中断感应寄存器ISENSEx写入1,端口中断的触发方式为电平中断。向寄存器写入0,端口中断的触发方式为沿中断触发,具体需要什么样的沿来触发,这个还需要下面的中断配置寄存器来设置。

1.2.11. GPIO中断配置寄存器

紧接上文,在明确使用端口触发方式为沿中断触发后,我们通过中断配置寄存器IBEx来选择沿触发条件。向寄存器写入1,管脚的上升沿和下降沿都触发中断。向寄存器写入0,管脚只能由上升沿或下降沿中的一种来触发中断,具体由哪种来触发,需要下面的中断事件寄存器IEVx来决定。

1.2.12. GPIO中断事件寄存器

当中断配置寄存器IBEx值为0时,中断事件寄存器就决定着中断触发的条件,向寄存器写1,上升沿触发中断。写入0,则下降沿产生中断。

1.2.13. GPIO中断屏蔽寄存器

在实际的开发过程中,使用到中断功能的端口毕竟是少数,因此MCU在上电后就默认屏蔽了端口的中断功能。如果要开启端口的中断功能,向对应的寄存器位写1即可。

1.2.14. GPIO原始中断状态寄存器

该寄存器的位读出为高时反映了对应管脚上的原始(屏蔽之前)中断状态,表示在触发 IE 之前所有的要求都满足。位读出为0时表示对应的输入管脚还未启动中断。该寄存器为只读。

1.2.15. GPIO中断状态寄存器

该寄存器中的位读为高反映了输入触发中断的状态。读出为低则表示对应的输入管脚没有中断产生,或者中断被屏蔽。读出为高则表示对应的输入管脚有中断产生。该寄存器为只读。

1.2.16. GPIO中断清除寄存器

在中断发生后,程序会进入中断服务子程序。在中断服务子程序中处理完中断程序后,需要向中断清除寄存器CLRx写1来清除中断标志。

1.3. ME32F030R8T6的GPIO 库函数函数

为了便于开发者快速上手,敏矽微电子官方例程中提供了gpio.c文件,其中包含了设置端口方向、读取端口状态、配置端口中断等函数,供开发者直接使用。

1、设置GPIO为输入方向

void GPIO_ConfigPinsAsInput(PA_Type *port, uint16_t pins)

{

    port->DIR &= ~pins;

    return;

}

2、设置GPIO位输出方向

void GPIO_ConfigPinsAsOutput(PA_Type *port, uint16_t pins)

{

    port->DIR|=pins;

    return;

}

3、设置GPIO输出高

void GPIO_SetPin(PA_Type *port, uint16_t pin)

{

    port->SET |= pin;

    return;

}

4、设置GPIO输出低

void GPIO_ResetPin (PA_Type *port, uint16_t pin)

{

    port->CLR |= pin;

    return;

}

5、设置GPIO输出反转

void GPIO_InvertOutPin (PA_Type *port, uint16_t pin)

{

    port->NOT |= pin;

    return;

}

6、读取GPIO某个引脚的输入状态

uint8_t GPIO_GetPinState(PA_Type *port, uint16_t pin)

{

    if (port->PIN & pin)

    return 1;

    else

    return 0;

}

7、读取GPIO整个引脚的输入状态

uint16_t GPIO_GetPortState(PA_Type *port)

{

    return (uint16_t)port->PIN;

}

8、屏蔽GPIO引脚

void GPIO_SetPortMask(PA_Type *port, uint16_t pins)

{

    port->MASK |= pins;

    return;

}

9、使能GPIO引脚

void GPIO_SetPortMask(PA_Type *port, uint16_t pins)

{

    port->MASK |= pins;

    return;

}

10、配置GPIO引脚的中断功能

void GPIO_EnableInt(PA_Type *port, uint16_t pin, uint8_t triggeredge)

{

	port->IS &= ~pin;


        port->IE |= pin;

    	switch(triggeredge)

    	{

    		case RISE_EDGE:
					port->IBE &= ~pin;

					port->IEV |= pin;			break;			case FALL_EDGE:

					port->IBE &= ~pin;

					port->IEV &= ~pin;			break;			case BOTH_EDGE:

					port->IBE |= pin;			break;				default:			break;



    		}

    		return;

}

11、清除GPIO引脚的中断标志

void GPIO_ClrInt(PA_Type *port, uint16_t pins)

{

    	port->IC =pins;

    	return;
}

1.4. ME32F030R8T6的GPIO 开发实例

介绍完GPIO的原理和函数,接下来就用最经典的LED小灯试验来进行示例。

本例使用敏矽微电子专门为ME32F030R8T6提供的库函数编写程序。

实例程序的代码如下:

int main(void

{
	WDT->MOD=0;          //关闭看门狗   

	PB_9_INIT(PB_9_GPIO);          //PB9(LED)设置为GPIO功能

	GPIO_ConfigPinsAsOutput(PB, IO_PIN9);  //PB9(LED)设置为输出方向

	while (1)

	{

		GPIO_InvertOutPin(PB, IO_PIN9);  //PB9(LED)端口输出反转

		SYS_DelaymS(500);                //延时500ms

	}

}

程序下载成功后,先在端口反转这句话处打上一个断点,然后全速运行程序(快捷键F5)。随后程序会停在断点处,

5.png

此时先暂停观察下LED小灯的状态,发现红圈标注的小灯并没有被点亮。

6.png

运行结果1

接下来单步运行程序,观察执行完端口反转这段程序后的状态。这时我们发现小灯已经被点亮了。

7.png


继续单步运行,当再次执行端口反转这段程序后,端口输出就会反转,接下来小灯就会熄灭。最后取消程序中的所有断点,让程序全速运行起来,小灯便开始周期性的闪烁。

来源:敏矽MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 234