看完了GPIO简单的寄存器,下面来看一个复杂的寄存器:GPIOx->CRL和GPIOx->CRH。为什么说这两个寄存器比较复杂呢,因为如果是自己配置寄存器的话会比较复杂。下面看看这两个寄存器器的介绍: CRH和CRL每一位的功能是相同的,只不过CRL控制的是每一个端口的引脚0~引脚7共8个引脚,CRH控制的是每一个端口的引脚8~引脚15共8个引脚。这样CRL,CRH才能控制一个端口的16个引脚。 从图中也可以看出,每一个引脚的模式的配置是需要4bit来配置的。这4bit中的高两位代表哪一种方式(输入还是输出),当时输出模式的时候,低两位代表输出的速度,当时输入模式的时候,低两位的作用不大, 并且只能设置成为00。这样看来,假设我们需要将某一个引脚设置成为浮空输入,那么着四位从高到底依次是0100 (这也正是上电复位后的状态)。相同的,如果是设置成为推挽输出呢?很显然,从高到低四位依次是00XX(XX是除了00的任何值). 这后面的XX代表的是三种不同的输出速度。 千帆初学的时候,使用V3.50的库文件来编程,当把一个引脚配置成为输入模式的时候,看见别人没有给他配置速度,很是不解。当看到了这个寄存器功能的时候,才恍然大悟。可是这样看着挺简单的,根据在之前代码架构的时候提出的函数设想,该如何实现带代码呢?在之前我们是这样来架构我们的代码的:
[cpp] view plaincopy
- typedef enum
- {
- AnalogIn=0x00,InFloating=0x04,IPD=0x28,IPU=0x48,
- OutOD=0x14,OutPP=0x10,AFOD=0x1C,AFPP=0x18
- }PinMode;
- typedef enum{Speed_10M=1,Speed_2M,Speed_50M} PinSpeed;
[cpp] view plaincopy
- void SetPinMode(const Pin pin,const PinMode mode,const PinSpeed speed=Speed_50M);//函数声明
这个SetPinMode函数的声明看起来怪怪的,前两个参数比较简单,一个是引脚,一个是模式,可是第三个后面有个=,这是什么意思呢?在刚开始的时候,千帆就和大家说过,在写代码的时候,后缀改成.cpp,以C++的方式编程。后面的第三个参数叫做默认参数,也就是说,当调用函数的时候,第三个参数可以写,也可以不写。如果写了一个新的参数,那么新的参数将覆盖这个Speed_50M ,如果不写的话,第三个参数默认就是Speed_50M。
下面来想一想这个函数应该怎样写: 1.根据引脚来判断是需要CRL还是需要使用CRH。如果PinNum(pin)>7,那么操作的就是CRH,否则是CRL; 2.将之前控制引脚的位擦出(清零)。比如说第二个引脚吧,那就将CRL的4~7位擦除; 3.根据Mode和Speed算出需要在引脚控制位的地方写入的4bit(比如说第二引脚需要设置成为推挽输出,50MHz,那么就将4~7位写入0011)。 下面是函数的具体实现,千帆写的稍微有点有点复杂。如果你有好的算法,希望能够告诉我,谢过啦;
[cpp] view plaincopy
- #define CNF_MODE_AIN 0X0 /*Andlog In*/
- #define CNF_MODE_INFLOATING 0X4 /*In Floating*/
- #define CNF_MODE_IP 0x8 /*IPD and IPU */
-
- void SetPinMode(const Pin pin,const PinMode mode,const PinSpeed speed)
- {
- OpenPinClock(pin);
- //add your code in there...
- Byte CNFandMODE=0x0;
- switch(mode)
- {
- case AnalogIn:
- SetPinMode_1(pin,CNF_MODE_AIN);
- return ;
-
- case InFloating:
- SetPinMode_1(pin,CNF_MODE_INFLOATING);
- return ;
-
- case IPD:
- SetPinMode_1(pin,CNF_MODE_IP);
- DigtalWrite(pin,0);
- return ;
-
- case IPU:
- SetPinMode_1(pin,CNF_MODE_IP);
- DigtalWrite(pin,1);
- return ;
-
- case OutPP:
- CNFandMODE=(0x0|speed);/* 00,speed*/
- SetPinMode_1(pin,CNFandMODE);
- return ;
-
- case OutOD:
- CNFandMODE=(0x4|speed);/*01,speed*/
- SetPinMode_1(pin,CNFandMODE);
- return ;
-
- case AFPP:
- CNFandMODE=(0x8|speed);/*10,speed*/
- SetPinMode_1(pin,CNFandMODE);
- return ;
-
- case AFOD:
- CNFandMODE=(0xC|speed);/*11,speed*/
- SetPinMode_1(pin,CNFandMODE);
- return ;
-
-
- }
-
-
- }
[cpp] view plaincopy
- void SetPinMode_1(const Pin pin,const Byte toWrite)
- {
- Byte num=PinNum(pin);
- Byte pos=(num<8?num:num-8)*4;//result:0,4,8,12,16,20,24,28
- DWord clearBits= ~(0xF<<pos);
-
- /**
- ***First:首先将CRL或者是CRH寄存器中影响pin的位清除
- **Second: 将toWrite指定的四个二进制位填充进刚刚清零的地方
- **/
- switch(PinPort(pin))
- {
- case PortA:
- if(num<8){//Op CRL
- GPIOA->CRL&=clearBits;
- GPIOA->CRL|=(toWrite<<pos);
- }
- else{//Op CRH
- GPIOA->CRH&=clearBits;
- GPIOA->CRH|=(toWrite<<pos);
- }
- break;
- case PortB:
- if(num<8){
- GPIOB->CRL&=clearBits;
- GPIOB->CRL|=(toWrite<<pos);
- }
- else{
- GPIOB->CRH&=clearBits;
- GPIOB->CRH|=(toWrite<<pos);
- }
- break;
- case PortC:
- if(num<8){
- GPIOC->CRL&=clearBits;
- GPIOC->CRL|=(toWrite<<pos);
- }
- else{
- GPIOC->CRH&=clearBits;
- GPIOC->CRH|=(toWrite<<pos);
- }
- break;
- case PortD:
- if(num<8){
- GPIOD->CRL&=clearBits;
- GPIOD->CRL|=(toWrite<<pos);
- }
- else{
- GPIOD->CRH&=clearBits;
- GPIOD->CRH|=(toWrite<<pos);
- }
- break;
- case PortE:
- if(num<8){
- GPIOE->CRL&=clearBits;
- GPIOE->CRL|=(toWrite<<pos);
- }
- else{
- GPIOE->CRH&=clearBits;
- GPIOE->CRH|=(toWrite<<pos);
- }
- break;
- }
- }
对这两段代码就不做过多的解释啦
|