OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 746|回复: 0

《M144Z-M3最小系统板使用指南——STM32F103版》第五章 STM32基础知识入门

[复制链接]

1118

主题

1129

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4671
金钱
4671
注册时间
2019-5-8
在线时间
1224 小时
发表于 2024-3-20 16:43:40 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-3-20 16:43 编辑

第五章 STM32基础知识入门
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板

2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boar ... _mini_sysboard.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子STM32技术交流QQ群:725095144

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

本章着重介绍STM32的一些基础知识,令读者对STM32有一个初步的了解,为后面的章节学习做铺垫。对于本章的内容,读者可以先只看一个大概,在后面需要使用到这部分知识点的时候,再回过头来仔细看。
本章分为如下几个小节:
5.1 C语言基础知识复习
5.2 寄存器基础知识
5.3 STM32F103系统架构

5.1 C语言基础知识复习
本节介绍C语言的基础知识,对C语言比较熟练的读者,可以跳过本节,对于基础比较薄弱的读者,建议好好学习一下本节的内容。
由于C语言博大精深,不可能由一小节的内容就全讲明白,所以本节知识回顾在进行STM32开发时常用的几个C语言知识点,以便读者的更好的学习本书后续的内容,并编写相关的代码。
5.1.1 位操作
C语言的位操作就是对基本类型变量进行位级别的操作。本节的内容比较简单,这里也就点到为止,不深入探讨。下面先讲解几种位操作运算符,然后介绍其相关的使用技巧。C语言支持如下6种位操作的运算符:
QQ截图20240320163933.png
表5.1.1.1 6种位操作的运算符
下面介绍这些位操作运算符的使用技巧。
①:在不改变其他位的状况下,对某几个位进行设值
这个场景在单片机开发中经常使用,方法就是先对需要设置的位用&运算符进行清零操作,然后用|运算符设值。例如要设置GPIOA的ODATA寄存器Bit6(第6位)为1,则可以先使用&运算符对该寄存器的Bit6进行清零操作:
  1. GPIOA->ODATA &= 0xFFFFFFBF;    /* 将Bit6清0 */
复制代码
然后再使用|运算符对该寄存器的Bit6进行置1操作:
  1. GPIOA->ODATA |= 0x00000040;    /* 将Bit6置1 */
复制代码
②:移位操作提高代码的可读性
例如①中|操作使用到的0x00000040,虽然通过换算,可以知道是将Bit6置1,但是这样的表达可读性比较差,可以通过移位操作对其进行改进:
  1. GPIOA->ODATA |= (1 << 6);      /* 将Bit6置1 */
复制代码
这么一来,就可以非常直观地看出是将Bit6置1了。
③:按位取反操作使用技巧
②中使用移位操作改进①中仅使用|运算将Bit6置1的可读性,但要改进①中使用&运算将Bit6清0的可读性还需借助按位取反操作:
  1. GPIOA->ODATA &= ~(1 << 6);     /* 将Bit6清0 */
复制代码
这么一来,就可以非常直观地看出是将Bit6清0了。
④:按位异或操作使用技巧
按位异或可以很方便地对Bit位进行翻转,例如不考虑LED当前是何种状态,只要求控制LED翻转状态等情况(假设LED的亮灭状态由PA6输出的高低电平控制):
  1. GPIOA->ODATA ^= (1 << 6);      /* Bit6的值取反 */
复制代码
这么一来,就可以很方便地操作PA6引脚输出相反的电平,而不用先读取PA6输出的电平状态然后才输出相反的电平。
5.1.2 define宏定义
define是C语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供方便,其常见的格式如下:
  1. #define 标识符   字符串
复制代码
“标识符”为所定义宏的名称;“字符串”可以是常数、表达式、格式串等。例如:
  1. #define HSE_VALUE 8000000U
复制代码
定义标识符HSE_VALUE的值为8000000U,数字后的U是unsigned(无符号)的意思,随后便可在程序代码中使用HSE_VALUE来代替8000000U。
至于define宏定义的一些其他高级用法,例如宏定义带参数等,本章不过多介绍。
5.1.3 ifdef条件编译
在单片机程序开发过程中,经常会遇到需要在满足某些条件时对一段代码进行编译,而当条件不满足或满足另一条件时编译另一段代码,这就可以使用条件编译,条件编译最常见的形式如下:
  1. #ifdef 标识符
  2. 代码段1
  3. #else
  4. 代码段2
  5. #endif
复制代码
如上的条件编译,当标识符被定义过(一般使用define进行定义),则代码段1会被编译,否则会编译代码段2。
5.1.4 extern外部申明
C语言中extern关键字用于修饰变量或函数,以表示变量或函数定义在别的文件中,提示编译器遇到此变量或函数时,需在其他文件中寻找其定义。这里要注意的是,可以使用extern多次在不同文件中修饰同一个变量或函数,但该变量或函数只能被定义一次
5.1.5 typedef类型别名
typedef用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。例如在编写程序时经常使用到的uint8_t、uint16_t和uint32_t等都是由typedef定义的类型别名,其定义如下:
  1. typedef unsigned char      uint8_t;
  2. typedef unsigned short int uint16_t;
  3. typedef unsigned int       uint32_t;
