@乔木 发表于 2017-8-21 19:56:25

【JESSE】STM32初学(寄存器版)——GPIO操作[1]

可能有些朋友在别的论坛看到我发过类似的帖子,但这并不是一个帖子发多个论坛,因为某些原因,那个论坛我并不打算继续更帖;而是借着STM32社区这个平台继续完成。

在学校学习期间,曾遇到很多问题,有幸遇到了一些老师和朋友为我解答。现在看到一些学弟学习STM32的时候感觉很困难,遂在此写下个人浅显的见解,希望在他们遇到困难的时候能帮上一点忙。
如果大家发现有错误,希望大家能够指出,别让我误导大家了,哈哈。
我对STM32也并不精通,在这一过程中大家一起学习。
说说为什么用寄存器,现在有大量工具帮助大家建立工程,生成初始化代码,但是个人感觉学单片机这类东西还是要了解一下它的大致结构的,反正我不习惯用CubeMX这一类工具,这类工具让我觉得像是站在棉花上,没有脚踏实地的感觉,虚虚的。

大部分人写的第一个程序应该是“hello world”,第一个单片机程序应该是“点亮LED”,那我们就继续这种老套路。
我们先点个灯。
先说下,平台是STM32F469DIS板卡。

看看原理图中有关LED那部分图中LED1—LED4分别是接在PG6、PD4、PD5、PK3引脚上,我们先点亮LED2试试。贴出代码:    /*
      开启GPIOD的时钟
    */
    RCC->AHB1ENR      |=0x01<<3;
    /*
      将GPIOD->MODER寄存器中PIN4对应的位清零
    (在这里,这一步其实可以省略,单片机复位之后便是0)
      并不是所有端口复位之后都是清零的
    */
    GPIOD->MODER      &=~(0x03<<(2*4));
    /*
      将GPIOD->PIN4设置为输出模式
    */
    GPIOD->MODER      |=0x01<<(2*4);
    /*
      设置输出速度为中速(25MHz)
    */
    GPIOD->OSPEEDR |=0x01<<(2*4);
    /*
      设置输出类型为通用推挽输出
    */
    GPIOD->OTYPER&=~(0x01<<4);
    /*
      设置引脚输出低电平
    */
    GPIOD->ODR   &=~(0x01<<4);
RCC->AHB1ENR       |=0x01<<3;   这条语句是开启GPIOD这个端口的时钟,STM32(其实不只是STM32)为了降低功耗,将外设的驱动时钟层层细化,并且可以单独控制,大部分外设的时钟默认是关闭的,所以我们如果要这个外设工作,第一件事便是打开它的驱动时钟。这张图便是STM32的时钟树,可能现在看起来有点懵逼,但是随着深入之后慢慢就理解了。为什么是操作AHB1总线上的寄存器呢,我们看下面这张图这张图清晰的描述了部分外设的地址分布,GPIO端口正是挂载在AHB1总线上;所以,我们要操作GPIO外设就要配置AHB1中控制GPIO外设的寄存器,哪个寄存器呢,当然是使能寄存器寄存器第三位便是GPIOD端口时钟的使能位,我们往里面写入1即可。所以RCC->AHB1ENR |= 0x01<<3; 这条语句便是将AHB1ENR寄存器中的值先读出来,再在第三位(相对于第零位)上或上1,再写回去。
打开了GPIOD端口的时钟,我们再配置好GPIOD的相应寄存器,相应引脚便可以输出高低电平了。这就列出了GPIO的寄存器我们并不需要配置所有的寄存器,可以视情况而定,有些寄存器可以保持它复位后的状态即可。这里没有用上的寄存器或是对某些寄存器功能仍有疑惑,可以查看参考手册第7章通用IO

GPIOD->MODER   &=~(0x03<<(2*4));GPIOD->MODER   |=0x01<<(2*4);MODER寄存器两个位控制了一个引脚,我们先将PD4对应的MODER寄存器清零(清零是为了防止运行这段代码之前对相应位进行了操作),MODERx中x便是标识这个位控制的第几个引脚;GPIOD->MODER   &=~(0x03<<(2*4));清零之后,我们需要将其设置成相应模式,图中可以看到01是通用输出模式。
GPIOD->MODER      |=0x01<<(2*4);

GPIOD->OSPEEDR |=0x01<<(2*4);这句是设置引脚输出速度。没有清零是因为在这之前并没有对相应位进行操作,复位值便是‘00’,我们将其设置为了‘01’中速模式(25MHz);
GPIOD->OTYPER   &=~(0x01<<4);这句便是只清零,没有置位,是因为我们保持‘0’即可,即下图所示的推挽模式。
我们并没有将GPIOD对应的寄存器全部配置一遍,因为有些寄存器在这个程序中并没有用上,像AFR寄存器、IDR寄存器。
配置完这些之后,PD4这个引脚基本就可以使用了GPIOD->ODR   &=~(0x01<<4);我们往ODR寄存器中的相应位置为0,LED灯就亮了。为什么是写‘0’亮LED?逻辑有些颠倒。写‘0’,引脚输出低电平,根据原理图可知,只有引脚输出低电平LED才能导通。

配个效果图

最终的代码我做了一些修改,但是应该能看懂(有同学说看不懂我的代码,嗯~~我要面壁反思一下)





lspring 发表于 2019-2-9 17:05:33

你这里面的语法怎么我看不懂呢?怎么用&和|这样的符号在中间

二子 发表于 2018-10-3 22:41:23

楼主做的事情非常有意义
对于初学者理解掌握STM32编程很有好处

@乔木 发表于 2017-8-21 20:24:33

zero99 发表于 2017-8-21 20:18
过来支持一下啦

:'(怎么也给个评分吧

zero99 发表于 2017-8-21 20:18:39

过来支持一下啦 :loveliness:

andey 发表于 2017-8-21 22:22:03

@乔木 发表于 2017-8-21 22:34:37

andeyqi 发表于 2017-8-21 22:22
谢谢分享

互相学习:)

epochal 发表于 2017-8-22 07:24:13

学习了!

@乔木 发表于 2017-8-22 07:55:16

epochal 发表于 2017-8-22 07:24
学习了!

你们都是大神

乖乖妮 发表于 2017-8-22 08:43:18

@乔木 发表于 2017-8-21 20:24
怎么也给个评分吧

等着你继续更呢;P

@乔木 发表于 2017-8-22 08:48:50

乖乖妮 发表于 2017-8-22 08:43
等着你继续更呢

慢慢来嘛

freeelectron 发表于 2017-8-22 08:53:47

板子不错:lol:lol:lol:lol:lol

@乔木 发表于 2017-8-22 09:09:36

freeelectron 发表于 2017-8-22 08:53
板子不错

噗~~~~~

zero99 发表于 2017-8-22 15:48:58

@乔木 发表于 2017-8-22 08:48
慢慢来嘛

下期在什么时候啊,透露下

@乔木 发表于 2017-8-22 16:38:13

zero99 发表于 2017-8-22 15:48
下期在什么时候啊,透露下

今晚:)

feixiang20 发表于 2018-9-5 23:56:59

谢谢分享,来看看
页: [1] 2
查看完整版本: 【JESSE】STM32初学(寄存器版)——GPIO操作[1]