2-LPC1778之GPIO

其实这篇文章主要是介绍自己为其写的GPIO库,自己借鉴了原子写的STM32,野火写的K60,还有LPC官方库,然后按照自己平时用的,然后写了一个..其实写库的主要目的是为了方便(主要是方便操作)以后自己用,还想着分享给别人用,加快项目开发的速度,,本想着后期的各种功能库都自己写一套...不过就今天看来应该到此为止了.......

其实现在也没心情介绍了,直接说一下有什么实用的功能

第一点哈,支持位带操作

//IO口操作宏定义#defineBITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))#defineMEM_ADDR(addr)  *((volatile unsigned long  *)(addr))#defineBIT_ADDR(addr, bitnum)  MEM_ADDR(BITBAND(addr, bitnum))//IO口地址映射#defineGPIO0_PIN_Addr    (LPC_GPIO0_BASE+20)#defineGPIO1_PIN_Addr    (LPC_GPIO1_BASE+20)#defineGPIO2_PIN_Addr    (LPC_GPIO2_BASE+20)#defineGPIO3_PIN_Addr    (LPC_GPIO3_BASE+20)#defineGPIO4_PIN_Addr    (LPC_GPIO4_BASE+20)#defineGPIO5_PIN_Addr    (LPC_GPIO5_BASE+20)#defineP0out(n)  BIT_ADDR(GPIO0_PIN_Addr,n)//输出#defineP0in(n)    BIT_ADDR(GPIO0_PIN_Addr,n)//输入#defineP1out(n)  BIT_ADDR(GPIO1_PIN_Addr,n)//输出#defineP1in(n)    BIT_ADDR(GPIO1_PIN_Addr,n)//输入#defineP2out(n)  BIT_ADDR(GPIO2_PIN_Addr,n)//输出#defineP2in(n)    BIT_ADDR(GPIO2_PIN_Addr,n)//输入#defineP3out(n)  BIT_ADDR(GPIO3_PIN_Addr,n)//输出#defineP3in(n)    BIT_ADDR(GPIO3_PIN_Addr,n)//输入#defineP4out(n)  BIT_ADDR(GPIO4_PIN_Addr,n)//输出#defineP4in(n)    BIT_ADDR(GPIO4_PIN_Addr,n)//输入#defineP5out(n)  BIT_ADDR(GPIO5_PIN_Addr,n)//输出#defineP5in(n)    BIT_ADDR(GPIO5_PIN_Addr,n)//输入

好处就不言而喻了,,简直太方便了和实用了

第二点

voidGPIO_Conf_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint32_t mode);//配置指定引脚的模式voidGPIO_Conf_Bits(uint8_t GPIOx, uint32_t StartPinx,uint32_t PinNum,uint32_t mode);//配置多个连续引脚的模式voidGPIO_Init_Bit(GPIO_InitTypeDef * GPIO_InitStruct);//初始化一个引脚的模式--内部调用,用户不使用voidGPIO_Init_Bits(GPIO_InitTypeDef *GPIO_InitStruc,uint32_t PinNum);//初始化多个连续引脚的配置--内部调用,用户不使用voidGPIO_Dir_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t Dir);//设置指定引脚的输入输出方向voidGPIO_Dir_Bits(uint8_t GPIOx, uint32_t StartPinx,uint32_t PinNum,uint8_t Dir);//设置多个连续引脚的输入输出方向voidGPIO_Write_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t BitVal);//设置指定引脚输出高低电平voidGPIO_Write_Bits(uint8_t GPIOx,uint32_t BitVal);//将数据写入指定的GPIO数据端口uint8_t GPIO_Read_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx);//读取指定引脚的电平状态uint32_t GPIO_Read_Bits(uint8_t GPIOx);//读取指定的GPIO端口的电平状态voidGPIO_Mask_Bit(uint8_t GPIOx,uint32_t GPIO_Pinx,uint8_t Mask);//屏蔽或清除屏蔽引脚voidGPIO_Mask_Bits(uint8_t GPIOx, uint32_t StartPinx,uint32_t PinNum,uint8_t Mask);//屏蔽或清除屏蔽多个连续引脚

其实有了位带操作自己感觉应该去掉上面的设置一个引脚的电平,,,不过呢!位带操作我是访问的PIN寄存器,而函数里面用的是SET和CLR

先说第一个函数的实现过程

先看内部

