恩智浦 飞思卡尔Freescale Kinetis KEA128学习笔记3--GPIO模块(一)

 

 

       KEA128芯片有7组IO,PORTA--H每组8个引脚,PORTI有7个引脚,共计71个。

       单个引脚驱动能力是2.5mA,内部均可上拉到VDD,无内部下拉。应通过编程将未使用引脚内部上拉。

     MCU处在运行、等待、调试模式下,GPIO正常工作,停止模式下,GPIO停止工作。

下面是端口控制寄存器介绍,主要是端口滤波寄存器,上拉使能寄存器和高驱动能力使能寄存器

GPIO有三组寄存器,分别为GPIOA、GPIOB、GPIOC。每组有7个寄存器,分别为输出寄存器(PDOR)、输出置1寄存器(PSOR)、输出清0寄存器(PCOR)、输出取反寄存器(PTOR)、输入寄存器(PDIR)、数据放向寄存器(PDDR)、输入禁止寄存器(PIDR)。

GPIO编程步骤:

1.设定GPIO是输入还是输出,设置数据方向寄存器

2.若是输出则设定GPIO的值,低0高1

3.若是输入则通过输入寄存器获得引脚的状态。低0高1.

 

//===========================================================================
//文件名称:common.h
//功能概要:公共要素头文件
//版权所有:苏州大学飞思卡尔嵌入式中心(sumcu.suda.edu.cn)
//版本更新:2015-06-05  V2.0
//芯片类型:KEA128
//===========================================================================

#ifndef	__COMMON_H       //防止重复定义(_COMMON_H  开头)
#define __COMMON_H

// 1.芯片寄存器映射文件及处理器内核属性文件
#include "core_cmFunc.h"
#include "core_cmInstr.h"
#include "core_cm0plus.h"
#include "SKEAZ1284.h"           // 包含芯片头文件
#include "system_SKEAZ1284.h"    // 包含芯片系统初始化文件

#define  SYSTEM_CLK_KHZ   DEFAULT_SYSTEM_CLOCK/1000// 芯片系统时钟频率(KHz)
#define  CORE_CLK_KHZ     SYSTEM_CLK_KHZ           // 芯片内核时钟频率(KHz)
#define  BUS_CLK_KHZ      SYSTEM_CLK_KHZ/2         // 芯片总线时钟频率(KHz)

// 2.定义开关总中断
#define ENABLE_INTERRUPTS   __enable_irq   // 开总中断
#define DISABLE_INTERRUPTS  __disable_irq  // 关总中断

// 3.位操作宏函数(置位、清位、获得寄存器一位的状态)
#define BSET(bit,Register)  ((Register)|= (1<<(bit)))    // 置寄存器的一位
#define BCLR(bit,Register)  ((Register) &= ~(1<<(bit)))  // 清寄存器的一位
#define BGET(bit,Register)  (((Register) >> (bit)) & 1)  // 获得寄存器一位的状态

// 4.重定义基本数据类型(类型别名宏定义)
typedef unsigned char uint_8;   // 无符号8位数,字节
typedef unsigned short int uint_16;  // 无符号16位数,字
typedef unsigned long int uint_32;  // 无符号32位数,长字
typedef char int_8;    // 有符号8位数
typedef short int int_16;   // 有符号16位数
typedef int int_32;   // 有符号32位数
// 不优化类型
typedef volatile uint_8 vuint_8;  // 不优化无符号8位数,字节
typedef volatile uint_16 vuint_16; // 不优化无符号16位数,字
typedef volatile uint_32 vuint_32; // 不优化无符号32位数,长字
typedef volatile int_8 vint_8;   // 不优化有符号8位数
typedef volatile int_16 vint_16;  // 不优化有符号16位数
typedef volatile int_32 vint_32;  // 不优化有符号32位数

#endif       //防止重复定义(_COMMON_H结尾)
//===========================================================================
//文件名称:gpio.h
//功能概要:GPIO底层驱动构件头文件
//版权所有:苏州大学飞思卡尔嵌入式中心(sumcu.suda.edu.cn)
//版本更新:2015-06-05  V2.0
//芯片类型:KEA128
//===========================================================================

