STM32使用寄存器开发实现点灯_stm32寄存器开发手册
一 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 <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 /*------------------------------------------------------------ 端口模式寄存器的实际地址 = 端口模式寄存器的起始地址 + 它的偏移地址对应引脚:D1-----LED0---------PF9D2-----LED1---------PF10D3-----FSMC D10-----PE13D4-----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) { } }