/**

* @brief  配置指定引脚的模式

* @param  GPIOx:设置的端口0-5

* @param  GPIO_Pinx:设置的引脚0-32

* @param  mode:引脚的模式

GPIO_Mode_IFT        //无上下拉

GPIO_Mode_IPD        //内部下拉

GPIO_Mode_IPU        //内部上拉

GPIO_Mode_TRA        //转发模式

GPIO_Mode_HYS        //迟滞模式

GPIO_Mode_INV        //输入反向

GPIO_Mode_SWI        //转换速率

GPIO_Mode_OOD        //开漏输出

* @retval None

* @example GPIO_Conf_Bit(GPIO0,1,GPIO_Mode_IPD);//P0_1下拉*/voidGPIO_Conf_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint32_t mode)

{

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.GPIOx=GPIOx;

GPIO_InitStruct.mode=mode;

GPIO_InitStruct.Pinx=GPIO_Pinx;

GPIO_Init_Bit(&GPIO_InitStruct);

}

我定义了一个结构体

/*端口初始化结构体*/typedefstruct{

uint8_t      GPIOx;//引脚端口号uint32_t    mode;//工作模式uint32_t    Pinx;//引脚号0~31}GPIO_InitTypeDef;

/**

* @brief  初始化一个引脚的配置--用户不使用

* @param  *GPIO_InitStruc:端口初始化结构体指针

* @param

* @param

* @retval None

* @example GPIO_Init_Bit(&GPIO_InitStruc);*/voidGPIO_Init_Bit(GPIO_InitTypeDef *GPIO_InitStruc)

{switch(GPIO_InitStruc->GPIOx)

{case0:GPIO_Type->GPIO0_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case1:GPIO_Type->GPIO1_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case2:GPIO_Type->GPIO2_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case3:GPIO_Type->GPIO3_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case4:GPIO_Type->GPIO4_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;case5:GPIO_Type->GPIO5_Table[GPIO_InitStruc->Pinx] = GPIO_InitStruc->mode;break;default:break;

}

}

然后呢

/*引脚初始化结构体*/typedefstruct{

__IO uint32_t GPIO0_Table[32];

__IO uint32_t GPIO1_Table[32];

__IO uint32_t GPIO2_Table[32];

__IO uint32_t GPIO3_Table[32];

__IO uint32_t GPIO4_Table[32];

__IO uint32_t GPIO5_Table[4];

}GPIO_Type_Config;

LPC_ICON_BASE这个地址到LPC_ICON_BASE+32+32+32+32+32+4这个地址分别对应P0,P1,P2,P3,P4,P5的各个引脚的配置寄存器

那么

GPIO_Type->GPIO0_Table[0] 就是配置P0_0引脚

GPIO_Type->GPIO1_Table[1] 就是配置P1_1引脚

GPIO_Type->GPIO2_Table[2] 就是配置P2_2引脚

其实写成数组也是为了便于区分是哪个端口

因为我传入的是

端口号  还有  引脚号后面的  模式(mode)  一开始用的枚举,后来一想为了能一下子写入多种配置,所以就宏定义的,这样的话模式或运算写入就好啦

/*宏定义引脚的所有配置*/#defineGPIO_Mode_IFT  (0x0000)      /* 无上下拉 */#defineGPIO_Mode_IPD  (0x0008)      /* 内部下拉 */#defineGPIO_Mode_IPU  (0x0010)      /* 内部上拉 */#defineGPIO_Mode_TRA  (0x0018)      /* 转发模式*/#defineGPIO_Mode_HYS  (0x0020)      /* 迟滞模式*/#defineGPIO_Mode_INV  (0x0040)      /* 输入反向*/#defineGPIO_Mode_SWI  (0x0200)      /* 转换速率*/#defineGPIO_Mode_OOD  (0x0400)      /* 开漏输出 */

看最后一个函数

/**

* @brief  设置指定引脚输出高低电平

* @param  GPIOx:设置的端口0-5

* @param  GPIO_Pinx:设置的引脚0-32

* @param  BitVal:0-输入低电平,1-输出高电平

* @retval None

* @example GPIO_Write_Bit(GPIO0,1,1);//P0_1输出高电平*/voidGPIO_Write_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t BitVal)

