在STM32中也可以像C51和AVR那样直接读取和操作I/O口。
其中,GPIOx->ODR几乎完全等价于C51中的Px和AVR中的PORTx,GPIOx->IDR则等价于AVR中的PINx(注:C51中读写I/O口都是用的Px寄存器)。唯一不同的是,Px和PORTx都是8位的寄存器,一次只能操作8个I/O口,而ODR和IDR都是16位的,一次可操作16个I/O口。
对于AVR中的DDRx寄存器(8位),STM32中也有类似的寄存器:CRL和CRH,这两个寄存器都是16位的,加起来就是32位,因此要比DDRx复杂很多。DDRx是每一位控制一个I/O口的输入输出方向,而CRL和CRH则是每4位控制一个I/O口的属性,包括输入输出方向,是否使用上拉电阻等等。并且,CRL控制Px0~Px7,CRH控制Px8~Px15。
不管工程是否引入了标准固件库,这几个寄存器都可以直接使用。当然,也可以用固件库中的相关函数代替。
【示例程序1:ODR寄存器的用法】
#include <stm32f10x.h>
#define _BV(n) (1 << (n))
#define BIT _BV
#define PORTB GPIOB->ODR // ODR寄存器完全等价于AVR中的PORTx寄存器
#define P1 PORTB // 同时也等价于C51中的P1寄存器
void delay()
{
uint32_t i;
for (i = 0; i < 400000; i++);
}
void init()
{
int i;
RCC->APB2ENR |= _BV(3); // 打开GPIOB的时钟
// 把PB8~15都设置为输出模式
// 这个相当于AVR中的DDRB,只不过操作起来更复杂一些
for (i = 0; i < 8; i++)
GPIOB->CRH |= _BV(4 * i + 1) | _BV(4 * i);
}
int main()
{
init();
PORTB = _BV(8); // 一开始只点亮PB8
delay();
while (1)
{
PORTB |= _BV(10); // 点亮PB10
delay();
PORTB &= ~_BV(10); // 熄灭PB10
delay();
PORTB |= _BV(12) | _BV(13); // 点亮PB12和PB13
delay();
PORTB &= ~(_BV(12) | _BV(13)); // 熄灭PB12和PB13
delay();
}
}
void SystemInit()
{
}