STM32使用寄存器开发实现点灯
因为根据公式算出来的只是寄存器地址的值,而我们要用的是这个地址,所以要进行强转 并加上volatile关键字:防止被优化#define RCC_AHB1EN *( (volatile unsigned int *)(0x40023800+0x30) ) //RCC使能时钟#define GPIOF_MODER *( (volatile unsigned int *)(0x40021400+0x00
一 STM32种GPIO外设相关的寄存器
中文手册---通用IO---GPIO寄存器:

中文手册187页:
1.端口模式寄存器
引脚编号:0~15 引脚对应的比特位 :位2y : 2y +1 (一个引脚会占两个比特位)
eg:要设置GPIO引脚的第5个引脚的端口模式为 输出模式(01) 所以第5个引脚对应的比特位为 : 10和11 所以将第10位比特位设置为0,将第11位比特位设置为1(因为是从右往左数)

2.输出类型寄存器

3.输出速度寄存器
速度越快,功耗越高,信号越容易被干扰

4.上下拉寄存器

5.输出数据寄存器

6.输入数据寄存器
输入模式下的引脚的输入数据只能只读,不能设置 通过读取引脚的数据数据来判断是高电平还是低电平:
//循环读取PA5状态
while (1)
{
uint32_t temp = GPIOA_IDR & (1 << 5); // 提取第5位
if (temp != 0)
{
state = 1; // 高电平
}
else
{
state = 0; // 低电平
}
}

二 寄存器实际地址公式
寄存器实际地址公式:
寄存器实际地址 = 寄存器起始地址 + 对应寄存器的偏移地址
eg:端口模式寄存器的实际地址 = 端口模式寄存器的起始地址 + 它的偏移地址 #define GPIOF_MODER *((volatile unsigned int *) ( 0x40021400 + 0x00 )) (1)因为( 0x40021400 + 0x00 )只是地址的值,需要强转再解引用*,才是我们需要的地址 (2)并且加上volatile关键字,避免被优化
1.寄存器起始地址
中文手册P52

2.寄存器偏移地址
(1)RCC
从设备树图中的可以看出GPIO引脚都是挂在AHB1总线上:

所以RCC时钟的地址为:
RCC时钟寄存器的起始地址 :0x40023800 RCC时钟寄存器的偏移地址:RCC_AHB1ENR 0x30


(2)GPIO
中文参考手册中的---通用IO章节----GPIO寄存器
eg:工作模式的寄存器
偏移地址为 0x00

RCC时钟寄存器的起始地址 :0x40023800
RCC时钟寄存器的偏移地址:RCC_AHB1ENR 0x30
GPIO寄存器起始地址: 0x40021400
GPIO工作模式偏移地址: 0x00
GPIO输出类型偏移地址: 0x04
GPIO输出速度偏移地址: 0x08
GPIO上下拉模式偏移地址:0x0C
GPIO输出电平偏移地址: 0x14
计算后的实际寄存器地址:
使能RCC时钟的寄存器实际地址: 0x40023800+0x30
GPIO工作模式寄存器的实际地址: 0x40021400+0x00
GPIO输出类型寄存器的实际地址: 0x40021400+0x04
GPIO输出速度寄存器的实际地址: 0x40021400+0x08
GPIO上下拉模式寄存器的实际地址: 0x40021400+0x00
GPIO输出电平寄存器的实际地址: 0x40021400+0x14
三 LED灯的工作原理
1.电路原理图:
芯片要给LED低电平,它才会亮

2.对应的GPIO引脚
D1-----LED0---------PF9
D2-----LED1---------PF10
D3-----FSMC D10-----PE13
D4-----FSMC D11-----PE14


四 点亮LED灯需要设置的模式
根据LED的工作原理,需要得到低电平,所以需要设置GPIO引脚:
设置GPIO引脚:
1.端口模式:输出模式
2.输出类型:推挽模式(因为开漏模式只能被动输出低电平,推挽模式可以输出高低电平)
3.输出速度:低速或高速
4.上下拉电阻:不加(因为是推挽模式)
5.输出数据:低电平
五 设置功能时进行的位操作
1.因为修改某个比特位的值不能印象别的比特位的值,所以用运算符 位或 | =
进行位移设置引脚功能
因为可以由下面看出,不管原来是0还是1,位或 |= 上1后都能保证结果为1
2.进行位移之前必须清空引脚 用 位与 &= ,再取反~
eg:想要向PF9的18 19比特位进行位操作的话,应该先将这两位清0,这样才能达到效果 而这两个比特位转换为二进制就是0011,再转换为十六进制就是0x03 所以例如:清空PF9的18和19比特位的话就是: GPIOF_MODER &= ~( 0x03 << 18 ); 一个引脚两个比特位--->0011----->0x03 所以清空18比特位就可以一起清空19
六 步骤
总步骤:
1.宏定义GPIO的RCC时钟和需要配置的GPIO功能的寄存器
2.使能GPIO的RCC时钟
3.设置GPIO引脚的参数:
(1)设置端口模式GPIOF_MODER:输出模式
(2)设置输出类型GPIOF_OTYPE:推挽输出
(3)设置输出速度GPIOF_SPEED:低速或中速
(4)设置上下拉电阻GPIOF_PUPD:浮空模式(无上下拉电阻)
(5)设置输出电平GPIOF_ODR:低电平
详细步骤:
1.宏定义GPIO的RCC时钟和需要配置的GPIO功能的寄存器
因为根据公式算出来的只是寄存器地址的值,而我们要用的是这个地址,
所以要进行强转 并加上volatile关键字:防止被优化
#define RCC_AHB1EN *( (volatile unsigned int *)(0x40023800+0x30) ) //RCC使能时钟
#define GPIOF_MODER *( (volatile unsigned int *)(0x40021400+0x00) ) //端口模式
#define GPIOF_OTYPE *( (volatile unsigned int *)(0x40021400+0x00) ) //输出类型
#define GPIOF_SPEED *( (volatile unsigned int *)(0x40021400+0x00) ) //输出速度
#define GPIOF_PUPD *( (volatile unsigned int *)(0x40021400+0x00) ) //上下拉模式
#define GPIOF_ODR *( (volatile unsigned int *)(0x40021400+0x00) ) //输出电平
2.使能GPIO的RCC时钟
因为它是一个比特位,不管原来是0还是1,位或 |= 上1后 都变成1,所以不需要清空


