第一章 1小节:点亮LED灯
2026/6/30 1:41:53 网站建设 项目流程

这节课需要做到的事情是点亮电路板上的LED灯,首先做到点亮第一个LED灯

stm32开发板

stm32开发板上有很多很多的一个电流接口,每一个接口都需要负责对应的部分,你需要先开启对应的接口,他才会供应电流,有了电流,他才能给每一个接口进行供电,就像一道道关卡,只有先通过第一关,第二关的大门才会打开

开始点亮

以上是电路板的LED组件,电流回路是从左侧阳极输出高电压,那么右边的引脚就需要输出低电压,只有两者形成一个电压差,才有可能形成一个电路回路,点亮LED灯,如果右边也输出一个高电压的话,两边一样电压,就像一个池子里边的水,两边相等就不会产生任何的高视差,自然也就不会产生电流

连接在LED_R右边的叫做引脚,我们要做的是通过右边的引脚去进行输出电流,让电流流出来或者流进去,而嵌入式板子就可以控制电流跟电压的高低

在这块板子当中,他已经给我们封装好了地址,我们需要做的是通过访问他的地址,把电流进行输出的一个操作

要点亮这个LED灯,我们需要用到一个GPIO库,他就相当于管控开关的,可以进行输入输出电流的电压,但是他还有许多其他的功能,这个边学边看

首先我们需要点亮红灯,他接的是PF6的引脚,那么我们需要去找到PF6引脚的一个初始地址

因为gpio分为很多的端口,而我们要做的是接入pf6的端口,那么根据对应的字母,我们应该要找GPIOF的起始地址

可以看到起始地址是0x4002 1400,接下来需要在这个起始地址的基础上找到PF6的一个地址,改成输出模式才能输出电流

由于我们要点亮的是PF6,所以找到ODR6,他是起始地址向左偏移6位,但是一开始的引脚都是输入模式,所以我们需要找到端口模式寄存器,把引脚改成输出模式,我们要用到的是输出引脚,PF6,那么就需要把PF6这个端口改成输出模式,也就是把原本的默认复位模式00改成01,所以需要在初始地址上边向左移12位

因为GPIOF的基础地址是0x40021400,所以需要再在这个基础上+0x00,偏移到这个端口模式寄存器的地址,修改里边的值

所以语句是*(unsigned int *)(0x40021400+0x00)=(1<<2*6)但是不可以这么写,因为这么写的话,虽然那一个位置是被替换掉了,但是其他的会全部变成0,因为=是直接赋值覆盖,因为寄存器是32位的,那么赋值的话就是相当于00000000000000000001,然后1左移了,其他的还是0,所以直接这样子写不对

位与规则:对应位同时为 1,结果才是 1;任意一位是 0,结果就是 0

或与规则:只要任意一位是 1,结果就是 1

*(unsigned int *)(0x40021400+0x00)&=~(1<<2*6)

*(unsigned int *)(0x40021400+0x00)|=(1<<2*6)

只有先执行取反操作,然后在进行或与,值才2不会被改变,如果没有这么做的话,其他引脚的值就会变成不是原来引脚的值了

在将引脚换成01之后,就需要进行控制引脚进行输出低电平

那么需要偏移到ODR6这个地址,控制他输出低电平(所以是要把这个位置变成0,其余引脚不变)

*(unsigned int *)(0x40021400+0x14)&=~(1<<6)

但是在做完这些之后还不会亮,因为时钟还没开启,也就是说那个3v的地方还没有电流,现在需要把对应时钟的端口给他打开

因为GPIOF挂载在AHB1总线上,所以要使用RCC(因为所有外设时钟、复位都由RCC统一进行管理)

RCC的话就需要向左偏移5个地址,把这个地址设置为1,要找到时钟的起始地址,RCC的起始地址是23800,而AHB1的偏移地址是0x30

*(unsigned int *) (0x40023800+0x30)|=(1<<5)

下边为程序参考:

#include "stm32f4xx.h"


void Delay(unsigned int i){
for(;i!=0;i--){
}
};

int main(void){
/*打开时钟寄存器*/
*(unsigned int *) (0x40023800+0x30) |= ( 1<<5 ); //首先需要打开时钟配置器,给出一定的电流,才能够操作输出成低电平,点亮LED灯
//首先开启GPIOF为输出配置,接着才能输出低电平产生电势差才可以有电流
//GPIOF配置为输出
*(unsigned int *) (0x40021400+0x00) &=~( (0x03) << (2*8) ); //0x03代表的二进制是11,接着让他偏移12位,取反成00,其他的是1,
//然后就会跟之前没有修改的值进行一个位与的操作,因为原本的是0所以在改变其他的之后,其他的并没有原本就是1,故之后还是为0,但是改的那个地方的值已经是0了,所以在做了操作之后还是00
*(unsigned int *) (0x40021400+0x00) |= ( 1 << (2*8) );//偏移了地址取1之后,因为是位或操作,所以只要后边有一个是任何数,他就可以变成另一个数

*(unsigned int *) (0x40021400+0x00) &=~( (0x03) << (2*7) );
*(unsigned int *) (0x40021400+0x00) |= ( 1 << (2*7) );

*(unsigned int *) (0x40021400+0x00) &=~( (0x03) << (2*6) );
*(unsigned int *) (0x40021400+0x00) |= ( 1 << (2*6) );
///*PF6输出高电平*/
////*( unsigned int *) (0x40021400+0x14)|= (1<<8); //将1偏移6位,原本是0的就全部是0,然后这个修改之后的值会跟之前没有修改的值进行一个或的操作
////PF6输出低电平
//*(unsigned int *) (0x40021400+0x14) &= ~(1<<6); //将1偏移6位
// *(unsigned int *) (0x40021400+0x14) &= ~(1<<7);
// *(unsigned int *) (0x40021400+0x14) &= ~(1<<8);

while(1){

LED_B |= (1<<8);
Delay(10000000);
LED_B &= ~(1<<8);
Delay(10000000);

LED_G &= ~(1<<7);
Delay(10000000);
LED_G|= (1<<7);
Delay(10000000);

*(unsigned int *) (0x40021400+0x14) &= ~(1<<6);
Delay(10000000);
*( unsigned int *) (0x40021400+0x14)|= (1<<6);
Delay(10000000);

}

}


void SystemInit(){
/*这个函数为空,因为原来调用的库函数里边没有实现这个函数,写这个函数是为了骗过编译器不报错误*/

}


//作业:把其他灯也点亮
//实现三个灯闪烁(时间的控制使用软件延时)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询