• STM32 GPIO LED和蜂鸣器实现【第四天】



    原理图

    寄存器总图

    在这里插入图片描述

    启动 汇编
    在这里插入图片描述

    时钟树
    在这里插入图片描述

    一 、STM32大小说明

    栈大小:1024Kbyte
    堆大小:512byte
    单片机内存:192Kbyte CPU -> 寄存器->R0 =systemInit :初始化函数(配置) ->main执行主函数

    二、STM32时钟分析

    寄存器:寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成 在计算机领域,寄存器是CPU内部的元件,包括通用寄存器、专用寄存器和控制寄存器。寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。


    MCU: 微控制单元(MCU) ,又称单片微型计算机或者单片机,是把中央处理器(CPU)的频率与规格做适当缩减,并将内存(memory)、计数器(Timer)、 USB、A/D转换、UART(通用异步收发传输器)、PLC(可编程逻辑控制器)、 DMA(直接内存访问)等周边接口,甚至LCD驱动电路都整合在单一芯片上,形成芯片级的计算机,为不同的应用场合做不同组合控制。

    控制寄存器:相当一排可通过0/1进行设置外设功能的开关,程序中通过地址查找到对应的寄存器,所以说控制寄存器的地址是唯一。

    芯片时钟:芯片工作时,是需要脉冲,脉冲相当于给芯片起振,可保证芯片的正常工作,类似于人,心脏正常跳动,人体生命特征才能正常。

    1HZ:一秒产生1个脉冲
    频率换算单位:
    1GHZ =  1000MHZ = 1000 000KHZ = 1000 000 000HZ
    
    • 1
    • 2
    • 3

    STM32时钟源: 时钟源是可以产生器件。

    LSIRC    32KHZ    		32 kHz 低速内部 RC (LSIRC)
    LSEOSC  32.168KHZ		32.768 kHz 低速外部晶振( LSE 晶振)
    HSIRC	 16MHZ		   16MHZ  高速内部 RC (LSIRC)
    HSEOSC 4-26MHZ       4-26MHZ高速外部晶振(HSE 晶振) 
    
    • 1
    • 2
    • 3
    • 4

    粤嵌开发板外部晶振为8MHZ
    STM32主要总线时钟频率

    SYSCLK					168MHZ
    HCLK					   168MHZ
    AHB1/AHB2				168MHZ
    APB1					   42MHZ
    APB2					   84MHZ
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、GPIO分析

    GPIO: GPIO(英语:General-purpose input/output),通用型之输入输出) GPIO分组

    STM32F407ZET6(芯片型号)

        -  一共有7组IO口(PA  PB  PC  PD  PE  PF  PG)
        -  每组IO口有16个IO引脚
        -  一共16X7=112个IO引脚
    外加2个PH0和PH1
    一共114个IO口引脚(I:input  O:output)       IO引脚口:114
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    每组(PA PB PC PD PE PF PG)通用 I/O 端口包括:

    •4 个 32 位配置寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR 和 GPIOx_PUPDR)。
    •2 个 32 位数据寄存器(GPIOx_IDR 和 GPIOx_ODR)。
    •1 个 32 位置位/复位寄存器 (GPIOx_BSRR)、
    •1 个 32 位锁定寄存器(GPIOx_LCKR) 
    •2 个 32 位复用功能选择寄存器(GPIOx_AFRH 和 GPIOx_AFRL)。(高 低)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    GPIO工作方式(寄存器设置GPIO工作方式)

    4种输入模式

    `浮空输入(没有上下拉电阻)
    上拉输入(有上拉电阻)
    下拉输入(有下拉电阻)
    模拟输入`
    
    • 1
    • 2
    • 3
    • 4

    4种输出模式

    `开漏输出(带上拉或者下拉)
    开漏复用功能(带上拉或者下拉)
    推挽式输出(带上拉或者下拉)
    推挽是复用功能(带上拉或者下拉)`
    
    • 1
    • 2
    • 3
    • 4

    4种最大输出速度

    `2MHZ
    25MHZ
    50MHZ
    100MHZ`
    
    • 1
    • 2
    • 3
    • 4

    1.注意点

    开漏输出只能输出0(低电平),若想出输出1(高电平),需要外部接上拉电阻(类似到51单片机P0组)。
    推挽式输出可输出0(低电平)或者1(高电平),这是常用模式

    四、寄存器地址查找

    寄存器地址 = 寄存组基地址+偏移地址
    在这里插入图片描述


    在这里插入图片描述

    1、写出GPIOF外设的所有寄存器地址

    GPIOF_MODER    =  0x42001400 + 0x00 = 0x40021400
    GPIOF_OTYPER    =  0x42001400 + 0x04 = 0x40021404
    GPIOF_OSPEEDR  =  0x42001400 + 0x08 = 0x40021408
    GPIOF_PUPDR 	  =  0x42001400 + 0x0C = 0x4002140C
    GPIOF_IDR 	      =  0x42001400 + 0x10 = 0x40021410
    GPIOF_ODR 	  =  0x42001400 + 0x14 = 0x40021414
    GPIOF_BSRR 	  =  0x42001400 + 0x18 = 0x40021418
    GPIOF_LCKR 	  =  0x42001400 + 0x1C = 0x4002141C
    GPIOF_AFRL 	  =  0x42001400 + 0x20 = 0x40021420
    GPIOF_AFRH 	  =  0x42001400 + 0x24 = 0x4002142C
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    五、LED灯开发

    1、理解led灯原理图

    LED0连接在PF9
    PF9输出低电平(0), 灯亮;
    PF9输出高电平(1),灯灭;

    在这里插入图片描述

    2、打开GPIOF组时钟

    //将第5位置1 使能GPIOF组时钟 RCC_AHB1ENR |= (0x01<<5);

    设置PF9灯为输出模式 输出推挽上拉速度(50MHZ)

    4、通过GPIOF_BSRR控制LED灯亮与灭

    举例:

    ① 寄存器实现函数lcd.h RCC_AHB1ENR

    在这里插入图片描述

    5.设置时钟

    #define  RCC_AHB1ENR    (*((unsigned int *)(0x40023800+0x30)))  
    //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    • 1
    • 2

    设置端口模式 2y+1:2y y=寄存器的PFy

    在这里插入图片描述

    #define GPIOF_MODER   (*((unsigned int *)(0x40021400+0x00)))  
    //值强制类型转为地址,通过地址解引用,访问地址空间的值 //板子灯:D1   D2
    #define GPIOE_MODER   (*((unsigned int *)(0x40021000+0x00))) 
     //值强制类型转为地址,通过地址解引用,访问地址空间的值 //板子灯:D3  D4
    
    • 1
    • 2
    • 3
    • 4

    6.设置输出类型

    在这里插入图片描述

    #define GPIOF_OTYPER  (*((unsigned int *)(0x40021400+0x04))) 
     //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OTYPER  (*((unsigned int *)(0x40021000+0x04)))  
    //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    • 1
    • 2
    • 3
    • 4

    设置端口速度 2y:2y+1 y=要配置的操作位
    在这里插入图片描述

    #define GPIOF_OSPEEDR   (*((unsigned int *)(0x40021400+0x08))) 
     //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OSPEEDR   (*((unsigned int *)(0x40021000+0x08))) 
     //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    • 1
    • 2
    • 3
    • 4

    7.设置上拉电阻

    在这里插入图片描述

    #define GPIOF_PUPDR   (*((unsigned int *)(0x40021400+0x0C)))  
    //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_PUPDR   (*((unsigned int *)(0x40021000+0x0C)))  
    //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    GPIOF_BSRR设置输出控制

    #define GPIOF_ODR     (*((unsigned int *)(0x40021400+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_ODR     (*((unsigned int *)(0x40021000+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    • 1
    • 2

    GPIOF_BSRR设置控制位 灯亮和蜂鸣器

    #define GPIOF_BSRR    (*((unsigned int *)(0x40021400+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_BSRR    (*((unsigned int *)(0x40021000+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    • 1
    • 2

    举例

    #ifndef __LED_H
    #define __LED_H
    
    #include "stm32f4xx.h"
    //设置时钟
    #define RCC_AHB1ENR   (*((unsigned int *)(0x40023800+0x30)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    #define GPIOF_MODER   (*((unsigned int *)(0x40021400+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_OTYPER  (*((unsigned int *)(0x40021400+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_OSPEEDR (*((unsigned int *)(0x40021400+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_PUPDR   (*((unsigned int *)(0x40021400+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_ODR     (*((unsigned int *)(0x40021400+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_BSRR    (*((unsigned int *)(0x40021400+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    #define GPIOE_MODER   (*((unsigned int *)(0x40021000+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OTYPER  (*((unsigned int *)(0x40021000+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OSPEEDR (*((unsigned int *)(0x40021000+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_PUPDR   (*((unsigned int *)(0x40021000+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_ODR     (*((unsigned int *)(0x40021000+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_BSRR    (*((unsigned int *)(0x40021000+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    void Led_Init(void);
    
    //分别初始化各个D1 -- D4的灯函数
    void Led0(void);
    void Led1(void);
    void Led2(void);
    void Led3(void);
    void Beep(void);  //蜂鸣器
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    ② 寄存器实现函数lcd.c

    void Led0()   //针对D1  D2灯  GPIOF_XXXX形式
    {
    	//设置GPIOF9为输出模式 
    	GPIOF_MODER &= ~(0x01<<19);	  //19位清0
    	GPIOF_MODER |= (0x01<<18);	  //18位置1
    
    	//设置GPIOF9为输出推挽
    	GPIOF_OTYPER &= ~(0x01<<9);  	//9位清0
    	
    	//设置GPIOF9为上拉
    	GPIOF_PUPDR &= ~(0x01<<19);  	//19位清0
    	GPIOF_PUPDR |= (0x01<<18);	  //18位置1	
    	
    	//设置GPIOF9输出速度50MHZ
    	GPIOF_OSPEEDR |= (0x01<<19);	//19位置1
    	GPIOF_OSPEEDR &= ~(0x01<<18);	//18位清0
    }
    //***************************************************************************************
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    void Led2()  //针对D1  D2灯  GPIOE_XXXX形式
    {
    
    	//设置GPIOF13为输出模式
    	GPIOE_MODER &= ~(0x01<<27);		 //27位清0
    	GPIOE_MODER |= (0x01<<26);		 //26位置1
    	
    	//设置GPIOE输出速度为50MHZ
    	GPIOE_OSPEEDR |= (0x01<<26);   //26位置1
    	GPIOE_OSPEEDR &= ~(0x01<<27);  //27为清0
    	 
    	//设置GPIOE为上拉
    	GPIOE_PUPDR &= ~(0x01<<27);    //27位清0
    	GPIOE_PUPDR |= (0x01<<26);		 //26位置1
    	
    	//设置GPIOE为输出推挽
    	GPIOE_OTYPER &= ~(0x01<<13); 	 //13位清0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    解释:模式 速度 上拉 操作的对应位

    D1(19 - 18位) D2 (21 -20):设置相关参数
    D3(27 - 26位) D4 (29 -28):设置相关参数
    
    • 1
    • 2

    解释:推挽 GPIOF_OTYPER 操作的对应位0

    D1(9位清0) D2 (10位清0)
    D3(13位清0) D4 (14位清0)
    
    • 1
    • 2

    ③ 寄存器实现函数main.c GPIOX_BSRR->ODR

    板子:D1 --D2灯 GPIOF_BSRR

    `
    BSRR 25位置1  ODR输出0  Led0灯亮 D1亮
    BSRR  9位置1  ODR输出1  Led0灯灭 D1灭
    BSRR 26位置1  ODR输出0  Led1灯亮 D2亮
    BSRR 10位置1  ODR输出1  Led1灯灭 D2灭
    `
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    板子:D3 --D4灯 GPIOE_BSRR

    `
    BSRR  29位置1  ODR输出0  Led2灯亮 D3亮
    BSRR  13位置1  ODR输出1  Led2灯灭 D3灭
    BSRR  30位置1  ODR输出0  Led3灯亮 D4亮
    BSRR  14位置1  ODR输出1  Led3灯灭 D4灭
    `
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    六、蜂鸣器

    蜂鸣器位的控制 复位和置位BSRR

    `
    //BSRR 24位置1  ODR输出0  蜂鸣器关
    GPIOE_BSRR |= (0x01<<24);
    //BSRR 8位置1  ODR输出1   蜂鸣器开
    GPIOE_BSRR |= (0x01<<8);
    `
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    七、问题上、下拉电阻作用

    > 1、请解释上、下拉电阻作用

    上拉就是将不确定的信号通过一个电阻钳位在高电平,电阻同时起限流作用。【灌电流】
    1、当TTL电路驱动CMOS电路时,如果电路输出的高电平低于CMOS电路的最低高电平(一般为3.5V),
    这时就需要在TTL的输出端接上拉电阻,以提高输出高电平的值。U=IR 2、OC门电路必须使用上拉电阻,以提高输出的高电平值。
    3、为增强输出引脚的驱动能力,有的单片机管脚上也常使用上拉电阻。
    4、在CMOS芯片上,为了防止静电造成损坏,不用的管脚不能悬空,一般接上拉电阻以降低输入阻抗, 提供泄荷通路。
    5、芯片的管脚加上拉电阻来提高输出电平,从而提高芯片输入信号的噪声容限,增强抗干扰能力。
    6、提高总线的抗电磁干扰能力,管脚悬空就比较容易接受外界的电磁干扰。
    7、长线传输中电阻不匹配容易引起反射波干扰,加上、下拉电阻是电阻匹配,有效的抑制反射波干扰。


    下拉电阻是直接接到地上,接二极管的时候电阻末端是低电平。【拉电流】
    1、提高电压准位 同时管脚悬空就比较容易接受外界的电磁干扰。
    2、电阻匹配,抑制反射波干扰:长线传输中电阻不匹配容易引起反射波干扰,加上下拉电阻是电阻匹配,有效的抑制反射波干扰。
    3、预设空间状态/缺省电位:在一些 CMOS 输入端接上或下拉电阻是为了预设缺省电位。 当你不用这些引脚的时候, 这些输入端下拉接 0
    或上拉接 1。在I2C总线等总线上,空闲时的状态是由上下拉电阻获得
    4、提高芯片输入信号的噪声容限:输入端如果是高阻状态,或者高阻抗输入端处于悬空状态,此时需要加上拉或下拉,以免收到随机电平而影响电路工作。

    七、流水灯代码

    MAIN.C

    #include "stm32f4xx.h"
    #include "led.h"
    void delay(int n)
    {
    	int i,j;
    	
    	for(i=0; i<n; i++)
    		for(j=0; j<30000; j++);
    
    }
    int main(void)
    {
    	Led_Init(); //初始化led
    	
    	while(1)
    	{
    		//BSRR 25位置1  ODR输出0  Led0灯亮
    		GPIOF_BSRR |= (0x01<<25);
    		delay(1000);
    		
    		//BSRR 9位置1  ODR输出1  灯灭
    		GPIOF_BSRR |= (0x01<<9);
    		//delay(1000);
    		
    		//BSRR 26位置1  ODR输出0  Led1灯亮
    		GPIOF_BSRR |= (0x01<<26);
    		delay(1000);
    		
    		//BSRR 10位置1  ODR输出1  灯灭
    		GPIOF_BSRR |= (0x01<<10);
    		//delay(1000);
    		
    		//BSRR 29位置1  ODR输出0  Led2灯亮
    		GPIOE_BSRR |= (0x01<<29);
    		delay(1000);
    		
    		//BSRR 13位置1  ODR输出1  灯灭
    		GPIOE_BSRR |= (0x01<<13);
    		//delay(1000);
    		
    		//BSRR 30位置1  ODR输出0  Led3灯亮
    		GPIOE_BSRR |= (0x01<<30);
    		delay(1000);
    		
    		//BSRR 14位置1  ODR输出1  灯灭
    		GPIOE_BSRR |= (0x01<<14);
    		delay(1000);
    
    	}
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    LED.H

    #ifndef __LED_H
    #define __LED_H
    
    #include "stm32f4xx.h"
    
    //设置时钟
    #define RCC_AHB1ENR   (*((unsigned int *)(0x40023800+0x30)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    #define GPIOF_MODER   (*((unsigned int *)(0x40021400+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_OTYPER  (*((unsigned int *)(0x40021400+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_OSPEEDR (*((unsigned int *)(0x40021400+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_PUPDR   (*((unsigned int *)(0x40021400+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_ODR     (*((unsigned int *)(0x40021400+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_BSRR    (*((unsigned int *)(0x40021400+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    #define GPIOE_MODER   (*((unsigned int *)(0x40021000+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OTYPER  (*((unsigned int *)(0x40021000+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OSPEEDR (*((unsigned int *)(0x40021000+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_PUPDR   (*((unsigned int *)(0x40021000+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_ODR     (*((unsigned int *)(0x40021000+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_BSRR    (*((unsigned int *)(0x40021000+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    void Led_Init(void);
    
    //分别初始化各个D1 -- D4的灯函数
    void Led0(void);
    void Led1(void);
    void Led2(void);
    void Led3(void);
    //void Beep(void);
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    LED.C

    #include "led.h"
    
    void Led_Init(void)
    {
    	//将第5位置1  使能GPIOF组时钟
    	RCC_AHB1ENR |= (0x01<<5);
    	
    	//将第4位置1  使能GPIOE组时钟
    	RCC_AHB1ENR |= (0x01<<4);
    	
    	Led0();
    	Led1();
    	Led2();
    	Led3();
    	
    }
    /*********************************
    引脚说明:
    
    LED0 -- PF9
    
    **********************************/
    void Led0()
    {
    	//设置GPIOF9为输出模式 
    	GPIOF_MODER &= ~(0x01<<19);	  //19位清0
    	GPIOF_MODER |= (0x01<<18);	  //18位置1
    
    	//设置GPIOF9为输出推挽
    	GPIOF_OTYPER &= ~(0x01<<9);  	//9位清0
    	
    	//设置GPIOF9为上拉
    	GPIOF_PUPDR &= ~(0x01<<19);  	//19位清0
    	GPIOF_PUPDR |= (0x01<<18);	  //18位置1	
    	
    	//设置GPIOF9输出速度50MHZ
    	GPIOF_OSPEEDR |= (0x01<<19);	//19位置1
    	GPIOF_OSPEEDR &= ~(0x01<<18);	//18位清0
    }
    /*********************************
    引脚说明:
    
    LED1 -- PF10
    
    **********************************/
    void Led1()
    {
    	//设置GPIOF10为输出模式
    	GPIOF_MODER &= ~(0x01<<21);	  //21位清0
    	GPIOF_MODER |= (0x01<<20);	  //20位置1
    
    	//设置GPIOF9为输出推挽
    	GPIOF_OTYPER &= ~(0x01<<10);	//10位清0
    	
    	//设置GPIOF9为上拉
    	GPIOF_PUPDR &= ~(0x01<<21);	  //21位清0
    	GPIOF_PUPDR |= (0x01<<20);	  //20位置1	
    	
    	//设置GPIOF9输出速度50MHZ
    	GPIOF_OSPEEDR |= (0x01<<21);	//21位置1
    	GPIOF_OSPEEDR &= ~(0x01<<20);	//20位清0
    }
    /*********************************
    引脚说明:
    
    LED2 -- PE13
    
    **********************************/
    void Led2()
    {
    	//将第4位置1  使能GPIOE组时钟
    	//RCC_AHB1ENR |= (0x01<<4);
    	
    	//设置GPIOF13为输出模式
    	GPIOE_MODER &= ~(0x01<<27);		 //27位清0
    	GPIOE_MODER |= (0x01<<26);		 //26位置1
    	
    	//设置GPIOE输出速度为50MHZ
    	GPIOE_OSPEEDR |= (0x01<<26);   //26位置1
    	GPIOE_OSPEEDR &= ~(0x01<<27);  //27为清0
    	 
    	//设置GPIOE为上拉
    	GPIOE_PUPDR &= ~(0x01<<27);    //27位清0
    	GPIOE_PUPDR |= (0x01<<26);		 //26位置1
    	
    	//设置GPIOE为输出推挽
    	GPIOE_OTYPER &= ~(0x01<<13); 	 //13位清0
    }
    
    /*********************************
    引脚说明:
    
    LED3 -- PE14
    
    **********************************/
    void Led3()
    {
    	//设置GPIOE14为输出模式
    	GPIOE_MODER &= ~(0x01<<29);	   //29位清0
    	GPIOE_MODER |= (0x01<<28);	   //28位置1
    	
    	//设置GPIOE输出速度为50MHZ
    	GPIOE_OSPEEDR |= (0x01<<28);   //28位置1
    	GPIOE_OSPEEDR &= ~(0x01<<29);  //29为清0
    	
    	//设置GPIOE为上拉
    	GPIOE_PUPDR &= ~(0x01<<29);    //29位清0
    	GPIOE_PUPDR |= (0x01<<28);     //28位置1
    	
    	//设置GPIOE为输出推挽
    	GPIOE_OTYPER &= ~(0x01<<14);   //14位清0
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114

    八、蜂鸣器代码

    main.c

    #include "stm32f4xx.h"
    #include "led.h"
    
    void delay(int n)
    {
    	int i,j;
    	
    	for(i=0; i<n; i++)
    		for(j=0; j<30000; j++);
    
    }
    int main(void)
    {
    	Led_Init();
    	while(1)
    	{
    	
    		GPIOF_BSRR |= (0x01<<8);  //开  
    		delay(3000);
    		GPIOF_BSRR |= (0x01<<24); //关
    		
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Led.c

    #ifndef __LED_H
    #define __LED_H
    
    #include "stm32f4xx.h"
    
    //设置时钟
    #define RCC_AHB1ENR   (*((unsigned int *)(0x40023800+0x30)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    #define GPIOF_MODER   (*((unsigned int *)(0x40021400+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_OTYPER  (*((unsigned int *)(0x40021400+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_OSPEEDR (*((unsigned int *)(0x40021400+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_PUPDR   (*((unsigned int *)(0x40021400+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_ODR     (*((unsigned int *)(0x40021400+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOF_BSRR    (*((unsigned int *)(0x40021400+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    #define GPIOE_MODER   (*((unsigned int *)(0x40021000+0x00)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OTYPER  (*((unsigned int *)(0x40021000+0x04)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_OSPEEDR (*((unsigned int *)(0x40021000+0x08)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_PUPDR   (*((unsigned int *)(0x40021000+0x0C)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_ODR     (*((unsigned int *)(0x40021000+0x14)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    #define GPIOE_BSRR    (*((unsigned int *)(0x40021000+0x18)))  //值强制类型转为地址,通过地址解引用,访问地址空间的值
    
    void Led_Init(void);
    
    //分别初始化各个D1 -- D4的灯函数
    void Led0(void);
    void Led1(void);
    void Led2(void);
    void Led3(void);
    void Beep(void);
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    led.c

    
    #include "led.h"
    
    void Led_Init(void)
    {
    	//将第5位置1  使能GPIOF组时钟
    	RCC_AHB1ENR |= (0x01<<5);
    	
    	//将第4位置1  使能GPIOE组时钟
    	RCC_AHB1ENR |= (0x01<<4);
    	
    	Led0();
    	Led1();
    	Led2();
    	Led3();
    	Beep();
    	
    }
    /*********************************
    引脚说明:
    
    LED0 -- PF9
    
    **********************************/
    void Led0()
    {
    	//设置GPIOF9为输出模式 
    	GPIOF_MODER &= ~(0x01<<19);	  //19位清0
    	GPIOF_MODER |= (0x01<<18);	  //18位置1
    
    	//设置GPIOF9为输出推挽
    	GPIOF_OTYPER &= ~(0x01<<9);  	//9位清0
    	
    	//设置GPIOF9为上拉
    	GPIOF_PUPDR &= ~(0x01<<19);  	//19位清0
    	GPIOF_PUPDR |= (0x01<<18);	  //18位置1	
    	
    	//设置GPIOF9输出速度50MHZ
    	GPIOF_OSPEEDR |= (0x01<<19);	//19位置1
    	GPIOF_OSPEEDR &= ~(0x01<<18);	//18位清0
    }
    /*********************************
    引脚说明:
    
    LED1 -- PF10
    
    **********************************/
    void Led1()
    {
    	//设置GPIOF10为输出模式
    	GPIOF_MODER &= ~(0x01<<21);	  //21位清0
    	GPIOF_MODER |= (0x01<<20);	  //20位置1
    
    	//设置GPIOF9为输出推挽
    	GPIOF_OTYPER &= ~(0x01<<10);	//10位清0
    	
    	//设置GPIOF9为上拉
    	GPIOF_PUPDR &= ~(0x01<<21);	  //21位清0
    	GPIOF_PUPDR |= (0x01<<20);	  //20位置1	
    	
    	//设置GPIOF9输出速度50MHZ
    	GPIOF_OSPEEDR |= (0x01<<21);	//21位置1
    	GPIOF_OSPEEDR &= ~(0x01<<20);	//20位清0
    }
    /*********************************
    引脚说明:
    
    LED2 -- PE13
    
    **********************************/
    void Led2()
    {
    	//将第4位置1  使能GPIOE组时钟
    	//RCC_AHB1ENR |= (0x01<<4);
    	
    	//设置GPIOF13为输出模式
    	GPIOE_MODER &= ~(0x01<<27);		 //27位清0
    	GPIOE_MODER |= (0x01<<26);		 //26位置1
    	
    	//设置GPIOE输出速度为50MHZ
    	GPIOE_OSPEEDR |= (0x01<<26);   //26位置1
    	GPIOE_OSPEEDR &= ~(0x01<<27);  //27为清0
    	 
    	//设置GPIOE为上拉
    	GPIOE_PUPDR &= ~(0x01<<27);    //27位清0
    	GPIOE_PUPDR |= (0x01<<26);		 //26位置1
    	
    	//设置GPIOE为输出推挽
    	GPIOE_OTYPER &= ~(0x01<<13); 	 //13位清0
    }
    
    /*********************************
    引脚说明:
    
    LED3 -- PE14
    
    **********************************/
    void Led3()
    {
    	//设置GPIOE14为输出模式
    	GPIOE_MODER &= ~(0x01<<29);	   //29位清0
    	GPIOE_MODER |= (0x01<<28);	   //28位置1
    	
    	//设置GPIOE输出速度为50MHZ   2y:2y   2*14:2*14+1   28:29  
    	GPIOE_OSPEEDR |= (0x01<<28);   //28位置1
    	GPIOE_OSPEEDR &= ~(0x01<<29);  //29为清0
    	
    	//设置GPIOE为上拉
    	GPIOE_PUPDR &= ~(0x01<<29);    //29位清0
    	GPIOE_PUPDR |= (0x01<<28);     //28位置1
    	
    	//设置GPIOE为输出推挽
    	GPIOE_OTYPER &= ~(0x01<<14);   //14位清0
    }
    //设置蜂鸣器
    void Beep(void)
    {
    	//设置GPIOE8为01  输出模式
    	GPIOF_MODER &= ~(0x01<<17);	   //0
    	GPIOF_MODER |= (0x01<<16);	   //1
    	
    	//设置GPIOE输出速度为50MHZ  
    	GPIOF_OSPEEDR |= (0x01<<17);   //1
    	GPIOF_OSPEEDR &= ~(0x01<<16);  //0
    	
    	//设置GPIOE为上拉
    	GPIOF_PUPDR &= ~(0x01<<17);    //0
    	GPIOF_PUPDR |= (0x01<<16);     //1
    	
    	//设置GPIOE为输出推挽
    	GPIOF_OTYPER &= ~(0x01<<24);   //0
    	
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
  • 相关阅读:
    接口自动化测试总结
    Java实现图书管理系统
    【密码学篇】虚拟专用网技术原理与应用(商密)
    JavaScript模块导入与编程
    快速了解员工脉动调查
    Java进程退出
    Edge浏览器下载文件提示 “无法安全下载” 的解决方法
    JSP plugin动作
    C语言实例_调用SQLITE数据库完成数据增删改查
    MySQL执行计划EXPLAIN
  • 原文地址:https://blog.csdn.net/m0_45463480/article/details/126109398