#ifndef GPIO_H        //防止重复定义(GPIO_H  开头)
#define GPIO_H

#include "common.h"   //包含公共要素头文件

// 端口号地址偏移量宏定义
#define PORTA    (0<<8)
#define PORTB    (1<<8)
#define PORTC    (2<<8)
#define PORTD    (3<<8)
#define PORTE    (4<<8)
#define PORTF    (5<<8)
#define PORTG    (6<<8)
#define PORTH    (7<<8)
#define PORTI    (8<<8)
//引脚方向宏定义
#define GPIO_IN      0
#define GPIO_OUTPUT  1

//===========================================================================
//函数名称:gpio_init
//函数返回:无
//参数说明:port_pin:(端口号)|(引脚号)(例:PORTB|(5) 表示为B口5号脚)
//       dir:引脚方向(0=输入,1=输出,可用引脚方向宏定义)
//       state:端口引脚初始状态(0=低电平,1=高电平)
//功能概要:初始化指定端口引脚作为GPIO引脚功能,并定义为输入或输出,若是输出,
//       还指定初始状态是低电平或高电平
//===========================================================================
void gpio_init(uint_16 port_pin, uint_8 dir, uint_8 state);

//===========================================================================
//函数名称:gpio_set
//函数返回:无
//参数说明:port_pin:(端口号)|(引脚号)(例:PORTB|(5) 表示为B口5号脚)
//       state:希望设置的端口引脚状态(0=低电平,1=高电平)
//功能概要:当指定端口引脚被定义为GPIO功能且为输出时,本函数设定引脚状态
//===========================================================================
void gpio_set(uint_16 port_pin, uint_8 state);

//===========================================================================
//函数名称:gpio_get
//函数返回:指定端口引脚的状态(1或0)
//参数说明:port_pin:(端口号)|(引脚号)(例:PORTB|(5) 表示为B口5号脚)
//功能概要:当指定端口引脚被定义为GPIO功能且为输入时,本函数获取指定引脚状态
//===========================================================================
uint_8 gpio_get(uint_16 port_pin);

//===========================================================================
//函数名称:gpio_reverse
//函数返回:无
//参数说明:port_pin:(端口号)|(引脚号)(例:PORTB|(5) 表示为B口5号脚)
//功能概要:当指定端口引脚被定义为GPIO功能且为输出时,本函数反转引脚状态
//===========================================================================
void gpio_reverse(uint_16 port_pin);

//===========================================================================
//函数名称:gpio_pull
//函数返回:无
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//          pullselect:引脚上拉使能选择( 0=上拉除能,1=上拉使能)
//功能概要:使指定引脚上拉高电平
//===========================================================================
void gpio_pull(uint_16 port_pin, uint_8 pullselect);

#endif     //防止重复定义(GPIO_H  结尾)
//===========================================================================
//声明:
//(1)我们开发的源代码,在本中心提供的硬件系统测试通过,真诚奉献给社会,不足之处,欢迎指正。
//(2)对于使用非本中心硬件系统的用户,移植代码时,请仔细根据自己的硬件匹配。
//
//苏州大学飞思卡尔嵌入式中心
//技术咨询:0512-65214835  http://sumcu.suda.edu.cn
//===========================================================================
//文件名称:gpio.c
//功能概要:GPIO底层驱动构件源文件
//版权所有:苏州大学飞思卡尔嵌入式中心(sumcu.suda.edu.cn)
//版本更新:2015-06-05  V2.0
//芯片类型:KEA128
//===========================================================================
#include "gpio.h"   //包含本构件头文件

