第一种:指针形式
led.c文件:
#include "led.h"
#include "stm32f4xx.h"
void LED_Init(void)
{
//1左移五位既是将第五位置为1,查寄存器可知1是使能0失能
RCC->AHB1ENR|= 1<<5;//使能RCC的AHB1时钟
//PF9 的GPIO配置
//将(1 1)左移18位再取反清零:2代表两位控制一IO,因为IO是F9,所以最后是~(3<<2*9),达到清零效果
GPIOF->MODER &= ~(3<<2*9);//配置为0用&,配置为1用 |
GPIOF->MODER |= 1<<(2*9);//1既是0 1,代表输出模式(查寄存器)
GPIOF->OSPEEDR &= ~(3<<2*9);//同理,清零
GPIOF->OSPEEDR |= 2<<(2*9);//2是1 0,将F9设置为50MHZ的速度
GPIOF->PUPDR &= ~(3<<2*9);//清零
GPIOF->PUPDR |=1<<(2*9);//上拉
GPIOF->OTYPER &= ~(1<<9);//清零,该寄存器是低16位有效,1位控制1个IO
GPIOF->OTYPER |=0<<9;//置0,既是输出推挽(复位)
GPIOF->ODR|= 1<<9;//1 控制高低电平
//GPIOF->ODR&=~(1<<9);//
//PF10 同理配置PF10
GPIOF->MODER &= ~(3<<2*10);
GPIOF->MODER |= 1<<(2*10);
GPIOF->OSPEEDR &= ~(3<<2*10);
GPIOF->OSPEEDR |= 2<<(2*10);
GPIOF->PUPDR &= ~(3<<2*10);
GPIOF->PUPDR |=1<<(2*10);
GPIOF->OTYPER &= ~(1<<10);
GPIOF->OTYPER |=0<<10;
GPIOF->ODR|= 1<<10;
}
///
led.h文件:
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
#endif
///
main.c文件:
#include "stm32f4xx.h"
#include "led.h"
#include "delay.h"
int main(void)
{
delay_init(168);
LED_Init();
while(1)
{
GPIOF->ODR&=~(1<<9);
GPIOF->ODR&=~(1<<10);
delay_ms(500);
GPIOF->ODR |= 1<<9;
GPIOF->ODR |=1<<10;
delay_ms(500);
}
}
------------------------------------------------------------------------------------------------------------------
第二种方法:配置基地址开始
// 设置寄存器宏定义
//1、时钟线
#define RCC_AHB1ENR *(volatile unsigned long *)(0x40023800 + 0x30) // volatile 防止编译器优化 AHB1外设使能时钟线
#define GPIOF_MODER *(volatile unsigned long *)(0x40021400 + 0x00) // GPIOF的模式寄存器
#define GPIOF_OTYPER *(volatile unsigned long *)(0x40021400 + 0x04) // GPIOF的输出类型寄存器
#define GPIOF_OSPEEDR *(volatile unsigned long *)(0x40021400 + 0x08) // GPIOF的输出速度寄存器PUPDR
#define GPIOF_PUPDR *(volatile unsigned long *)(0x40021400 + 0x0c) // GPIOF的上下拉寄存器
#define GPIOF_ODR *(volatile unsigned long *)(0x40021400 + 0x14) // GPIOF的输出数据寄存器
#define GPIOF_BSRR *(volatile unsigned long *)(0x40021400 + 0x18) // GPIOF的复位/置位寄存器
#define GPIOE_MODER *(volatile unsigned long *)(0x40021000 + 0x00) // GPIOF的模式寄存器
#define GPIOE_OTYPER *(volatile unsigned long *)(0x40021000 + 0x04) // GPIOF的输出类型寄存器
#define GPIOE_OSPEEDR *(volatile unsigned long *)(0x40021000 + 0x08) // GPIOF的输出速度寄存器PUPDR
#define GPIOE_PUPDR *(volatile unsigned long *)(0x40021000 + 0x0c) // GPIOF的上下拉寄存器
#define GPIOE_ODR *(volatile unsigned long *)(0x40021000 + 0x14) // GPIOF的输出数据寄存器
#define GPIOE_BSRR *(volatile unsigned long *)(0x40021000 + 0x18) // GPIOF的复位/置位寄存器
// 大概时间的延时函数
void delay(int n)
{
while(n--)
{
int i = 1000;
while(i--);
}
}
// 初始化LED
int init_led(void)
{
// 2、初始化时钟、寄存器 第5位置1就是使能
RCC_AHB1ENR |= 1<<5;
//3、配置寄存器各种参数,LED只是输出,所以选择每个参数里面的输出模式
// ①初始化GPIOF为输出模式
//---------------模式--移动位数
GPIOF_MODER &= ~(0x3<<18); // 清空第18位和19位 11
GPIOF_MODER |= 1<<18; // 配置PF9
//GPIOF_MODER &= ~(0xF<<18); // 清空第18位和19位、20位、21位 1111
//GPIOF_MODER |= 0x5<<18; // 配置PF9、PF10
GPIOF_MODER &= ~(0x3<<20); // 清空第20位、21位 11
GPIOF_MODER |= 1<<20;//配置PF10
// ②配置GPIOF的输出类型为推挽
GPIOF_OTYPER &= ~(0x1<<9); // 清空第9位
GPIOF_OTYPER &= ~(0x1<<10); // 清空第10位
// ③配置GPIOF的输出速度
GPIOF_OSPEEDR &= ~(0x3<<18); // 清空第18位和19位 11
GPIOF_OSPEEDR &= ~(0x3<<20); // 清空第20 21 11
GPIOF_OSPEEDR |= 0x2<<18; // 50M速度
GPIOF_OSPEEDR |= 0x2<<20; // 50M速度
// ④配置 GPIOF为上拉输出
GPIOF_PUPDR &= ~(0x3<<18); // 清空第18位和19位 11
GPIOF_PUPDR |= 1<<18; // 配置PF9为上拉输出
GPIOF_PUPDR &= ~(0x3<<20); // 清空第20位和21位 11
GPIOF_PUPDR |= 1<<20; // 配置PF10为上拉输出
// ⑤输出数据:高电平 1 低电平 0
GPIOF_ODR |= 1<<9; // PF的第9个引脚输出高电平
GPIOF_ODR |= 1<<10; // PF的第10个引脚输出高电平
/*********************************PE脚**************************************/
// 初始化时钟 寄存器第4位置1就是使能
RCC_AHB1ENR |= 1<<4; //PE脚
// 初始化GPIOF为输出模式
GPIOE_MODER &= ~(0x3<<26); // 清空第26位和272829位 11
GPIOE_MODER |= 1<<26; // 配置PF9, 1010即是5,可同时配置
GPIOE_MODER &= ~(0x3<<28); // 清空第20位、21位 11
GPIOE_MODER |= 1<<28;//配置PF10
// 配置GPIOF的输出类型为推挽
GPIOE_OTYPER &= ~(0x1<<13); // 清空第9位
GPIOE_OTYPER &= ~(0x1<<14); // 清空第10位
// 配置GPIOF的输出速度
GPIOE_OSPEEDR &= ~(0x3<<26); // 清空第18位和19位 11
GPIOE_OSPEEDR &= ~(0x3<<28); // 清空第20 21 11
GPIOE_OSPEEDR |= 0x2<<26; // 50M速度
GPIOE_OSPEEDR |= 0x2<<28; // 50M速度
// 配置 GPIOF为上拉输出
GPIOE_PUPDR &= ~(0x3<<26); // 清空第18位和19位 11
GPIOE_PUPDR |= 1<<26; // 配置PF9为上拉输出
GPIOE_PUPDR &= ~(0x3<<28); // 清空第20位和21位 11
GPIOE_PUPDR |= 1<<28 ;// 配置PF10为上拉输出
// 输出数据:高电平 1 低电平 0
GPIOE_ODR |= 1<<13; // PF的第9个引脚输出高电平
GPIOE_ODR |= 1<<14; // PF的第10个引脚输出高电平
return 0;
}
int main(void)
{
// 初始化LED
init_led();
while (1)
{
// 点亮LED0
GPIOF_ODR &= ~(1<<9); // PF的第9个引脚输出低电平
delay(2000);
GPIOF_ODR |= 1<<9;
delay(2000);
// 输出数据:高电平 1 低电平 0
GPIOF_ODR &= ~(1<<10);
delay(2000);
GPIOF_ODR |= 1<<10; // PF的第9个引脚输出高电平
delay(2000);
GPIOE_ODR &= ~(1<<13);
delay(2000);
GPIOE_ODR |= 1<<13; // PE的第13、14个引脚输出高电平
delay(2000);
GPIOE_ODR &= ~(1<<14);
delay(2000);
GPIOE_ODR |= 1<<14;
delay(2000);
}
}
两者的区别在于一个需要配置基地址,一个直接用指针对寄存器进行操作,那怎样配置基地址,下面解释一下:
1、根据STM32F4xx中文参考手册的2.3节存储器的映射找到对应总线、外设的边界基地址,我这里只截了部分图,仅供参考
2、找到对应寄存器的偏移地址,在STM32F4xx中文参考手册7.4节
配置后如下所示:
2、最后对应寄存器进行对其位移操作即可(寄存器映射),可参考上面的代码
总结:这里以一个简单的LED闪烁来了解对寄存器进行具体的操作,使自己能够用寄存器来进行项目的开发,其他的外设配置是一样的原理。
上一篇:STM32的DMA基本原理及实现过程
下一篇:教你如何使用STM32控制无源蜂鸣器发声播放音乐
推荐阅读最新更新时间:2024-11-12 20:27
推荐帖子
- 瑞萨芯片的学习
- 我们一起来学习瑞萨这块芯片。电子竞赛要用到的芯片。瑞萨芯片的学习估计还是飞机的主控支持一下楼主~~请问MCU是不是必须用瑞萨的单片机啊,以前没有学过,用12c芯片可以吗??我靠看来得现学了
- 王。。。。 电子竞赛
- STM32
- NANDFlash模拟U盘的过程中,需要给NAND做文件系统吗,如果需要的话,步骤有哪些呢???STM32
- meijianmao stm32/stm8
- 关于应用MSP430F449设计一个电流表的量程问题
- 我们在利用F449进行设计一个电流表,在对固定电阻取电压时考虑以下几个问题:1.F449的供电电压是9v(我是说那个变压器),那么对于单片机进行AD转换时的驱动电压是多少?也就是我所能得到的电压的范围是多少??2.F449在进行AD转换过程中,所能分辨的最小的电压增量是多少,比如0.005v和0.006v,单片机是否能进行辨别,如果不能的话,是由什么来计算和确定这个分辨量的??很急。。。跪求能者能解答。。。小女子在此一拜。。。~~o(_)o~~关于应用MSP430F449设计
- skyzxcvbnm 微控制器 MCU
- CircuitPython 发布 4.0.2 版
- 作为micropython目前最重要的分支,CircuitPython发布了4.0.2版,这是4.x的第二个错误修复版本。自4.0.1以来的新修复 修复导致崩溃的根显示组的错误gc。感谢@dhalbert和@ATMakersBill 修复gamepadshift在快速阅读时工作。感谢@deshipu和@kattni 修复nrfNeoPixel写短链。感谢@dhalbert和@bmeisels 修复导入损坏的.mpy时崩溃。感谢@tannewt和@jn
- dcexpert MicroPython开源版块
- 如何保证SPI flash中的数据安全?
- 各位大侠,小弟有个问题请教:请问:将用户开发的程序存储到SPIFLASH后供其他芯片调用,有没有什么措施《防止FLASH中的数据被导出》,导出数据有时能够直接用于其他FLASH中;另外,是否有自带加密功能的SPIFLASH芯片呢,如果有,请推荐下型号,或是分享下资料;感激不尽,在线等待答复。如何保证SPIflash中的数据安全?普通的SPIFLASH好象没有办法加密我有办法解决。QQ:359117122我也想知道
- wende 嵌入式系统
- 三极管怎么加个反馈
- 想100kHz的信号高电压放大,这样用三极管怎么样?但这样输出幅度和三极管的B值有关。能不能加个反馈使得输出放大像运放应用一样只和配搭的电阻值有关,当然电路越简单越好,精度可以差些。如果能推荐个高压高频运放直接用也非常感谢,未来可能电压高到100V,频率300kHz,但是功率不大三极管怎么加个反馈此电路中三极管已经加有本级负反馈,是三极管发射极到地串联了100欧电阻构成的。由于本级负反馈,输出幅度与三极管电流放大倍数关系不是很大。此电路三极管发射极电阻数值为100欧,集电
- rockchn 模拟电子
设计资源 培训 开发板 精华推荐
- 基于Blinker和ESP8266的红外学习型遥控器
- DC2268A-B,用于 LTM4620AEV 双降压模块稳压器的演示板,5.5V = VIN = 16V,Vout1 = 3.3V @ 13A,Vout2 = 1.5V @ 13A
- 使用VIPer0P和STM32L的、通过电容式触摸进行待机管理的、7V双路输出反激式转换器
- 小四轴飞行器DIY
- EVAL6207N,基于 L6207N DMOS 双路全桥驱动器和 PWM 电流控制器的评估板
- LT1072CT 具有外部电流限制的高效开关稳压器的典型应用
- #第四届立创大赛#智能空调控制器
- stm32智能语音小车
- 【中山大学校赛】远程继电器控制板
- 超级电容保护板2.8V3000F方形