stm32f407学习之路2

叠甲
        大家理性讨论 我要是作为一个初学者分享自己的学习思路 如果有说错的地方欢迎大家和我说

这个学习心得是基于b站一up的视频学习过程中一些问题得来的 我会将视频链接放在下面 大家可以去看完视频 如果有不懂的朋友再回来看我这个文章或许会解答你学习中的疑惑

大卫-史密斯的个人空间-大卫-史密斯个人主页-哔哩哔哩视频 (bilibili.com)

第二天 我们开始配置gpio 以及中断

配置gpio输出高低电平

首先我们配置gpio 先要了解他的大概结构 可能大家和我一样是初学者看手册非常的困难 所以我给大家说一下如何快速理解那么配置参数

GPIO_Pin:这个就是你要用哪个引脚

GPIO_Mode:这个就是你要用哪种模式 一共有4种模式:输入 ,输出, 复用(就是将使用权给其他硬件)模拟输入,

GPIO_OType:这个直接配置为 GPIO_OType_PP  基本上百分之99.99都使用这个模式 因为推挽输出的驱动能力非常强 不要管就配置这个模式

GPIO_PuPd:这个配置要不要上拉或者下拉 或者不拉 怎么配置呢 当你引脚外接设备时候电压是稳定的就可以不拉 但如果你外接设备时候电压不稳定 那么就可以上拉或者下拉 他们两的区别就是你引脚没工作时候上拉默认为高电平 下拉默认为低电平

GPIO_Speed:配置引脚响应速度 这个看你需求

这样我们的引脚就配置好了

但是最重要的一点是配置设备时候的思想是

第一步打开设备对应的硬件时钟

第二步配置设备的结构体 然后初始化

第三步使能设备(有些需要有些不需要)

在32的配置过程中基本上全是套用这个模式 所以这个思想比gpio的具体配置要重要 这个思想一直在smt32的学习中延续

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);

	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3	| GPIO_Pin_4 | GPIO_Pin_5;						
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;	
	GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;	
	GPIO_Init(GPIOB,&GPIO_InitStruct);

这里我将 3 4 5引脚配置为复用模式 推挽输出 无上下拉 高速模式

配置一个外部中断

我要配置一个当某个引脚电平发生变化时候产生中断 应该如何配置

你要配置外部中断 那么你就要接收信号 那么就要将引脚配置为输入模式来接收外面来的信  号 我exit可以和和pa1 pb1 pc1 连接 那么我这个一号引脚要和谁连接呢 你要告诉我 所以就要将exit与gpio连接起来 然后你exit是产生下降沿还是上升沿触发这些就要在exit结构体里面配置了 然后就要配置nvic nvic配置他是否同意你这个中断 有可能你给一个中断申请 nvic不同意呢 当所有的配置好了就可以产生中断 但产生中断函数你要在启动文件里面去找对应中断名的函数 现在来梳理一下思路

1使能gpio时钟

2配置gpio为输入模式

3初始化gpio

4使能exit时钟

5配置exit结构体

6初始化exit

7连接exit

8配置nvic结构体

9初始化nvic

10配置中断函数

可以看见 每一步都非常的公式话 stm32后续的配置也大差不差

#include "stm32f4xx.h"                  // Device header
#include "sys.h"

int flag=0;

void led_init(void);
void exit_init(void);
void delay(void);

int main (void)
{

	led_init();
	exit_init();
	while(1)
	{

	}
}

void EXTI0_IRQHandler(void)				//外部中断0服务函数
{
	//判断是否有中断请求
	if(EXTI_GetITStatus(EXTI_Line0) == SET)
	{
		delay();
		while(PAin(0) == 0);
		flag++;
		if(flag == 2)
		{
			PFout(9) = 1;
			flag = 0;
		}
		if(flag == 1)
		{
			PFout(9) = 0;
		}
		EXTI_ClearITPendingBit(EXTI_Line0);
		delay();
	}
}

void EXTI2_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line2) == SET)
	{
		delay();
		while(PEin(2) == 0);
		flag++;
		if(flag == 2)
		{
			PFout(10) = 1;
			flag = 0;
		}
		if(flag == 1)
		{
			PFout(10) = 0;
		}
		EXTI_ClearITPendingBit(EXTI_Line2);
		delay();
	}
}

void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3) == SET)
	{
		delay();
		while(PEin(3) == 0);
		flag++;
		if(flag == 2)
		{
			PEout(13) = 1;
			flag = 0;
		}
		if(flag == 1)
		{
			PEout(13) = 0;
		}
		EXTI_ClearITPendingBit(EXTI_Line3);
		delay();
	}
}

void EXTI4_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line4) == SET)
	{
		delay();
		while(PEin(4) == 0);
		flag++;
		if(flag == 2)
		{
			PEout(14) = 1;
			flag = 0;
		}
		if(flag == 1)
		{
			PEout(14) = 0;
		}
		EXTI_ClearITPendingBit(EXTI_Line4);
		delay();
	}
}

