位操作
首先要知晓这几种位操作,假设都是想操作x的第n位数据
置1操作
x |= (1<<n);
清0操作
x &=~(1<<n);
翻转操作
x ^=(1<<n);
数据拼凑
由两个unsigned char
- - > u8
拼凑成一个unsigned short
- - >u16
u8 lsb,msb;一般l指低位,m指高位
u16 data;
拼凑(发送): data=(msb<<8)|lsb;
解析(接收):
lsb=data&0xff;
msb=(data>>8)&0xff;
部分常用关键字以及操作
取别名/宏定义:
typedef 宏名 操作代码
全局变量关键字:
extern
预编译指令:
#ifndef XXX
#define XXX
#endif
条件编译:
#ifdef XXX
//code
#else
//code
#endif
搭建工程文件
keli的安装部分以及ST官网下载相关库文件步骤就省略了
基本文件夹建立内容为先创建两个文件夹,一个名为cmsis,用于存放一些.c和.s文件,另一个名为user,其中可以再包含两个文件夹inc和src分别用于存放自己写的头文件以及.c源文件。这里我是用的是STM32F407VGT6,cmsis中放置的文件均为从ST官网下载库文件中提取的部分文件,如下图:
大体步骤如下:
-
新建文件夹(demo_01)用于保存工程
将包含系统文件的文件夹(cmsis)整体移动到此处
在(demo_01)文件夹下可以创建user文件夹,用于存储用户代码
在user下在创建src(存放.c源文件)和inc(存放.h源文件)文件夹
-
打开keli,新建工程(选择工程存放位置、设置工程名)
-
选择芯片型号
-
设置虚拟目录+设置工程路径(用于寻址文件)
-
新建核心文件(main.c→main() main.h)
-
相关工程设置(添加芯片宏名、设置下载方式……)
-
后续就是在keli中创建新的.c文件进行编写了
-
由于具体步骤图片上传一直失败,往后如果有人有需求可以私信给我
时钟使能的作用
首先时钟使能必须在外设初始化之前!
“ARM的芯片,外设通常都是给了时钟后才能设置它的寄存器(即才能使用这个外设)。
STM32、LPC1XXX等等都是这样,这么做的目的是为了省电,使用了所谓时钟门控的技术。
寄存器是基于什么的?
当然是D触发器。触发器的赋值是一定需要时钟的, 而寄存器的时钟是由总线时钟提供的,就是说没有总线时钟的话,你给寄存器值它是不会读入的。换句话说,只有送来了时钟,触发器才能被改写值,这样寄存器才会工作。
在默认情况下这些时钟都是disable的。你如果要使用它,首先就需要enable。
我们也可以把这个时钟简单的比作为门,STM32之所以是低功耗,就是因为他把所有门都默认设置为disable,在你需要用哪个门的时候,开哪个门就可以,也就是说用到什么外设,只要打开对应外设的时钟就可以,其他的没用到的可以还是disable,这样耗能就会减少。
GPIO的基础输入输出写法
输出模式总体思路(并非具体)
- 首先将所要使用的GPIO端口所在时钟线使能。例如:将PC4所在时钟线使能:
RCC->AHB1ENR|=(1<<2);
- 将端口模式进行配置,设置为输入
00
、通用输出01
、复用10
、模拟11
中的一种。例如:将PC4设置为输出模式:GPIOC->MODER|=(1<<8);
GPIOC->MODER&=~(1<<9);
- 将端口类型进行配置,设置为推挽
0
或者开漏模式1
的一种(二者区别为:推挽可以输出高电平或者低电平,开漏默认只能输出低电平,但可以接上拉电阻输出高电平,此时输出的高电平可以超过3.3V)。例如将PC4设置为推挽模式:RCC->OTYPER&=~(1<<4);
- 设置输出速率,
00:2 MHz
(低速)01:25 MHz
(中速)10:50 MHz
(快速)11:30 pF 时为 100 MHz(高速)(15 pF 时为 80 MHz 输出)
(最大速度)。例如将PC4设置为中速:GPIOC->OSPEEDR|=(1<<8);
GPIOC->OSPEEDR&=~(1<<9);
- 进行上下拉配置,浮空
00
上拉01
下拉10
保留(一般不使用)11
。例如将PC4设置为浮空模式:GPIOC->PUPDR&=~(0x3<<8);
- 最后进行输出高低电平即可。例如将PC4输出高电平:
GPIOC->ODR|=(1<<4);
输入模式
- 首先将所要使用的GPIO端口所在时钟线使能。
- 将端口模式进行配置,设置为输入
00
、通用输出01
、复用10
、模拟11
中的一种。 - 进行上下拉配置,浮空
00
上拉01
下拉10
保留(一般不使用)11
。 - 最后进行检测高低电平即可。例如获取PA0输出的是高电平还是低电平,获取后直接比较其与0是否相等即可判断:
GPIOA->IDR&(1<<0)
,若将其写为宏定义,最好在两侧再加上(),以方便后续直接进行判断。