学习正点原子开发板,发现点亮LED个程序并没有讲解的特别详细。我只看了驱动开发指南,不知道是别的文档讲过还是说后面有更好的实现方法,这个程序只是入门。不过既然是学习就仔细一点,至少把不明白的程序搞懂。其实对于初学者这个程序最难的应该是时钟树,我是迷糊了好久。stm32为了降低功耗和提供更大的外设设置灵活度,将时钟的配置完全交给了使用者,提升功能强度也提高了上手的门槛。但是系统时钟和总线时钟存在默认状态,可以不配置。而外设时钟默认全部是关闭状态,必须进行配置。
首先,手册上已经写了外设的起始地址为0x40000000
而时钟和IO都在在AHB4上,地址是0x50000000
RCC的地址是0x50000000,GPIOI的地址是0x5000A000
AHB4的时钟在RCC+0xA28的位置
GPIOI的时钟在第八位
GPIO的寄存器功能介绍
接下来看程序:
void led_switch(u8 sta)
{
u32 val = 0;
if(sta == LEDON) {
val = readl(GPIOI_BSRR_PI);
val |= (1 << 16);
writel(val, GPIOI_BSRR_PI);
}else if(sta == LEDOFF) {
val = readl(GPIOI_BSRR_PI);
val|= (1 << 0);
writel(val, GPIOI_BSRR_PI);
}
}
很好理解,读BSRR寄存器,在0位或16位写入1
BBSR是置位复位寄存器,写入高16位是输出低电平,写入低16位是输出高电平。这个寄存器实际是只写的,读只有0x0000。例程应该是为了统一规范
/* 2、使能PI时钟 */
val = readl(MPU_AHB4_PERIPH_RCC_PI);
val &= ~(0X1 << 8); /* 清除以前的设置 */
val |= (0X1 << 8); /* 设置新值 */
writel(val, MPU_AHB4_PERIPH_RCC_PI);
/* 3、设置PI0通用的输出模式。*/
val = readl(GPIOI_MODER_PI);
val &= ~(0X3 << 0); /* bit0:1清零 */
val |= (0X1 << 0); /* bit0:1设置01 */
writel(val, GPIOI_MODER_PI);
/* 3、设置PI0为推挽模式。*/
val = readl(GPIOI_OTYPER_PI);
val &= ~(0X1 << 0); /* bit0清零,设置为上拉*/
writel(val, GPIOI_OTYPER_PI);
/* 4、设置PI0为高速。*/
val = readl(GPIOI_OSPEEDR_PI);
val &= ~(0X3 << 0); /* bit0:1 清零 */
val |= (0x2 << 0); /* bit0:1 设置为10*/
writel(val, GPIOI_OSPEEDR_PI);
/* 5、设置PI0为上拉。*/
val = readl(GPIOI_PUPDR_PI);
val &= ~(0X3 << 0); /* bit0:1 清零*/
val |= (0x1 << 0); /*bit0:1 设置为01*/
writel(val,GPIOI_PUPDR_PI);
/* 6、默认关闭LED */
val = readl(GPIOI_BSRR_PI);
val |= (0x1 << 0);
writel(val, GPIOI_BSRR_PI);
(2)、能时钟。前面看了GPIOI在第八位
(3)、MODER的最后两位设为01.这个寄存器是设置IO的模式,最后两位是pin0,01是普通IO输出
(4)、OTYPER 的最后一位设置为0,这个寄存器是设置输出类型。只有低16位有效,对应不同的IO口。设为0是推挽模式
(5)、OSPEEDR 的最后两位设置为01,这个寄存器是设置IO口的输出速度。最后两位是pin0,10是高速。这个速度没测过是什么,网上说是翻转速度。
(6)、PUPDR 的最后两位设置为01,这个寄存器决定输出的是上拉还是下拉,也就是IO的默认电平。最后两位是pin0,01是上拉。我只知道输入上拉,这个输出上拉我是没搞懂,感觉应该是默认输出高电平吧