STM32库开发实战指南-M4:13- GPIO—位带操作

上传人:野鹰 文档编号:2567631 上传时间:2017-07-25 格式:PDF 页数:5 大小:238.34KB
返回 下载 相关 举报
STM32库开发实战指南-M4:13- GPIO—位带操作_第1页
第1页 / 共5页
STM32库开发实战指南-M4:13- GPIO—位带操作_第2页
第2页 / 共5页
STM32库开发实战指南-M4:13- GPIO—位带操作_第3页
第3页 / 共5页
STM32库开发实战指南-M4:13- GPIO—位带操作_第4页
第4页 / 共5页
STM32库开发实战指南-M4:13- GPIO—位带操作_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《STM32库开发实战指南-M4:13- GPIO—位带操作》由会员分享,可在线阅读,更多相关《STM32库开发实战指南-M4:13- GPIO—位带操作(5页珍藏版)》请在金锄头文库上搜索。

1、零死角玩转STM32F429第110页共996第13章GPIO位带操作本章参考资料:STM32F4xx中文参考手册存储器和总线构架章节、GPIO章节,Cortex-M4内核编程手册2.2.5Bit-banding。学习本章时,配套这些参考资料学习效果会更佳。13.1位带简介位操作就是可以单独的对一个比特位读和写,这个在51单片机中非常常见。51单片机中通过关键字sbit来实现位定义,F429中没有这样的关键字,而是通过访问位带别名区来实现。在F429中,有两个地方实现了位带,一个是SRAM区的最低1MB空间,另一个是外设区最低1MB空间。这两个1MB的空间除了可以像正常的RAM一样操作外,他们

2、还有自己的位带别名区,位带别名区把这1MB的空间的每一个位膨胀成一个32位的字,当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的。图13-1 F429位带地址13.1.1外设位带区外设位带区的地址为:0X400000000X400F0000,大小为1MB,这1MB的大小包含了APB1/2和AHB1上所以外设的寄存器,AHB2/3总线上的寄存器没有包括。AHB2总线上的外设地址范围为:0X500000000X50060BFF,AHB3总线上的外设地址范围为:零死角玩转STM32F429第111页共9960XA00000000XA0000FFF。外设位带区经过膨胀后的位带别名区地址

3、为:0X420000000X43FFFFFF,这部分地址空间为保留地址,没有跟任何的外设地址重合。13.1.2 SRAM位带区SRAM的位带区的地址为:0X20000000X200F0000,大小为1MB,经过膨胀后的位带别名区地址为:0X220000000X23FFFFFF,大小为32MB。操作SRAM的比特位这个用得很少。13.1.3位带区和位带别名区地址转换位带区的一个比特位经过膨胀之后,虽然变大到4个字节,但是还是LSB才有效。有人会问这不是浪费空间吗,要知道F429的系统总线是32位的,按照4个字节访问的时候是最快的,所以膨胀成4个字节来访问是最高效的。我们可以通过指针的形式访问位带

4、别名区地址从而达到操作位带区比特位的效果。那这两个地址直接如何转换,我们简单介绍一下。1.外设位带别名区地址对于片上外设位带区的某个比特,记它所在字节的地址为A,位序号为n(0=n=7),则该比特在别名区的地址为:1AliasAddr=0x42000000+(A-0x40000000)*8*4+n*40X42000000是外设位带别名区的起始地址,0x40000000是外设位带区的起始地址,(A-0x40000000)表示该比特前面有多少个字节,一个字节有8位,所以*8,一个位膨胀后是4个字节,所以*4,n表示该比特在A地址的序号,因为一个位经过膨胀后是四个字节,所以也*4。2. SRAM位带

5、别名区地址对于SRAM位带区的某个比特,记它所在字节的地址为A,位序号为n(0=n=7),则该比特在别名区的地址为:1AliasAddr=0x22000000+(A-0x20000000)*8*4+n*4公式分析同上。3.统一公式为了方便操作,我们可以把这两个公式合并成一个公式,把“位带地址+位序号”转换成别名区地址统一成一个宏。1/把“位带地址+位序号”转换成别名地址的宏零死角玩转STM32F429第112页共9962#defineBITBAND(addr,bitnum)(addr&0xF0000000)+0x02000000+(addr&0x000FFFFF)5)+(bitnum2)add

6、r& 0xF0000000是为了区别SRAM还是外设,实际效果就是取出4或者2,如果是外设,则取出的是4,+0X02000000之后就等于0X42000000,0X42000000是外设别名区的起始地址。如果是SRAM,则取出的是2,+0X02000000之后就等于0X22000000,0X22000000是SRAM别名区的起始地址。addr& 0x00FFFFFF屏蔽了高三位,相当于减去0X20000000或者0X40000000,但是为什么是屏蔽高三位?因为外设的最高地址是:0X20100000,跟起始地址0X20000000相减的时候,总是低5位才有效,所以干脆就把高三位屏蔽掉来达到减去

7、起始地址的效果,具体屏蔽掉多少位跟最高地址有关。SRAM同理分析即可。5相当于*8*4,2相当于*4,这两个我们在上面分析过。最后我们就可以通过指针的形式操作这些位带别名区地址,最终实现位带区的比特位操作。1/把一个地址转换成一个指针2#defineMEM_ADDR(addr)*(volatileunsignedlong*)(addr)34/把位带别名区地址转换成指针5#defineBIT_ADDR(addr,bitnum)MEM_ADDR(BITBAND(addr,bitnum)13.2 GPIO位带操作外设的位带区,覆盖了全部的片上外设的寄存器,我们可以通过宏为每个寄存器的位都定义一个位带

