EFM32-笔记-IO操作

EFM32的IO叫做GPIO(GeneralPurposeInput/Output,通用输入输出接口),其他的功能先不研究,最起码的IO功能应该可以实现吧。

EFM32的GPIO每16个一组,这些组分别叫做A、B、C……,每一组分别叫做0、1、2……15,因此他们的IO口可以叫做PB0、PE3、PD11……。
对IO各个传感器进行设置或读取的时候,这些寄存器包括MODEL、MODEH、DIN、DOUT、DOUTSET、DOUTCLR、DOUTTGL等等,使用这样的方式:GPIO->P[4].DOUT=0x000C;
其中,P[4]代表PE。0为A,1为B,2为C,3为D,4为E……,DOUT表示对其DOUT寄存器进行设置或读取。有的寄存器需要32位的数据来表示或设置,有的需要的就比较少。比如MODEL就需要一个32位的数据,而DOUT只需要16位就够了。

每一个IO口的功能用一个四位来描述(0xF),具体含义见表。那么16个IO口,需要使用16×4=64位来表示,而EFM32是一个32位的处理器,因此处理器里面使用两个寄存器来处理这16个IO功能描述:GPIO_Px_MODEL和GPIO_Px_MODEH。GPIO_Px_MODEL来描述前8个IO口,GPIO_Px_MODEH来描述后8个IO口。因此在处理IO口模式的时候,要判断此IO口是前8个还是后8个,然后将描述数值写入对应的那个地方。
比如要写入PE2和PE3两个IO口为推挽式输出,对应描述数值为0x4。因为2和3对属于前8个IO口,因而应该用GPIO_Px_MODEL来写入,因此应该在GPIO->P[4].MODEL里面写入两个0x4,具体为0x4<<(2 * 4) + 0x4<< (3 * 4)。

对GPIO引脚的输出进行设置,可以使用三种方式:
1.直接写入GPIO_Px_DOUT寄存器,比如使得PE2和PE3输出为1,则为:GPIO->P[4].DOUT=0x000C;
 
 GPIO->P[4].DOUT共有16位,因此需要使用一个0xFFFF来表示
2.向GPIO_Px_DOUTSET的对应位上写1,就可以将该位设置为高电平。
3.向GPIO_Px_DOUTCLR的对应位上写1,就可以将该位设置为低电平。
4.向GPIO_Px_DOUTTGL的对应位上写1,就可以将该位的电平反转。
对GPIO_Px_DOUT进行读取,就可以获取各个位的电平信息,因此可以使用GPIO->P[4].DOUT^=0x000C;来反转PE2和PE3两个IO的电平,不过还是建议用方法4来反转电平,因为速度更快;而对GPIO_Px_DOUTSET、GPIO_Px_DOUTCLR、GPIO_Px_DOUTTGL读取,始终读到的都是0。

GPIO_Px_DIN寄存器。无论该IO口被设置为输入还是输出,读取DIN寄存器,都可以得到该IO口当前的电平状态。系统之使用DIN寄存器的前16位,因为每一个Px只有16个IO口。

GPIO_Px_MODEL, GPIO_Px_MODEH, GPIO_Px_CTRL,GPIO_Px_PINLOCKN,GPIO_EXTIPSELL,GPIO_EXTIPSELH,GPIO_INSENSE  andGPIO_ROUTE这些寄存器都可以锁定,只需要向GPIO_LOCK寄存器写入不等于0xA534的数。如果向GPIO_LOCK写入0xA534,将会解锁。
对于每一组的每一个IO口的这些这些寄存器,都可以单独的锁定,只需要将GPIO_Px_PINLOCKN(16位配置有效)相应的位写0即可。在系统启动的时候,这些位都被置1,也就是每一组的GPIO_Px_PINLOCKN均为0xffff。

另外对GPIO操作之前,要首先使能它的时钟。GPIO使用的HFPERCLK,它本身在reset的时候默认为使能状态的(也可以在后期关闭,以进一步节省能耗)。还要在HFPERCLKEN0的相关位进行设置,使得GPIO能够使用HFPERCLK,也就是他的第13位,具体为0x2000的位置。然后就可以对GPIO进行各方面的操作。在操作完成之后,如果确定不再使用GPIO的功能可以清空该位,如果在某些特殊的应用里面,确定不使用例如AD、DA、timer、uart等常见功能的话,可以进一步关闭HFPERCLK(HFPERCLKDIV寄存器的第8位清零),以节省更多的电量。
对这些CMU寄存器进行操作的时候,使用语句形如:CMU->HFPERCLKEN0 =0x2000;


[疑问]在对GPIO控制之前,需要首先设定相应的时钟,即前面要加入CMU_ClockEnable(cmuClock_HFPER,true);CMU_ClockEnable(cmuClock_GPIO,true);这两行。实际上只添加第二行即可。这让我感到迷茫。对于IO操作的时候,难道IO口还要加入时钟的支持(虽然数据手册上说:高频外设时钟有HFCLK分频得到,用来驱动高频外设,如GPIO、ADC等)。难道GPIO电平的设置以及反转都需要该时钟的支持?
经过试验查看确实是这样的,在没有加入CMU_ClockEnable(cmuClock_GPIO,true);这句话时,对IO口所有的操作都没有发生作用,即使主程序已经执行了对IO口的操作,IO口的那些寄存器(MODEL等)都没有发生改变,甚至是PINLOCKN都处在0的状态(锁定)。这说明外部高频时钟没有起作用的时候,IO根本就没有进行初始化。
然后我试验了这样的操作,也就是先对IO口进行操作,然后在打开外部高频时钟,发现时钟被打开后,IO口进行了初始化(PINLOCKN已经变成了0xffff),但是原来对IO口进行的所有的操作语句都没有起作用。这说明所有对GPIO进行的操作都必须在外部高频时钟下进行。

你可能感兴趣的:(EFM32学习笔记)