{if(BitVal)

{

PORT_Table[GPIOx]->SET |= (1<

}else{

PORT_Table[GPIOx]->CLR |= (1<

}

}

#defineGPIO_BASES {LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4,LPC_GPIO5}//存储地址staticLPC_GPIO_TypeDef *constPORT_Table[] = GPIO_BASES;

这个呢我是利用的他自带的结构体实现的

LPC_GPIO_TypeDef

/*------------- General Purpose Input/Output (GPIO) --------------------------*//** @brief General Purpose Input/Output (GPIO) register structure definition*/typedefstruct{

__IO uint32_t DIR;

uint32_t RESERVED0[3];

__IO uint32_t MASK;

__IO uint32_t PIN;

__IO uint32_t SET;

__O  uint32_t CLR;

} LPC_GPIO_TypeDef;

原先的程序

#defineLPC_GPIO0            ((LPC_GPIO_TypeDef      *) LPC_GPIO0_BASE    )#defineLPC_GPIO1            ((LPC_GPIO_TypeDef      *) LPC_GPIO1_BASE    )#defineLPC_GPIO2            ((LPC_GPIO_TypeDef      *) LPC_GPIO2_BASE    )#defineLPC_GPIO3            ((LPC_GPIO_TypeDef      *) LPC_GPIO3_BASE    )#defineLPC_GPIO4            ((LPC_GPIO_TypeDef      *) LPC_GPIO4_BASE    )#defineLPC_GPIO5            ((LPC_GPIO_TypeDef      *) LPC_GPIO5_BASE    )

这样的话

如果把P0_12置一只需要

LPC_GPIO0->SET |= 1<<12;

我为了让前面这个LPC_GPIO0是个可变的,,,因为方便控制嘛

所以才有了

#defineGPIO_BASES {LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4,LPC_GPIO5}//存储地址staticLPC_GPIO_TypeDef *constPORT_Table[] = GPIO_BASES;

这样的话PORT_Table[0]正好是LPC_GPIO0 ,

PORT_Table[1]正好是LPC_GPIO1

这个函数就诞生了....

voidGPIO_Write_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx,uint8_t BitVal)

{if(BitVal)

{

PORT_Table[GPIOx]->SET |= (1<

}else{

PORT_Table[GPIOx]->CLR |= (1<

}

}

还有一个地方,我为了可以直接设置某些引脚的高低电平状态呢,,,,由于SET和CLR实现起来需要做判断,耽误时间,我看了下直接PIN就可以,所以就直接用的PIN

/**

* @brief  将数据写入指定的GPIO数据端口

* @param  GPIOx:设置的端口0-5

* @param  BitVal:指定端口的值写入输出数据寄存器

* @param

* @param

* @retval  None

* @example GPIO_Write_Bits(GPIO0,0xffffffff);//P0_0--P0_31输出高电平*/voidGPIO_Write_Bits(uint8_t GPIOx,uint32_t BitVal)

{

PORT_Table[GPIOx]->PIN =BitVal;

}

读取呢

/**

* @brief  读取指定引脚的电平状态--如果不先设置引脚方向,读出来一直是1

* @param  GPIOx:初始化的端口0-5

* @param  GPIO_Pinx:读取的引脚0-32

* @param

* @retval 1-状态高,0-状态低

* @example Value = GPIO_Read_Bit(GPIO0,1,1);//读取P0_1的电平状态*/uint8_t GPIO_Read_Bit(uint8_t GPIOx, uint32_t GPIO_Pinx)

{return((PORT_Table[GPIOx]->PIN >>GPIO_Pinx)&0x01);

}

/**

* @brief  读取整个端口的电平状态--如果不先设置引脚方向,读出来一直是1

* @param  GPIOx:初始化的端口0-5

* @param

* @param

* @retval bit=1--状态高,bit=0--状态低

* @example Value = GPIO_Read_Bits(GPIO0);//读取GPIO0的电平状态*/uint32_t GPIO_Read_Bits(uint8_t GPIOx)

{return(PORT_Table[GPIOx]->PIN);

}

其余的就没有什么说的了....可惜....我可能以后再也用不到了

工程呢为了方便,把Keil和IAR建到了一块,文件的.c和.h共用,,也是为了方便实用

对于程序的风格还是走的当年学操作系统时的代码风格,没说的,程序大了提高方便性

结束....老感觉伤感,,,,,,,,竟然写了一篇就写到头了

源码

链接:http://pan.baidu.com/s/1dE2X5uT密码:78ic

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容