目录
外部中断概述
外部中断的一般配置步骤:
硬件连接图:
实验源码:
中途遇到问题printf打印中文乱码:
外部中断概述
STM32F1的每个IO口都可以作为外部中断输入。
STM32F1的中断控制器支持19个外部中断/事件请求:
线0~15:对应外部IO口的输入中断。
线16:连接到PVD输出。
线17:连接到RTC闹钟事件。
线18:连接到USB换醒事件。
每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。
STM32供IO使用的中断线只有16个,但是STM32F10x系列的IO口多达上百个,所以这里是用到了映射例如EXTI0能触发它的是GPIOA.0,GPIOB.0,GPIOC.0...等,EXTI1能触发它的是GPIOA.1,GPIOB.1,GPIOC....等。注意每一个时间只有一个IO口能映射到EXTIX里。
IO口外部中断在中断向量表中之分配了7个中断向量,也就是只能使用7个中断服务函数图 缺了EXTI0
从表中可以看出,外部中断线5~9分配一个中断向量,共用一个服务函数外部中断线10~15分配一个中断向量,共用一个中断服务函数。
中断函数列表:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
外部中断常用库函数
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
//设置IO口与中断线的映射关系
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
//初始中断线:触发方式等
void ITStatus EXTI_GetITStatus(uint32_ EXTI_Line);
//判断中断状态,是否发生
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
//清除中断线上的中断标志位
外部中断的一般配置步骤:
1.初始化IO口为输入
GPIO_Init();
2.开启IO口复用时钟
RCC_APB2PeriClockCmd(RCC_APB2Periph_AFIO,ENABLE);
3.设置IO口与中断线的映射关系
Void GPIO_EXTILineConfig();
4.初始化线上中断,设置触发条件等。
EXTI_Init();
5.配置中断分组(NVIC),并使能中断。
NVIC_Init();
6.编写中断服务函数。
EXTIx_IRQHandle();
7.清除中断标志位
EXTI_ClearITPendingBit();
硬件连接图:
实验源码:
实验用的是KEY0 因为一端是接地所以初始化为上拉输入(芯片内部接的是正极)
/*!
\brief RCC配置
\param[in] none
\param[out] none
\retval none
*/
void Rcc_config(void)
{
/*使能GPIOA时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/*使能GPIOE时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
/*使能复用外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
/*使能UART1时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
}
/*!
\brief GPIO初始化函数
\param[in] none
\param[out] none
\retval none
*/
void Gpio_Init(void)
{
/*GPIO结构体*/
GPIO_InitTypeDef GPIO_InitTypeDefstruct;
/*KEY2结构体配置*/
GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 没按下默认是高电平
GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_4; //引脚选择
/*初始化GPIOE Pin2 3 4*/
GPIO_Init(GPIOE,&GPIO_InitTypeDefstruct);
/*UART1发送引脚配置*/
GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复用输出
GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz;
/*写入结构体到GPIOA*/
GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct);
/*UART1接收引脚配置*/
GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz;
/*写入结构体到GPIOA*/
GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct);
}
/*!
\brief UART1初始化
\param[in] none
\param[out] none
\retval none
*/
void Uart1_Init(u32 bound)
{
/*UART结构体*/
USART_InitTypeDef USART_InitTypeDefstruct;
/*NVIC结构体*/
NVIC_InitTypeDef NVIC_InitTypeDefstruct;
/*UART结构体配置*/
USART_InitTypeDefstruct.USART_BaudRate = bound; //波特率
USART_InitTypeDefstruct.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //不使用硬件流
USART_InitTypeDefstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//发送接收使能
USART_InitTypeDefstruct.USART_Parity = USART_Parity_No; //不使用奇偶校验
USART_InitTypeDefstruct.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitTypeDefstruct.USART_WordLength = USART_WordLength_8b; //8个数据位
/*写入USART1*/
USART_Init(USART1,&USART_InitTypeDefstruct);
/*使能串口1*/
USART_Cmd(USART1,ENABLE);
/*中断配置*/
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //UART1接收缓冲区非空中断,接收中断
NVIC_InitTypeDefstruct.NVIC_IRQChannel= USART1_IRQn; //USART1中断通道
NVIC_InitTypeDefstruct.NVIC_IRQChannelCmd = ENABLE; //使能USART1中断
NVIC_InitTypeDefstruct.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
NVIC_InitTypeDefstruct.NVIC_IRQChannelSubPriority = 1;//子优先级
/*写入NVIC中*/
NVIC_Init(&NVIC_InitTypeDefstruct);
}
/*!
\brief UART1中断服务函数
\param[in] none
\param[out] none
\retval none
*/
void USART1_IRQHandler(void)
{
uint8_t Receive;
/*接收数据*/
Receive = USART_ReceiveData(USART1);
printf("UART1中断,值为:%x\r\n",Receive);
}
/*!
\brief EXTI初始化
\param[in] none
\param[out] none
\retval none
*/
void EXTIX_Init(void)
{
/*EXTI结构体*/
EXTI_InitTypeDef EXTI_InitStuct;
/*NVIC结构体*/
NVIC_InitTypeDef NVIC_InitTypeDefstruct;
/*映射IO口到EXTI线上*/
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
/*触发方式设置*/
EXTI_InitStuct.EXTI_Line = EXTI_Line4;//EXTI4
EXTI_InitStuct.EXTI_LineCmd = ENABLE; //使能
EXTI_InitStuct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStuct.EXTI_Trigger = EXTI_Trigger_Falling; //下降验触发 按键按下是低电平
/*触发方式写入*/
EXTI_Init(&EXTI_InitStuct);
/*中断配置*/
NVIC_InitTypeDefstruct.NVIC_IRQChannel= EXTI4_IRQn; //EXTI4中断通道
NVIC_InitTypeDefstruct.NVIC_IRQChannelCmd = ENABLE; //使能EXTI4中断
NVIC_InitTypeDefstruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitTypeDefstruct.NVIC_IRQChannelSubPriority = 1;//子优先级
/*写入NVIC中*/
NVIC_Init(&NVIC_InitTypeDefstruct);
}
/*!
\brief EXTI4中断服务函数
\param[in] none
\param[out] none
\retval none
*/
void EXTI4_IRQHandler(void)
{
/*消抖处理*/
delay_ms(10);
/*读取GPIOE.4电平低是按下*/
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
{
printf("外部中断触发,KEY0按下\r\n");//提示语句
}
/*清除EXTI4中断标志位*/
EXTI_ClearITPendingBit(EXTI_Line4);
}
int main(void)
{
/*配置系统中断分组为2位抢占2位响应*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*Rcc初始化*/
Rcc_config();
/*GPIO初始化*/
Gpio_Init();
/*UART1初始化*/
Uart1_Init(9600);
/*EXTI初始化*/
EXTIX_Init();
/*死循环*/
while(1){
};
}
中途遇到问题printf打印中文乱码:
1.排除是否波特率太高
2.查看用到printf.c文件是否使用的是UTF-8编码,使用UTF-8编码会出现中文乱码解决办法如下博客
USART串口printf重定向中文乱码_洛尘~~的博客-CSDN博客