一、初始LED原理图
共阴极led
LED发光二极管,需要有电流通过才能点亮,当有电压差就会产生电流
二极管两端的电压差超过2.7v就会有电流通过
电阻的作用
由于公式I=V/R
不加电阻容易造成瞬间电流无穷大
发光二极管工作电流为10-20MA
3.3v / 1kΩ = 3.3mA
电阻作用限流电阻。
二、分析GPIO寄存器
2.1 前言
编程的目的是为了操作硬件,硬件分布在地址上,所以转变为编程操作地址,因为地址是唯一的。
编程的目的就操作地址间接操作硬件
地址分布比较广,硬件都会把地址用寄存器的方式来分布
某个地址到某个地址属于某个寄存器
这样的话我们操作硬件实际上就是在操作地址,操作地址实际上就是转化为操作寄存器。
2.2 本节目标
操控PA1-PA4输出高电平
经过前言分析可知,这几个问题编程找到一个或者某几个寄存器,这几个寄存器可以让我们的PA1-PA4进行高电平的输出。
另一个要注意的我们的gpio口,当前pa1-pa4要输出高低电平,那么当前这个pa1-pa4他所对应的功能是通用的输入输出。 这时候pa1-pa4是输出功能,还有其他功能,当前处理器有48个管脚,每一个管脚有多个功能,某一时刻只用一个功能,这就是管脚的复用。找寄存器,那几个可以管理我们的pa1-pa4,让这个四个管脚可以当做输入输出功能中的输出功能来用。
为了更好的实现分析,这时候需要去看stm32的中文参考手册
其中第八节是对gpio的描述
GPIO描述:每个gpio端口有两个32位配置寄存器,两个数据寄存器,一个32位置位/复位寄存器,一个16位复位寄存器,一个32位锁定寄存器,总共有七个寄存器,我们就是通过操作这些寄存器来控制我们的GPIO的。
注:1字节=8位(bit)
其中GPIO每个端口又可以配置成如下八种模式:
对于具体gpio配置成什么模式,8.1.11节外设的GPIO配置有详细解释
2.3 寄存器描述
首先看8.2.1端口配置低寄存器(GPIOx_CRL)x=A..E
4位一组
分别配置输入输出模式和速度。
从表中可以看到低寄存器对应的是GPIO0-7
正好对应32的八组。
端口配置高寄存器是8-15
因为我们要配置的是PA1-4,所以我们只关系低寄存器的1-4也就是4-19位
对于输出模式,大多数gpio采用推挽输出模式即可
2.4 寄存器地址确定
当我们确定好要操作的寄存器后,下一步就需要找到寄存器对应的地址,然后在相应的位写入数据即可
寄存器地址由基地址+偏移地址组成
gpio的基地址在
的寄存器映像中可以找到
整个地址被分为0x0000 0000 到 0Xffff FFFF,
当前stm32是32位的处理器。就是2的32次方。
最多能管理从0开始一直到2的32次方减1.
由寄存器映像可知,gpioA的基地址是0x4001 0800
所以我们要操作的低寄存器地址就是基地址+偏移地址=0x4001 0800 + 0x00
一会就要向这个地址里面的4到19位写0011 0011 0011 0011
根据寄存器配置说明可知00是通用推挽输出,11是最大速度50MHz,这样gpioA1-4就都配置成了最大速度50Mhz ,推挽输出模式
2.5 输出寄存器配置
当知道gpio1-4的地址并配置好输出模式后,我们应该考虑输出数据了,应该会有一个寄存器会完成这部分操作。
找到了端口输出数据寄存器
首先确定其地址,地址=基地址+偏移地址=0x4001 0800 + 0xCH = 0x4001 08CH
这16位就占了我们寄存器中的低16位。
端口输出寄存器干什么用的呢,你往哪一个端口写1,哪一个就输出高电平 ,哪一个端口写0就输出低电平。
gpio我们只用到了pa1-pa4,所以这个寄存器我们只需要关心
三、寄存器配置代码
控制低寄存器地址
我们现在是要往地址里面去写 值,那么我们现在要修改的不是地址指向的位置而是要修改我们地址里面的值,地址里面的内容,也就是说我们要取出这地址里面的内容把里面的内容做一个修改,要如何修改如何取出地址里面的值,我们就需要再加一个强制类型转换。
这个代表了地址了:
取出地址里面的内容:
用到了两个*,第一个*是强制类型转换,将我们的0x40010800转成了一个用来表示地址的指针,如何取出地址里面的值呢,取值操作符。
取出地址里面的值了下一步要干什么,我是不是要修改这个地址里面的值。
如何修改呢,我们要修改的是这个地址里面的4-19位就可以了。
如何修改4-19位最好的 做法是先给他清零,然后再写入我们的新值,
这一部分属于C语言的内容
分别用到了
|------|------|---------------------------------------|
| | | |
| & | 按位与 | 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0 |
| I | 按位或 | 两个相应的二进制位中只要有一个为1,该位的结果值为1 |
| ^ | 按位异或 | 若参加运算的两个二进制位值相同则为0,否则为1 |
| ~ | 取反 | ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0 |
| << | 左移 | 用来将一个数的各二进制位全部左移N位,右补0 |
| >> | 右移 | 将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0 |
| | | |
1.与运算(&)
参加运算的两个数据,按二进制位进行"与"运算。
运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:两位同时为"1",结果才为"1",否则为0
例如:3&5 即 0000 0011 & 0000 0101 = 0000 0001 因此,3&5的值得1。
两个数与的结果一定是比任意两个数都小,换句话说,越与数越小
2.或运算(|)
参加运算的两个对象,按二进制位进行"或"运算。
运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个对象只要有一个为1,其值为1。
例如:3|5 即 0000 0011 | 0000 0101 = 0000 0111 因此,3|5的值得7。
两个数或的结果一定是大于其中的任意一个数,换句话说,越或数越大
3.异或运算(^)
参加运算的两个数据,按二进制位进行"异或"运算。
运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0;
即:参加运算的两个对象,如果两个相应位为"异"(值不同),则该位结果为1,否则为0。
例如:9^5可写成算式如下: 00001001^00000101=00001100 可见9^5=12
4.取反运算(~)
参加运算的数据,按二进制位进行"取反"运算。
运算规则:~0=1; ~1=0;
即:参与运算的数据,对应的二进制取反后 0 变成 1 ,1 变成 0 。
例如: 3 :00000011 ; ~3 :11111100 = 252
5.左移运算(<<)
参与运算的数据,二进制全部向左移动 n 位,左边舍去,右边补 0
运算规则:00000101 << 1 = 00001010
即:参与运算的数据,对应的二进制位向左移动 n 位,左边舍去,右边补 0 。
例如:2 << 1 = 4 ; 00000010 << 1 = 00000100
左移一位相当于乘以 2
6.右移运算(>>)
参与运算的数据,二进制全部向右移动 n 位,右边舍去,左边补 0
运算规则:00000101 >> 1 = 00000010
即:参与运算的数据,对应的二进制位向右移动 n 位,右边舍去,左边补 0 。
例如 :2 >> 1 = 1 ; 00000010 >> 1 = 00000001
右移一位相当于除以 2
上述位预算符---------原文链接:https://blog.csdn.net/qq_52354698/article/details/119301131
与操作会清零,如何修改4-19位,4-19位清零,其他位不变,
0xff0000f = 111111111111000000000000000011111111
当进行位与操作时,因为4-19位都是0,按照其运算规则,得到值始终是0
清楚之后,这时候需要去修改我们的4-19位分别写成0011 0011 0011 0011,
这时候可以采用或操作。
0011等于十六进制的3
或操作置位, =0x00033330;
四、通过寄存器地址进行点灯操作
注:
清零是与操作
置1是或操作
管脚高电平点亮
低电平熄灭
点亮led灯和我们的端口输出数据寄存器有关:
寄存器地址等于基地址+偏移地址
现在我们要让他输出一个高电平
就要往这个寄存器里面的1-4位写高电平
要让灯熄灭的话对应写0就可以了
在进入循环语句之前应该让我们的led灯都熄灭,在循环中点亮熄灭
DOR寄存器地址:
=0x4001080c
首先对寄存器清零,清零就是与操作
1<<1 = 10
1<<2 = 100
1<<3 = 1000
1<<4 = 10000
|或完是11110
取反后是00001
通过循环做一个延时
五、GPIO库函数
在stm32固件库函数手册的第10节对GPIO的库函数进行了描述
GPIO寄存器结构,GPIO_TypeDef和AFIO_TypeDef在文件stm32f10x_map.h中
其中AFIO有两个功能:
1、引脚复用重映射
2、中断引脚选择
GPIO函数库
其中标黄的是常用的几个库函数
函数GPIO_DeInit和函数GPIO_DeInit
配置GPIO端口为默认值。
函数GPIO_Init对GPIO进行初始化,主要包括配置GPIOx的那个引脚,配置成什么模式,速度是多少,这些都是通过一个结构体进行配置的。
GPIO_ReadInputDataBit:读取PA15的输入值(GPIOA_PIN_15)
函数GPIO_ReadInputData:读取GPIOA的输入值,多位
函数GPIO_ReadOutputDataBit:读取PA15的输出值
函数GPIO_ReadOutputData:读取GPIOA的输出值,多位
一个字节=8位(bit)所以末尾bit就是读一位的值
函数 GPIO_SetBits:设置PA15的值,就是置1
函数 GPIO_ResetBits:清除PA15的输入值,就是置0
函数 GPIO_WriteBit:设置PA15的值,可以是0也可以是1
函数GPIO_Write:设置PA的值,可以是一个十六进制的值,一下设置多位
函数GPIO_EXTILineConfig:中断时使用,选择一个GPIO引脚作为中断线路。