在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()
{
}