复制代码
这么一来就可以在编写程序代码的时候使用uint8_t等代替unsigned char等,极大地提高的代码的可读性可编写代码的效率。
5.1.6 struct结构体
struct用于定义结构体,结构体就是一堆变量的集合,结构体中的成员变量的作用一般都是相互关联的,定义结构体的形式如下:
  1. struct 结构体名
  2. {
  3.     成员变量1的定义;
  4.     成员变量2的定义;
  5.     ......
  6. };
  7. 例如:
  8. struct lcd_device_struct
  9. {
  10.     uint16_t width;
  11.     uint16_t height;
  12. };
复制代码
如上举例的结构体定义,一堆描述LCD屏幕的变量的集合,其中包含了LCD屏幕的宽度和高度。
结构体变量的定义如下:
  1. struct lcd_device_struct lcd_device;
复制代码
如上,就定义了一个名为lcd_device的结构体变量,那么怎么访问这个结构体变量中的成员变量呢?如下:
  1. lcd_device.width = 240;
  2. printf("LCD Height: %d\n", lcd_device.height);
复制代码
如上就展示了结构体变量中成员变量的访问操作。
5.1.7 指针
指针是另一个变量的变量,指针变量在内存中保存的是另一个变量在内存中的地址,通过指针可以访问到另一个变量所在内存地址中的数据。
举一个定义指针的例子,如下:
  1. char *p_str = "This is a string!";
复制代码
如上,就定义一个名为p_str的指针变量,并将p_str指针指向了字符串“This is a string!”保存在内存中首地址,对于STM32来说,此时p_str的值就是一个32位的数,这个数就是一个内存地址,这个内存地址就是上述字符串保存在内存中的首地址。
通过p_str指针就可以访问到字符串“This is a string!”,那具体是如何访问的呢?前面说p_str保存的是一个内存地址,那么就可以通过这个内存地址去内存中读取数据,通过*p_str就可以访问地址为p_str的内存数据,*(p_str + 1)可以访问下一个内存地址中的数据。
知道了如何访问内存中的数据,但是读取到的数据要如何解析呢?这就有p_str指针的类型决定了。在这个例子中p_str是一个char类型的指针,那么访问*p_str就是访问地址为p_str,大小为sizeof(char)(一般为一个字节)的一段内存数据,在这个例子中就可以读取到字符“T”, 读取*(p_str + 1)就是“h”,以此类推。
指针是C语言的精髓,但也是初学者望而生畏的一个知识点,若读者一时半会无法理解指针的用法也没关系,善用搜索引擎,网上有很多参考的学习资料。

5.2 寄存器基础知识
寄存器(Register)是一种特殊的内存,它主要用于实现控制和访问MCU的内核和各个片上外设。
对于STM32来说,寄存器一般都是32位的,但由于MCU上的内存资源十分宝贵,因此在一个32位寄存器中,会使用其中的1位或多位来控制或访问MCU的内核或各个片上外设的一种功能,但即使如此,STM32上也还是有上百个寄存器,这实际上是因为STM32有很多的片上外设导致的,只要将这些寄存器按照功能分好类,学起来就不难了。
从大方向来区分,STM32中的寄存器可分为两大类,分别为内核寄存器和外设寄存器,大类下还可以分出许多小类,如下表所示:
QQ截图20240320163922.png
表5.2.1 STM32寄存器分类
对于初学者来说仅需在学习MCU的各个片上外设时,再去学习该片上外设相关的寄存器即可。

5.3 STM32F103系统架构
STM32F103是ST公司基于ARM授权Cortex-M3内核设计的一款芯片,而Cortex-M内核采用了ARM v7-M架构,具有低成本、低功耗、实时性好、中断响应快、处理效率高等特点。
5.3.1 Cortex-M3内核&芯片
ARM公司提供内核(例如Cortex-M3内核)授权,完成的MCU芯片还需要很多其他的组件。芯片公司(例如ST)在获取Cortex-M3内核授权后,就可以将其用于自己的芯片设计中,并添加存储器、外设、I/O等其他组件。同于型号的芯片也会有不同的规格,实际当大多数就是存储器容量、外设资源等的差异。
5.3.2 STM32F103系统框图
STM32F103的系统框图,如下图所示:                             
image002.jpg
图5.3.2.1 STM32F103系统框图
从上图可以看出,STM32F103就是在ARM提供的Cortex-M3内核上通过各种总线,挂载了各种各样的外设和存储器。
5.3.3 地址映射
STM32是32位的MCU,因此其地址总线的宽度也是32位,因此最大可访问的内存空间为4GB(2^32=4GB),STM32就将这4GB的空间映射给各种寄存器和存储器。
STM32F103地址映射图,如下图所示:   
image004.jpg
图5.3.3.1 STM32F103地址映射图
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 19:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表