(由于第一次在自带的浏览器写,结果在粘贴代码时网页卡死,没有保存。。。所以没了。。。这是第二次写,所以介绍简略了许多)
目的:通过对寄存器的操作,点亮LED;
参考文档:国信长天嵌入式竞赛平台原理图,stm32f103rbt6 ,
STM32中文参考手册_V10,Cortex-M3权威指南(中文)
通过对文档的翻阅,我们知道了LED1-8使用的是开发板的PC8-15;即GPIO的C端口的第8-15位;
其中,外设基地址是0x40000000;APB2的偏移地址是0x10000,GPIO接口都挂接在APB2总线上;
GPIOC的偏移地址是0x1000,保存着操作GPIO口的一些寄存器;
端口配置低寄存器GPIOC_CRL的偏移是0x00;端口配置高寄存器GPIOC_CRH的偏移是0x04,用来配置IO模式,俩个寄存器共64位,每4位可以配置一个IO位线的模式,可以配置0-15共16根位线;
GPIOC_ODR的偏移是0x0C;用来输出数据,通过实验发现,输出0可以使LED点亮,而ODR复位设置是0x00000000;所以,如果想要使某一个LED点亮,需要先全部置1,然后使用位运算;或者直接用立即数赋值。
我们发现,即使这样,仍然不能点亮LED,这是因为,APB2挂接在AHB,AHB基地址一般认为是0x40020000,AHB上有RCC时钟,其中APB2 外设时钟使能寄存器(RCC_APB2ENR)的偏移是0x18;复位是0x00000000;所以需要对GPIO的C端口的时钟打开,如图,需要将第4位置1,
代码如下:
一种是直接操作寄存器地址,另一种是通过寄存器映射来实现;
void SystemInit()
{
}
#if 0
//直接操作地址
int main()
{
//打开GPIOC的时钟
*(unsigned int *)0x40021018 |=((1)<<4);
//配置IO口为输出
*(unsigned int *)0x40011004 =0x11111111;
//控制ODR寄存器
*(unsigned int *)0x4001100C =0xFEFF;
}
void SystemInit()
{
}
#endif
//使用寄存器映射
//外设
#define PERIPH_BASE ((unsigned int)0x40000000)
//总线
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE+0X10000)
#define AHBPERIPH_BASE (PERIPH_BASE+0X20000)
//寄存器组
#define RCC_BASE (AHBPERIPH_BASE+0X1000)
#define GPIOC_BASE (APB2PERIPH_BASE+0X1000)
//寄存器
#define RCC_APB2ENR *(unsigned int *)(RCC_BASE+0X18)
#define GPIOC_CRL *(unsigned int *)(GPIOC_BASE+0X00)
#define GPIOC_CRH *(unsigned int *)(GPIOC_BASE+0X04)
#define GPIOC_ODR *(unsigned int *)(GPIOC_BASE+0X0C)
int main()
{
//打开GPIOC的时钟
RCC_APB2ENR |=((1)<<4);
//配置IO口为输出
GPIOC_CRH =0x11111111;
//控制ODR寄存器
GPIOC_ODR =0xFEFF;
}