void delay(void)
{
	int i;
	int j;
	for( i=1000 ; i>0 ; i--)
		for( j=10000 ; j>0 ; j--);
		
}


void led_init(void)
{
	
	GPIO_InitTypeDef GPIO_InitStruct; 					//创建引脚配置结构体
	//使能端口 给他通电
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF , ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE , ENABLE);
	//配置gpio引脚模式
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10; 	//引脚号为10和9
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;			//配置为输出模式
	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;			//配置为推挽输出
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;			//配置无上拉无下拉
	GPIO_InitStruct.GPIO_Speed=GPIO_Medium_Speed;		//配置引脚速度
	
	GPIO_Init(GPIOF,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14; 	//引脚号为10和9
	
	GPIO_Init(GPIOE,&GPIO_InitStruct);
}




void exit_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct; //创建引脚配置结构体
	EXTI_InitTypeDef EXTI_InitStruct; //创建外部中断结构体
	NVIC_InitTypeDef NVIC_InitStruct; //创建nvic结构体 用于配置优先级中断优先级一些参数
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);//使能A端口时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE , ENABLE);//使能端口时钟
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);					//中断优先级分组
	//配置gpio引脚模式
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0; 							//选择pa0号引脚
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;							//配置为输入模式
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;							//配置无上拉无下拉
	GPIO_InitStruct.GPIO_Speed=GPIO_Medium_Speed;					//配置引脚速度
	GPIO_Init(GPIOA,&GPIO_InitStruct);								//初始化gpioa的0号引脚
	
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;	//选择pe2 3 4号引脚
	GPIO_Init(GPIOE,&GPIO_InitStruct);								//初始化gpioE的2 3 4号引脚
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG , ENABLE);//使能系统配置控制器的时钟
	
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA , EXTI_PinSource0);	//将PA0与exit0连接起来
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE , EXTI_PinSource2);	//将PE2与exit2连接起来
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE , EXTI_PinSource3);	//将PE3与exit3连接起来
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE , EXTI_PinSource4);	//将PE4与exit4连接起来
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line0 |EXTI_Line2 |EXTI_Line3 | EXTI_Line4;		//配置外部中断为exti_0
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;									//配值exit_0的模式为外部中断
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;								//触发方法为下降沿触发 (EXTI_Trigger_Rising:上升沿触发 	EXTI_Trigger_Falling:下降沿触发 EXTI_Trigger_Rising_Falling:双边沿触发)
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;											//使能exit_0 2 3 4;
	EXTI_Init(&EXTI_InitStruct);													//初始化exit_0 2 3 4
					
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0x03;												//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0x03;													//响应优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;															//使能
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn ;					//打开外部中断0的请求通道	
	NVIC_Init(&NVIC_InitStruct);									//初始化外部中断通道
	NVIC_InitStruct.NVIC_IRQChannel=EXTI2_IRQn ;					//打开外部中断2的请求通道		
	NVIC_Init(&NVIC_InitStruct);
	NVIC_InitStruct.NVIC_IRQChannel=EXTI3_IRQn;						//打开外部中断3的请求通道		
	NVIC_Init(&NVIC_InitStruct);
	NVIC_InitStruct.NVIC_IRQChannel=EXTI4_IRQn;						//打开外部中断4的请求通道		
	NVIC_Init(&NVIC_InitStruct);
}

定时器延时函数

这里直接使用就可以了 哪里需要就复制到哪里

void colock_ms(uint32_t x)
{
	while(x--)
	{
		SysTick->CTRL = 0; 								// 关闭系统定时器 这一步用来配置接下来的系统定时器的值
		SysTick->LOAD = 168000; 						// 配置计数值
		SysTick->VAL = 0; 								// 清空计数标志位 防止使用之前没有清空从而导致计数错误
		SysTick->CTRL = 5; 								// 5:0    1      0     1
														//         这个一表示使用的时钟源是系统时钟源 如果这个值是0表示使用的是系统时钟源/8分频的时钟源
														//						这个一表示使能系统时钟源
		while ((SysTick->CTRL & 0x00010000)==0);		// 判断这个标志位是否为1 如果到1了代表时间到了 没有就一直循环
	}
	SysTick->CTRL = 0; // Disable SysTick			//关闭系统定时器
}
void colock_us(uint32_t x)
{
	SysTick->CTRL = 0; 								// 关闭系统定时器 这一步用来配置接下来的系统定时器的值
	SysTick->LOAD = (168)*x; 						// 配置计数值
	SysTick->VAL = 0; 								// 清空计数标志位 防止使用之前没有清空从而导致计数错误
	SysTick->CTRL = 5; 								// 5:0    1      0     1
													//         这个一表示使用的时钟源是系统时钟源 如果这个值是0表示使用的是系统时钟源/8分频的时钟源
													//						这个一表示使能系统时钟源
	while ((SysTick->CTRL & 0x00010000)==0);		// 判断这个标志位是否为1 如果到1了代表时间到了 没有就一直循环
	SysTick->CTRL = 0; // Disable SysTick			//关闭系统定时器
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值