第四章 STM32F4开发基础知识入门-正点原子探索者STM32F4开发板-STM32F4开发指南-库函数

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第四章STM32F4开发基础知识入门

这一章,我们将着重STM32开发的一些基础知识,让大家对STM32开发有一个初步的了解,为后面STM32的学习做一个铺垫,方便后面的学习。这一章的内容大家第一次看的时候可以只了解一个大概,后面需要用到这方面的知识的时候再回过头来仔细看看。这章我们分7个小结,

·4.1 MDK下C语言基础复习

·4.2 STM32F4系统架构

·4.3 STM32F4时钟系统

·4.4 IO引脚复用器和映射

·4.5 STM32F4 NVIC中断优先级管理

·4.6 MDK中寄存器地址名称映射分析

·4.7 MDK固件库快速开发技巧

4.1 MDK下C语言基础复习

这一节我们主要讲解一下C语言基础知识。C语言知识博大精深,也不是我们三言两语能讲解清楚,同时我们相信学STM32F4这种级别MCU的用户,C语言基础应该都是没问题的。我们这里主要是简单的复习一下几个C语言基础知识点,引导那些C语言基础知识不是很扎实的用户能够快速开发STM32程序。同时希望这些用户能够多去复习一下C语言基础知识,C语言毕竟是单片机开发中的必备基础知识。对于C语言基础比较扎实的用户,这部分知识可以忽略不看。

4.1.1 位操作

C语言位操作相信学过C语言的人都不陌生了,简而言之,就是对基本类型变量可以在位级别进行操作。这节的内容很多朋友都应该很熟练了,我这里也就点到为止,不深入探讨。下面我们先讲解几种位操作符,然后讲解位操作使用技巧。

C

表4.1.1 16种位操作

这些与或非,取反,异或,右移,左移这些到底怎么回事,这里我们就不多做详细,相信大家学C语言的时候都学习过了。如果不懂的话,可以百度一下,非常多的知识讲解这些操作符。下面我们想着重讲解位操作在单片机开发中的一些实用技巧。

1)不改变其他位的值的状况下,对某几个位进行设值。

这个场景单片机开发中经常使用,方法就是先对需要设置的位用&操作符进行清零操作,然后用|操作符设值。比如我要改变GPIOA->BSRRL的状态,可以先对寄存器的值进行&

清零操作

GPIOA-> BSRRL &=0XFF0F; //将第4-7位清0

然后再与需要设置的值进行|或运算

GPIOA-> BSRRL |=0X0040; //设置相应位的值,不改变其他位的值

2)移位操作提高代码的可读性。

移位操作在单片机开发中也非常重要,我们来看看下面一行代码

GPIOx->ODR = (((uint32_t)0x01) << pinpos);

这个操作就是将ODR寄存器的第pinpos位设置为1,为什么要通过左移而不是直接设置一个固定的值呢?其实,这是为了提高代码的可读性以及可重用性。这行代码可以很直观明了的知道,是将第pinpos位设置为1。如果你写成

GPIOx->ODR =0x0030;

这样的代码就不好看也不好重用了。

3) ~取反操作使用技巧

SR寄存器的每一位都代表一个状态,某个时刻我们希望去设置某一位的值为0,同时其他位都保留为1,简单的作法是直接给寄存器设置一个值:

TIMx->SR=0xFFF7;

这样的作法设置第3位为0,但是这样的作法同样不好看,并且可读性很差。看看库函数代码中怎样使用的:

TIMx->SR = (uint16_t)~TIM_FLAG;

而TIM_FLAG是通过宏定义定义的值:

#define TIM_FLAG_Update ((uint16_t)0x0001)

#define TIM_FLAG_CC1 ((uint16_t)0x0002) 看这个应该很容易明白,可以直接从宏定义中看出TIM_FLAG_Update就是设置的第0位了,可读性非常强。

4.1.2 define宏定义

define是C语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供方便。常见的格式:

#define 标识符字符串

“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。例如:#define PLL_M 8

定义标识符PLL_M的值为8。

至于define宏定义的其他一些知识,比如宏定义带参数这里我们就不多讲解。

4.1.3 ifdef条件编译

单片机程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。条件编译命令最常见的形式为:

#ifdef 标识符

程序段1

#else

程序段2

#endif

它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。其中#else部分也可以没有,即:

#ifdef

程序段1

#endif

这个条件编译在MDK里面是用得很多的,在stm32f4xx.h这个头文件中经常会看到这样的语句:#if defined (STM32F40_41xxx)

STM32F40x系列和STM32F41x系列芯片需要的一些变量定义

#end

而(STM32F40_41xxx则是我们通过#define来定义的。条件编译也是c语言的基础知识,这里也就点到为止吧。

4.1.4 extern变量申明

C语言中extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。这里面要注意,对于extern申明变量可以多次,但定义只有一次。在我们的代码中你会看到看到这样的语句:

extern u16 USART_RX_STA;

这个语句是申明USART_RX_STA变量在其他文件中已经定义了,在这里要使用到。所以,你肯定可以找到在某个地方有变量定义的语句:

u16 USART_RX_STA;

的出现。下面通过一个例子说明一下使用方法。

在Main.c定义的全局变量id,id的初始化都是在Main.c里面进行的。

Main.c文件

u8 id;//定义只允许一次

main()

{

id=1;

printf("d%",id);//id=1

test();

printf("d%",id);//id=2

}

但是我们希望在main.c的 changeId(void)函数中使用变量id,这个时候我们就需要在main.c 里面去申明变量id是外部定义的了,因为如果不申明,变量id的作用域是到不了main.c文件中。看下面main.c中的代码:

extern u8 id;//申明变量id是在外部定义的,申明可以在很多个文件中进行

void test(void){

id=2;

}

在main.c中申明变量id在外部定义,然后在main.c中就可以使用变量id了。

对于extern申明函数在外部定义的应用,这里我们就不多讲解了。

4.1.5 typedef类型别名

typedef用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。typedef在MDK用得最多的就是定义结构体的类型别名和枚举类型了。

struct _GPIO

{

__IO uint32_t MODER;

__IO uint32_t OTYPER;

相关文档
最新文档