你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
@乔木 提问时间:2017-8-21 19:56 /
可能有些朋友在别的论坛看到我发过类似的帖子,但这并不是一个帖子发多个论坛,因为某些原因,那个论坛我并不打算继续更帖;而是借着STM32社区这个平台继续完成。

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

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

看看原理图中有关LED那部分
led.PNG
图中LED1—LED4分别是接在PG6PD4PD5PK3引脚上,我们先点亮LED2试试。
贴出代码:
  1.     /*
  2.         开启GPIOD的时钟
  3.     */
  4.     RCC->AHB1ENR      |=  0x01<<3;
  5.     /*
  6.         将GPIOD->MODER寄存器中PIN4对应的位清零
  7.     (在这里,这一步其实可以省略,单片机复位之后便是0)
  8.         并不是所有端口复位之后都是清零的
  9.     */
  10.     GPIOD->MODER      &=~(0x03<<(2*4));
  11.     /*
  12.         将GPIOD->PIN4设置为输出模式
  13.     */
  14.     GPIOD->MODER      |=  0x01<<(2*4);
  15.     /*
  16.         设置输出速度为中速(25MHz)
  17.     */
  18.     GPIOD->OSPEEDR |=  0x01<<(2*4);
  19.     /*
  20.         设置输出类型为通用推挽输出
  21.     */
  22.     GPIOD->OTYPER  &=~(0x01<<4);
  23.     /*
  24.         设置引脚输出低电平
  25.     */
  26.     GPIOD->ODR     &=~(0x01<<4);
复制代码

RCC->AHB1ENR       |=  0x01<<3;   
这条语句是开启GPIOD这个端口的时钟,STM32(其实不只是STM32)为了降低功耗,将外设的驱动时钟层层细化,并且可以单独控制,大部分外设的时钟默认是关闭的,所以我们如果要这个外设工作,第一件事便是打开它的驱动时钟。
2.PNG
这张图便是STM32的时钟树,可能现在看起来有点懵逼,但是随着深入之后慢慢就理解了。
为什么是操作AHB1总线上的寄存器呢,我们看下面这张图
3.PNG
这张图清晰的描述了部分外设的地址分布,GPIO端口正是挂载在AHB1总线上;所以,我们要操作GPIO外设就要配置AHB1中控制GPIO外设的寄存器,哪个寄存器呢,当然是使能寄存器
4.PNG
寄存器第三位便是GPIOD端口时钟的使能位,我们往里面写入1即可。
所以RCC->AHB1ENR |= 0x01<<3; 这条语句便是将AHB1ENR寄存器中的值先读出来,再在第三位(相对于第零位)上或上1,再写回去。

打开了GPIOD端口的时钟,我们再配置好GPIOD的相应寄存器,相应引脚便可以输出高低电平了。
5.PNG
这就列出了GPIO的寄存器
我们并不需要配置所有的寄存器,可以视情况而定,有些寄存器可以保持它复位后的状态即可。这里没有用上的寄存器或是对某些寄存器功能仍有疑惑,可以查看参考手册第7通用IO

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

GPIOD->OSPEEDR |=  0x01<<(2*4);
这句是设置引脚输出速度。没有清零是因为在这之前并没有对相应位进行操作,复位值便是‘00’,我们将其设置为了‘01’中速模式(25MHz);
7.PNG

GPIOD->OTYPER   &=~(0x01<<4);
这句便是只清零,没有置位,是因为我们保持‘0’即可,即下图所示的推挽模式。
8.PNG

我们并没有将GPIOD对应的寄存器全部配置一遍,因为有些寄存器在这个程序中并没有用上,像AFR寄存器、IDR寄存器。

配置完这些之后,PD4这个引脚基本就可以使用了
GPIOD->ODR     &=~(0x01<<4);
我们往ODR寄存器中的相应位置为0LED灯就亮了。
为什么是写‘0’亮LED?逻辑有些颠倒。
写‘0’,引脚输出低电平,根据原理图可知,只有引脚输出低电平LED才能导通。

配个效果图
点灯.jpg

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





project_led.rar

下载

189.15 KB, 下载次数: 10, 下载积分: ST金币 -1

评分

参与人数 2 ST金币 +60 收起 理由
zero99 + 30
乖乖妮 + 30 赞一个!

查看全部评分

收藏 2 评论18 发布时间:2017-8-21 19:56

举报

18个回答
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
过来支持一下啦
andey 回答时间:2017-8-21 22:22:03
提示: 作者被禁止或删除 内容自动屏蔽
@乔木 回答时间:2017-8-21 22:34:37

互相学习
epochal 回答时间:2017-8-22 07:24:13
学习了!
@乔木 回答时间:2017-8-22 07:55:16

你们都是大神
乖乖妮 回答时间:2017-8-22 08:43:18
@乔木 发表于 2017-8-21 20:24
怎么也给个评分吧

等着你继续更呢
@乔木 回答时间:2017-8-22 08:48:50

慢慢来嘛
freeelectron 回答时间:2017-8-22 08:53:47
板子不错
@乔木 回答时间:2017-8-22 09:09:36
zero99 回答时间:2017-8-22 15:48:58

下期在什么时候啊,透露下
@乔木 回答时间:2017-8-22 16:38:13
zero99 发表于 2017-8-22 15:48
下期在什么时候啊,透露下

今晚
feixiang20 回答时间:2018-9-5 23:56:59
谢谢分享,来看看
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版