目录
一.IO口输出实验--点灯
GPIO常用库函数
- 1个初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
- 2个读取输入电平函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
- 2个读取输出电平函数
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
- 4个设置输出电平函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
点灯步骤及代码
1.使能io口时钟,调用函数
void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
2.初始化io口模式,调用函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
3.操作io口,输出高低电平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
led.c
void Led_Init(void)
{
//库函数初始化步骤1:定义一个xxx_InitTypeDef类型的初始化结构体
GPIO_InitTypeDef GPIO_InitStruct;//可goto到该结构体查看成员
//使能GPIO F组时钟,
//RCC_AHB1ENR |= (0x01<<5);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
//库函数初始化步骤2:根据使用要求,向这些初始化结构体的成员写入特定的控制参数
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //引脚9
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //快速
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOF, &GPIO_InitStruct);
}
main.c
//延时函数
void delay(int n)
{
int i, j;
for(i=0; i<n; i++)
for(j=0; j<40000; j++);
}
int main(void)
{
//LED灯初始化
Led_Init();
while(1)
{
GPIO_SetBits(GPIOF,GPIO_Pin_9); //PF9置1 灯灭
delay(1000);
GPIO_ResetBits(GPIOF,GPIO_Pin_9);//PF9置0 灯亮
delay(1000);
}
return 0;
}
二.外部中断实验--按键中断
外部中断常用库函数
void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);
//设置IO口与中断线的映射关系
example: SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
//初始化中断线:触发方式等
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
//判断中断线中断状态,是否发生
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
//清除中断线上的中断标志位
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
//这个函数非常重要,在使用外部中断的时候一定要先使能SYSCFG时钟
外部中断步骤及代码
- 使能SYSCFG时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- 初始化IO口为输入。
GPIO_Init();
- 设置IO口与中断线的映射关系。
void SYSCFG_EXTILineConfig();
- 初始化线上中断,设置触发条件等。
EXTI_Init();
- 配置中断分组(NVIC),并使能中断。
NVIC_Init();
- 编写中断服务函数。
EXTIx_IRQHandler();
- 清除中断标志位
EXTI_ClearITPendingBit();
exit.c
//按键1中断配置
void Exti_PA0_Init(void)
{
//库函数初始化步骤1:定义一个xxx_InitTypeDef类型的初始化结构体
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//☆☆☆使能GPIO A组时钟:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//☆☆☆使能SYSCFG时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//库函数初始化步骤2:根据使用要求,向这些初始化结构体的成员写入特定的控制参数
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; //引脚0
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; //输入模式
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA, &GPIO_InitStruct);
//设置IO口与中断线的映射关系。PA0对应中断线0,详细看上图
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
EXTI_InitStruct.EXTI_Line = EXTI_Line0; //中断线0 (可变)
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
//可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)
EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Falling; //下降沿触发
EXTI_InitStruct.EXTI_LineCmd= ENABLE; //中断线使能
//初始化线上中断,设置触发条件等。
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; //NVIC通道,在stm32f4xx.h可查看通道 (可变)
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; //响应优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
//配置中断分组(NVIC),并使能中断。
NVIC_Init(&NVIC_InitStruct);
}
//编写中断服务函数。这个函数不需要程序员在主函数调用,满足条件CPU自行调用的函数
void EXTI0_IRQHandler(void)
{
//判断中断标志是否为1 ☆☆☆消抖
if(EXTI_GetITStatus(EXTI_Line0)) //判断是EXTI0中断线进来的。一般用于防止例如EXTI5-9共用一个服务函数的情况
{
delay_ms(15);
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET)
{
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0)
{
//变更灯状态
GPIO_ToggleBits(GPIOF, GPIO_Pin_9);
}
// 清除中断标志位
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
}
main.c
#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
int main(void)
{
//NVIC分组(一个工程当中只能配置一次分组)抢占优先级2位,值范围:0~3;响应优先级2位,值范围:0~3;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//LED灯初始化
Led_Init();
Exti_PA0_Init();
while(1)
{
//delayms(15);
}
return 0;
}
三.通用定时器--定时器中断
通用定时器概述
STM32F4 的定时器有14个,其中TIM2-TIM5,TIM9~TIM14属于通用定时器,TIM1 和TIM8 则属于高级控制定时器,TIM6和TIM7是基本定时器。
定时器配置中断的步骤及代码
- 使能定时器时钟。
RCC_APB1PeriphClockCmd();
- 初始化定时器,配置ARR,PSC。
TIM_TimeBaseInit();
- 启定时器中断,配置NVIC。
NVIC_Init();
- 设置 TIM3_DIER 允许更新中断。
TIM_ITConfig();
- 使能定时器。
TIM_Cmd();
- 编写中断服务函数。
TIMx_IRQHandler();
以TIM3为例,延时1秒点亮led灯
tim.c
#include "tim.h"
/*
定时器说明:
TIM3 -- APB1
定时器TIM3:84MHZ
16位定时器:值范围:0~65535
*/
void Tim3_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//1、使能定时器时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//8400分频 84000 000/8400 = 10000HZ 1S数10000个数
TIM_TimeBaseInitStruct.TIM_Prescaler = 8400-1;
TIM_TimeBaseInitStruct.TIM_Period = 10000-1; //计10000个数 在10000HZ下,用时1s
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1; //分频因子
//2、初始化定时器,配置ARR,PSC。
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
//NVIC通道,在stm32f4xx.h可查看通道 (可变)
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; //响应优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
//3、启定时器中断,配置NVIC。
NVIC_Init(&NVIC_InitStruct);
//4、设置 TIM3_DIER 允许更新中断
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
//5、使能定时器。
TIM_Cmd(TIM3, ENABLE);
}
//编写中断服务函数。这个函数不需要程序员在主函数调用,满足条件CPU自行调用的函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
{
/*处理的程序段*/
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
原文链接:https://blog.csdn.net/wprpr/article/details/108046684