目录
1.static 函数的作用
static是静止存储区,说白了就是有记忆功能;
举例:
如上图所示:每次执行函数a时cont的都会被置0,所以cont的返回值结果为 1 1 1 1 1 ....
如下图所示:每次执行函数b时cont只执行1次,第二次执行b函数的时候将会略过cont执行下面的,所以执行结果返回值为 1 2 3 4 .....
2.Typedef的用法
这个函数的作用就是把数据类型给他起一个新名字;
例1:typedef unsigned char u8
u8 size 就等同于 unsigned char size
例2:typedef int *p point
同样的也可给指针命名
例3:struct student
{
int age ;
char name[110];
} ;
Typedef struct student ad ;
ad.name[30]="adcd" ;
这里相当于typedef 给这个结构体命名了一个新的名字,用这个新的名字就可以访问结构体成员。
3.#define 宏定义关键词用法
1.语法格式: #define 标识符 字符串 (字符串可以是表达式、常数、格式串)
2.例:
#define syscle_72M 72000000
也就是定义表示符syscle_72M的值为72000000
3.#ifdef条件编译的用法
注:在stm32开发过程中经常会遇到不同型号的设备,如何把不同设备共用一个程序,这样扩展性更好,可以减少不必要的麻烦! 这就用到ifdef条件编译了,当满足某条件时对一组语句进行编译,条件不满足时编译另一组语句。
1.格式
#ifdef a
程序段1
#else
程序段2
#endif
解释:如果定义了这个标识符a的话编译程序段1,否则编译程序段2;
2.例子:
#ifdef STM32F10X_HD
芯片所需要的变量定义
#endif
解释:这就是我们为什么在keil软件里宏定义USE_STDPERIPH_DRIVER,STM32F10X_HD了因为我们用到时f10x系列芯片,编译的也是属于这个芯片的程序
小伙子们注意:是编译程序而不是执行程序!!!!!!
4.extern外部变量声明
说白了也就是两个c文件中,其中一个c文件定义了一个int a,而另一个c文件想用这个变量a,就得写上 estern int a 即可
例子:
这里我们可能有个疑问 u8是什么意思???
我们上面介绍了typedef ,u8就是用typedef包装的一个名字而已。例如 typedef unsigned char u8
5.构造结构体
1. 格式:
struct 结构体名
{
成员变量1;
成员变量2;
}变量名列表;
3.MDK中寄存器地址名称映射分析
对MCU来说一切底层最终都是配置寄存器
1.首先在51单片机中的地址映射方法:
sfr P1 =0x80 ; //相当于 P1 映射到地址0x80
P1 =0x00; //往寄存器地址赋值0x00
2.那么在32中是怎么映射的呢:
例如:GPIOA —>ODR =0x00000000
为什么0x00000000 就赋值给了 GPIOA的ODR寄存器了呢?
注:在stm32f10x系列所有的GPIOx(x为ABCD......)都有7个寄存器
上图:手册中可以看出外设的基地址是0x4000 0000
上图:而GPIOA是挂载在APB2总线上,APB2的基地址从图中可以看出为0x4001 0000
我们的GPIOA的基地址为0x4001 0800
如何得到的GPIOA综合上述:外设的基地址经过偏移后—>APB2的基地址经过偏移后—>GPIOA的基地址。
GPIOA呢又有7个寄存器,经过偏移量后 GPIOA—>ODR(7个寄存器中的其中一个)
上图中:我们很多用过库函数的小伙伴都经常用这几个宏定义吧,其中重点是他把GPIOA的基地址转化成了结构体指针类型 ,相当于 GPIOA 是 GPIOA_BASE这个基地址,把这个基地址强制转化为结构体指针类型,相当于这个基地址存放的空间是结构体指针类型
注:指针和地址最大的区别是指针有类型,而地址没有类型,地址仅仅是地址编号;
指针是由地址和类型组成,指针不仅记录了地址编号还记录了该地址空间的类型。
这里就是GPIOA的7个寄存器,把他放在结构体里面更容易管理,为什么转化成结构体指针类型呢,因为这7个寄存器都是指针类型命名的。
注意:任何的GPIOx都有7个寄存器,每个寄存器有32位,每个寄存器占用4个地址,每个地址占1个字节,一个字节等于8位,我们如果用ODR寄存器:GPIOA —>ODR(在GPIOA上偏移多少后得到ODR寄存器,箭头的意思是指向结构体的ORD这个成员,而ODR是封装好了的)