Open Drain (漏极开路)与 push-pull(推挽) 介绍
Open Drain 输出为开路,使用时须加上上拉电阻,输出电压由外部决定。

IDE中的GPIO设定介绍
在STM32CubbeIDE中要设定GPIO相对来的容易~一样点开.ioc档可以去对各个脚位去做设定。
在这边我将PB4-PB8设定为GPIO_Output,首先点选PB4将它设为GPIO_Output,其余的脚位同样设定。
接下来点击左侧的SystemCore当中的GPIO再点选脚位,可以设定GPIO的相关功能。这边介绍一下下方选项的代表意思。

当设定完成后记得按下Ctrl+S来储存刚刚所做的设定,这时IDE会自动生成相关的GPIO函数。
GPIO相关函数介绍与暂存器
在透过上方.ioc档中设定完成后除了相关GPIO函数IDE会自动设定完成外,GPIO的暂存器也会配置好。在STM32当中GPIO有6个暂存器CRL、CRH、IDR、ODR、BRSS、BRR,CRL与CRH主要用来表示GPIO的状态一共有32bit,这部分会由IDE设置好。
CRL/CRH Register :CRL控制低8位元 CRH则负责控制高8位元
IDR Register:主要控制IO的输入电位情形,一共有32bit但这边只使用了低16位,高16位保留。要注意的是这个暂存器只能读而已~
ODR Register: 主要为控制IO输出电位情形,同样一共有32bit只使用低16位,对这个暂存器写可以直接控制GPIO输出状况。(在这里使用左移的方式会改变暂存器当中所有的值,与BSRR不同的是假设 1<<1 会变成00000011,而ODR则会变成00000010)
BSRR Register:用来做完IO位设置或是清除的暂存器,简单来说就是用来设置GPIO输出位是1还是0。如果想如果设置GPIOA_1的值为1,则要对BSRR低16位写入即可。
GPIOA->BSRR = 1<<1; //00000001 << 1 = 00000010
同样的如果想要设置GPIOA_1为0,则往高16位写入1即可。
GPIOA->BSRR = 1 << (16+1) //00000001 经过左移16+1位后会在bit17
BRR Register:为GPIO清除Register,作用跟上方BSRR的高16位元类似。
上方所说的是直接透过暂存器对GPIO去做操作,那有没有更好用的方法?当然有!接下来要介绍的是HAL库,可以在左侧专案面板当中的Drivers当中STM32xxxxx_HAL_Driver中找到,里面有各式HAL库所提供的函数!那要怎么使用HAL库所提供的函数去控制GPIO脚位呢?这边先介绍几个函数~
1. HAL_GPIO_WritePin这函数用来设置脚位是1 or 0
HAL_GPIO_WritePin(GPIOx, GPIO_Pin, PinState);
函数应用
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET); //将脚位设定为高电位HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET); //将脚位设定为低电位
2. HAL_GPIO_ReadPin这函数用来读取脚位是1 or 0
HAL_GPIO_ReadPin(GPIOx, GPIO_Pin);
函数应用
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5); //读取GPIOA_5
3. HAL_GPIO_TogglePin这函数可以理解为相反输出 也就是说假设原先设定为1则下次会输出0,每一次的输出都与现在输出相反。
HAL_GPIO_TogglePin(GPIOx, GPIO_Pin);
函数应用
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);//与当前输出相反
接下来另外介绍一个Delay函数,单位为毫秒。
4. HAL_Delay
HAL_Delay(1000);//1000ms = 1s
上面所介绍的函数可以相互组合来控制LED灯的明亮变化~
首先可以先查询一下Datasheet,我这块板子为L746RG在当中有写到板载LED灯LD2脚位为PA5,我们可以利用WritePin与ReadPin去对他读取值。
while(1){HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);State = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);HAL_Delay(500); //0.5sHAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);State = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);HAL_Delay(500); //0.5s}
记得要在全域变数的位置宣告State,接着在编译后可以在现场表达式当中输入State就可以看到PA5的变化~
接下来介绍另外一种控制方式,透过上面所说的暂存器去控制GPIO的变化!
GPIO的设定照上方的PB4-PB8去做设定,皆为Output!
透过BSRR去将脚位输出设为1,接着透过BRR去将脚位清0,一样可以实现跑马灯的效果!
如果手边没有多余的LED的话可以透过像下方设定全域变数PB_1-PB_5的方式,接着透过现场表达式来观看输出的变化!
while(1){int i; for(i=0;i<5;i++) { GPIOB->BSRR = (16<<i); HAL_Delay(1000); PB_1 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4); PB_2 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5); PB_3 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6); PB_4 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7); PB_5 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8); } for(i=0;i<5;i++) { GPIOB->BRR = (16<<i); HAL_Delay(1000); PB_1 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4); PB_2 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5); PB_3 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6); PB_4 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7); PB_5 = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8); }}
上方程式码当中可以看到GPIOB→BSRR = (16<<i),16的计算方式可以对应上方BSRR暂存器来看,16转二进位表示方式为00010000,对应到暂存器可以看到1的位置刚好是PB4,透过左移的方式可以陆续将PB5-8也设为1,BRR也是同理!