8、别名地址,从而实现位操作。但这个在实际项目中不是很现实,也很少人会这么做,我们在这里仅仅演示下GPIO中ODR和IDR这两个寄存器的位操作。从手册中我们可以知道ODR和IDR这两个寄存器对应GPIO基址的偏移是20和16,我们先实现这两个寄存器的地址映射,其中GPIOx_BASE在库函数里面有定义。1. GPIO寄存器映射代码9 GPIO ODR和IDR寄存器映射1/GPIOODR和IDR寄存器地址映射2#defineGPIOA_ODR_Addr(GPIOA_BASE+20)3#defineGPIOB_ODR_Addr(GPIOB_BASE+20)4#defineGPIOC_ODR_Addr(

9、GPIOC_BASE+20)5#defineGPIOD_ODR_Addr(GPIOD_BASE+20)6#defineGPIOE_ODR_Addr(GPIOE_BASE+20)7#defineGPIOF_ODR_Addr(GPIOF_BASE+20)8#defineGPIOG_ODR_Addr(GPIOG_BASE+20)9#defineGPIOH_ODR_Addr(GPIOH_BASE+20)10#defineGPIOI_ODR_Addr(GPIOI_BASE+20)11#defineGPIOJ_ODR_Addr(GPIOJ_BASE+20)12#defineGPIOK_ODR_Addr(G

10、PIOK_BASE+20)1314#defineGPIOA_IDR_Addr(GPIOA_BASE+16)15#defineGPIOB_IDR_Addr(GPIOB_BASE+16)16#defineGPIOC_IDR_Addr(GPIOC_BASE+16)17#defineGPIOD_IDR_Addr(GPIOD_BASE+16)18#defineGPIOE_IDR_Addr(GPIOE_BASE+16)19#defineGPIOF_IDR_Addr(GPIOF_BASE+16)20#defineGPIOG_IDR_Addr(GPIOG_BASE+16)21#defineGPIOH_IDR_

11、Addr(GPIOH_BASE+16)零死角玩转STM32F429第113页共99622#defineGPIOI_IDR_Addr(GPIOI_BASE+16)23#defineGPIOJ_IDR_Addr(GPIOJ_BASE+16)24#defineGPIOK_IDR_Addr(GPIOK_BASE+16)现在我们就可以用位操作的方法来控制GPIO的输入和输出了,其中宏参数n表示具体是哪一个IO口,n(0,1,2.16)。这里面包含了端口AK,并不是每个单片机型号都有这么多端口,使用这部分代码时,要查看你的单片机型号,如果是176pin的则最多只能使用到I端口。2. GPIO位操作代码10

12、 GPIO输入输出位操作1/单独操作GPIO的某一个IO口,n(0,1,2.16),n表示具体是哪一个IO口2#definePAout(n)BIT_ADDR(GPIOA_ODR_Addr,n)/输出3#definePAin(n)BIT_ADDR(GPIOA_IDR_Addr,n)/输入45#definePBout(n)BIT_ADDR(GPIOB_ODR_Addr,n)/输出6#definePBin(n)BIT_ADDR(GPIOB_IDR_Addr,n)/输入78#definePCout(n)BIT_ADDR(GPIOC_ODR_Addr,n)/输出9#definePCin(n)BIT_AD

13、DR(GPIOC_IDR_Addr,n)/输入1011#definePDout(n)BIT_ADDR(GPIOD_ODR_Addr,n)/输出12#definePDin(n)BIT_ADDR(GPIOD_IDR_Addr,n)/输入1314#definePEout(n)BIT_ADDR(GPIOE_ODR_Addr,n)/输出15#definePEin(n)BIT_ADDR(GPIOE_IDR_Addr,n)/输入1617#definePFout(n)BIT_ADDR(GPIOF_ODR_Addr,n)/输出18#definePFin(n)BIT_ADDR(GPIOF_IDR_Addr,n)/

14、输入1920#definePGout(n)BIT_ADDR(GPIOG_ODR_Addr,n)/输出21#definePGin(n)BIT_ADDR(GPIOG_IDR_Addr,n)/输入2223#definePHout(n)BIT_ADDR(GPIOH_ODR_Addr,n)/输出24#definePHin(n)BIT_ADDR(GPIOH_IDR_Addr,n)/输入2526#definePIout(n)BIT_ADDR(GPIOI_ODR_Addr,n)/输出27#definePIin(n)BIT_ADDR(GPIOI_IDR_Addr,n)/输入2829#definePJout(n)

15、BIT_ADDR(GPIOJ_ODR_Addr,n)/输出30#definePJin(n)BIT_ADDR(GPIOJ_IDR_Addr,n)/输入3132#definePKout(n)BIT_ADDR(GPIOK_ODR_Addr,n)/输出33#definePKin(n)BIT_ADDR(GPIOK_IDR_Addr,n)/输入3.主函数该工程我们直接从LED-库函数操作移植过来,有关LEDGPIO初始化和软件延时等函数我们直接用,修改的是控制GPIO输出的部分改成了位操作。该实验我们让相应的IO口输出高低电平来控制LED的亮灭,负逻辑点亮。具体使用哪一个IO和点亮方式由硬件平台决定。代码11 main函数零死角玩转STM32F429第114页共9961intmain(void)23/*LED端口初始化*/4LED_GPIO_Config();56while(1)7/PH10=0,点亮LED8PHout(10)=0;9SOFT_Delay(0x0FFFFF);1011/PH10=1,熄灭LED12PHout(10)=1;13SOFT_Delay(0x0FFFFF);14151613.3每课一问1、利用位带操作的方法,写一个GPIO输入的例程,比如按键采集。2、如果使用的不是GPIO这个外设,而是其他的外设,那么公式该怎么改,比如要使用的外设是ADC。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号