uint_32 bit;    //内部变量,用于记录引脚在端口寄存器中的偏移量
//内部函数声明
//解析端口号和引脚
static void gpio_port_pin_num(uint_16 port_pin,uint_8* port,uint_8* pin);
//解析基地址和引脚在寄存器中的偏移量
static void gpio_ptr_bit(uint_16 port_pin,GPIO_MemMapPtr* gpio_ptr,uint_32* bit);
//===========================================================================
//函数名称:gpio_init
//函数返回:无
//参数说明:port_pin:(端口号)|(引脚号)(例:PORTB|(5) 表示为B口5号脚)
//       dir:引脚方向(0=输入,1=输出,可用引脚方向宏定义)
//       state:端口引脚初始状态(0=低电平,1=高电平)
//功能概要:初始化指定端口引脚作为GPIO引脚功能,并定义为输入或输出,若是输出,
//       还指定初始状态是低电平或高电平
//===========================================================================
void gpio_init(uint_16 port_pin, uint_8 dir, uint_8 state)
{
	//局部变量声明
	GPIO_MemMapPtr gpio_ptr;    //声明port_ptr为GPIO结构体类型指针
	gpio_ptr_bit(port_pin,&gpio_ptr,&bit);//计算基地址和和引脚在寄存器中的偏移量
	
	
	//根据带入参数dir,决定引脚为输出还是输入
	if (1 == dir)   //希望为输出
	{
		//端口数据方向寄存器定义为输出
		BSET(bit, GPIO_PDDR_REG(gpio_ptr));//1为通用输出,0零表示作为输入
		//输出清零寄存器
		BSET(bit, GPIO_PCOR_REG(gpio_ptr));//该寄存器置1,引脚输出被置位为0
		//初始状态为低电平
		gpio_set(port_pin, state);   //调用gpio_set函数,设定引脚初始状态
	} 
	else 
	{
		//希望为输入
		BCLR(bit, GPIO_PDDR_REG(gpio_ptr));
	}
}

//===========================================================================
//函数名称:gpio_set
//函数返回:无
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//       state:引脚初始状态(0=低电平,1=高电平)
//功能概要:设定引脚状态为低电平或高电平
//===========================================================================
void gpio_set(uint_16 port_pin, uint_8 state)
{
	//局部变量声明
	GPIO_MemMapPtr gpio_ptr;    //声明port_ptr为GPIO结构体类型指针
	gpio_ptr_bit(port_pin,&gpio_ptr,&bit);//计算基地址和和引脚在寄存器中的偏移量
	
	//根据带入参数state,决定引脚为输出1还是0
	if (1==state) 
	{
		BSET(bit,gpio_ptr->PDOR);//对应位置为1
	} else {
		BCLR(bit,gpio_ptr->PDOR);//对应位置为0
	}
}

//===========================================================================
//函数名称:gpio_get
//函数返回:指定引脚的状态(1或0)
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//功能概要:获取指定引脚的状态(1或0)
//===========================================================================
uint_8 gpio_get(uint_16 port_pin)
{
	//局部变量声明
	GPIO_MemMapPtr gpio_ptr;    //声明port_ptr为GPIO结构体类型指针
	gpio_ptr_bit(port_pin,&gpio_ptr,&bit);//计算基地址和和引脚在寄存器中的偏移量
	
	//返回引脚的状态
	return ((BGET(bit,gpio_ptr->PDIR))>=1 ? 1:0);
}

//===========================================================================
//函数名称:gpio_reverse
//函数返回:无
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//功能概要:反转指定引脚输出状态。
//===========================================================================
void gpio_reverse(uint_16 port_pin)
{
	//局部变量声明
	GPIO_MemMapPtr gpio_ptr;    //声明port_ptr为GPIO结构体类型指针
	gpio_ptr_bit(port_pin,&gpio_ptr,&bit);//计算基地址和和引脚在寄存器中的偏移量
	//反转指定引脚输出状态
	BSET(bit,gpio_ptr->PTOR);
}