RCC_AHB1EN |= (1<<5); //使能GPIOF的设备时钟
3.设置GPIO引脚的参数:
(1)设置端口模式GPIOF_MODER:输出类型
根据手册,PF9引脚对应的比特位是18和19,所以要设置这两个比特位才能设置对应的端口模式
我们需要设置为输出模式,所以将18比特位置1(输出模式是置1)左移18位,然后再位或

GPIOF_MODER &= ~(0x03<<18); //先清空引脚
GPIOF_MODER |= (1<<18); //设置PF9工作模式为 输出模式
(2)设置输出类型GPIOF_OTYPE:推挽输出
因为推挽模式是置0,清空了之后那两个比特位就已经是0了,所以不用再置0了

GPIOF_OTYPE &= ~(1<<9); //设置PF9输出类型为 推挽模式
(3)设置输出速度GPIOF_SPEED:低速或中速
点亮LED灯只需要低速或者中速就可以了,不然速度越高越不稳定,我们可以设置为50HZ
50hz是将18和19比特位设置为10,所以是将19位(从右往左数)置1(左移19位)

GPIOF_SPEED &= ~(0x03<<18); //先清空
GPIOF_SPEED |= (1<<19); //设置输出速度为 50MHz
(4)设置上下拉电阻GPIOF_PUPD:浮空模式(无上下拉电阻)
因为浮空模式是置0,清空了之后那两个比特位就已经是0了,所以不用再置0了

GPIOF_PUPD &= ~(0x03<<18); //设置PF9上下拉模式为 浮空电路
(5)设置输出电平GPIOF_ODR:低电平
因为低电平是置0,清空了之后那两个比特位就已经是0了,所以不用再置0了

GPIOF_ODR &= ~(1<<9); //清空就等于置0
七 完整代码示例
#include <STM32F4xx.h>
/*------------------------------------------------------------
端口模式寄存器的实际地址 = 端口模式寄存器的起始地址 + 它的偏移地址
对应引脚:
D1-----LED0---------PF9
D2-----LED1---------PF10
D3-----FSMC D10-----PE13
D4-----FSMC D11-----PE14
总线:
GPIO---AHB1
*/
//1.宏定义GPIO的RCC时钟和需要配置的GPIO功能的寄存器
#define RCC_AHB1EN *( (volatile unsigned int *)(0x40023800+0x30) ) //RCC使能时钟
#define GPIOF_MODER *( (volatile unsigned int *)(0x40021400+0x00) ) //端口模式
#define GPIOF_OTYPE *( (volatile unsigned int *)(0x40021400+0x04) ) //输出类型
#define GPIOF_SPEED *( (volatile unsigned int *)(0x40021400+0x08) ) //输出速度
#define GPIOF_PUPD *( (volatile unsigned int *)(0x40021400+0x0C) ) //上下拉模式
#define GPIOF_ODR *( (volatile unsigned int *)(0x40021400+0x14) ) //输出电平
int main()
{
//2.使能GPIO的RCC时钟
RCC_AHB1EN |= (1<<5);
//3.设置GPIO引脚的参数:
//(1)设置端口模式GPIOF_MODER:输出模式
GPIOF_MODER &= ~(0x03<<18); //先清空引脚
GPIOF_MODER |= (1<<18);
//(2)设置输出类型GPIOF_OTYPE:推挽输出
GPIOF_OTYPE &= ~(1<<9);
//(3)设置上下拉电阻GPIOF_PUPD:浮空模式(无上下拉电阻)
GPIOF_PUPD &= ~(0x03<<18);
//(4)设置输出速度GPIOF_SPEED:50MHz
GPIOF_SPEED &= ~(0x03<<18); //先清空
GPIOF_SPEED |= (1<<19);
//(5)设置输出电平GPIOF_ODR:低电平
GPIOF_ODR &= ~(1<<9); //清空就等于置0
while(1)
{
}
}
更多推荐



所有评论(0)