//===========================================================================
//函数名称:gpio_pull
//函数返回:无
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//       pullselect:引脚上拉使能选择( 0=上拉除能,1=上拉使能)
//功能概要:使指定引脚上拉高电平
//===========================================================================
void gpio_pull(uint_16 port_pin, uint_8 pullselect)
{
	//局部变量声明
	uint_8 port;                //端口号
	uint_8 pin;                 //引脚号
	gpio_port_pin_num(port_pin, &port, &pin);   //解析出端口号及引脚号
	//计算引脚在寄存器中的偏移量
	if (port < 4)               //端口号为PORTA~PORTD
	{
		//引脚所在的位数
		bit = 8 * port + pin;
		if (1==pullselect){BSET(bit,PORT_PUE0);}//端口上拉使能低位寄存器0上拉使能
			else {BCLR(bit,PORT_PUE0);}//上拉除能(不使能)
	}
	else if(3<port &&port< 8)  //端口号为PORTE~PORTH
	{
		//引脚所在的位数
		bit = 8 * (port - 4) + pin;
		if (1==pullselect){BSET(bit,PORT_PUE1);}//端口上拉使能低位寄存器1上拉使能
			else {BCLR(bit,PORT_PUE1);}
	}
	else                       //端口号为PORTI
	{
		//引脚所在的位数
		bit = 8 * (port - 8) + pin;
		if (1==pullselect){BSET(bit,PORT_PUE2);}//端口上拉使能低位寄存器2上拉使能
			else {BCLR(bit,PORT_PUE2);}
	}
}

//----------------------以下为内部函数存放处----------------------------------------
//===========================================================================
//函数名称:gpio_port_pin_num
//函数返回:无
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//       port:解析出的端口号
//		 pin:解析出的引脚号(0~8,实际取值由芯片的物理引脚决定)
//功能概要:将传进参数port_pin(例:PORTB|(5))进行解析,得出具体端口号与引脚号,由port、pin传出。
//       例如,PORTB|(5)解析为*port=PORTB,*pin=5)。
//备        注:port,pin为传地址参数,目的是将结果带回,调用函数前,不需要赋值
//===========================================================================
static void gpio_port_pin_num(uint_16 port_pin,uint_8* port,uint_8* pin)
{
	*port = port_pin>>8;
	*pin = port_pin;
}
//===========================================================================
//函数名称:gpio_ptr_bit
//函数返回:无
//参数说明:port_pin:端口号|引脚号(例:PORTB|(5) 表示为B口5号脚)
//          gpio_ptr:解析出的基地址
//		      bit:引脚在寄存器中的偏移量
//功能概要:将传进参数port_pin(例:PORTB|(5))进行解析,解析基地址和引脚在寄存器中的偏移量,由gpio_ptr、bit传出。
//          例如:PORTB|(5)解析为基地址为GPIOA_BASE_PTR,偏移量为13
//备        注:port,pin为传地址参数,目的是将结果带回,调用函数前,不需要赋值
//===========================================================================
//解析基地址和引脚在寄存器中的偏移量
static void gpio_ptr_bit(uint_16 port_pin,GPIO_MemMapPtr* gpio_ptr,uint_32* bit)
{
	
	uint_8 port;                //端口号
	uint_8 pin;                 //引脚号
	gpio_port_pin_num(port_pin, &port, &pin);   //解析出端口号及引脚号
	//计算引脚在寄存器中的偏移量
	if (port < 4)               //端口号为PORTA~PORTD
	{
		//端口所在的寄存器基地址
		*gpio_ptr = GPIOA_BASE_PTR;
		//引脚所在的位数
		*bit = 8 * port + pin;
	} 
	else if(3<port &&port< 8)   //端口号为PORTE~PORTH
	{
		//端口所在的寄存器基地址
		*gpio_ptr = GPIOB_BASE_PTR;
		//引脚所在的位数
		*bit = 8 * (port - 4) + pin;
	}
	else                       //端口号为PORTI
	{
		//端口所在的寄存器基地址
		*gpio_ptr = GPIOC_BASE_PTR;
		//引脚所在的位数
		*bit = 8 * (port - 8) + pin;
	}
	
}
//----------------------------内部函数结束---------------------------------------

 

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值