一、外部中断介绍
1.EXTI 基本结构
2.中断/事件线
EXTI有 20个中断/事件线,每个 GPIO都可以被设置为输入线,每个输入线的来源如图所示:
从图中可以看出STM32的外部中断只有16个,又是怎么使每个GPIO都可以实现中断了,通过编程控制可以实现任意一个 GPIO作为 EXTI的输入源。
从上图可知EXTI0 可以通过 AFIO 的外部中断配置寄存器 1(AFIO_EXTICR1)的EXTI0[3:0]位选择配置为 PA0、PB0、PC0、PD0、PE0、PF0、PG0,其他 EXTI线(EXTI中断/事件线)使用配置都是类似的。
二、GPIO外部中断的配置
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET)
{
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
三、串口的介绍
串口是单片机中最常用也是最简单的一种通信方式通信:两个或两个以上的设备进行数据交换
串口是用于两个设备之间的异步全双工通信
异步---->两个设备不需要共时钟
全双工---->两个设备之间服务于数据交换的“线”有两根
Tx:数据发送端,用于发送数据
Rx:数据接收端,用于接收数据
在使用串口进行通信时,要求通信双方必须在“同频道” “同频道” =》 相同的通信协议,同时双方需要共地,也就是GND相连
串口(USART)约定:通信时数据必须以“帧”的形式传递串口的一帧数据包括:起始位 + 数据位 + 校验位 + 停止位
其中:
1)起始位:固定是1个周期的低电平信号
2)数据位:可由通信双方自行约定是 5 ~ 9 bits
3)校验位:串口采用的是奇偶校验,可由通信双方自行约定
4)停止位:可选的 0.5 ~ 2 个周期的高电平
同时,为了同步通信双发的收发速度,还需要约定每秒钟传输的数据帧的数量,称为 波特率,典型波特率有9600 115200 57600 ……
四、串口的配置方法
1.配置RX/TX
GPIO_InitTypeDef GPIO_InitStruct;
/* 配置GPIO引脚复用为 Rx Tx */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GP IOA,ENABLE); //使能GPIOA组时钟
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; 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_Speed_100MHz; GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,G PIO_AF_USART1); //PA9 -> USART1_Tx
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10, GPIO_AF_USART1);//PA10-> USART1_Rx
/* 配置USART1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_US ART1,ENABLE); //使能USART1的时钟(USART1 在APB2总线上)
USART_InitStruct.USART_BaudRate = 9600; //指定波特率
USART_InitStruct.USART_WordLength= USART_WordLength_8b; //指定数据位长度(通 常是8bits)
USART_InitStruct.USART_Parity = USART_Parity_No; //指定校验方式(通常不校验)
USART_InitStruct.USART_StopBits = USART_StopBits_1; //指定停止位(通常是1个停止)
USART_InitStruct.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; //指定收发模式
USART_InitStruct.USART_HardwareFlowContr ol = USART_HardwareFlowControl_None;//指定硬件控制流(通常不要)
USART_Init(USART1,&USART_InitStruct);
/* 开启串口,就可以开始通信 */
USART_Cmd(USART1,ENABLE);
//通过USART1发送1个字节
void usart1_send_byte(char data)
{
//USART_GetFlagStatus 用来获取串口SR寄 存器中的指定标志位
//获取TXE标志,判断其是否被设置(SET) while(USART_GetFlagStatus(USART1,USART_F LAG_TXE) != SET);
//USART_SendData 用来通过指定串口发送数 据 USART_SendData(USART1,data);
}
char usart1_recv_byte(void)
{
char ch = 0;
while(USART_GetFlagStatus(USART1,USART_F LAG_RXNE) != SET);
ch = USART_ReceiveData(USART1);
return ch;
}
2.串口接收中断
/* 配置串口1的接收中断 */ USART_ITConfig(USART1,USART_IT_RXNE,ENABL E); //USART_IT_RXNE接收数据寄存器不为空时产生 中断
/* 配置NVIC中断控制器 */
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; //指定中断通道 xxx_IRQn
NVIC_InitStruct.NVIC_IRQChannelPreemption Priority = 2;//抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriorit y = 2;//子优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
char ch = 0;
void USART1_IRQHandler(void)
{
//判断是由 RXNE接收数据寄存器非空 产生的中断 if(USART_GetITStatus(USART1,USART_IT_RXN E) == SET)
{
ch = USART_ReceiveData(USART1); //接收1个字节的数据
USART_ClearITPendingBit(USART1,USART_IT_ RXNE);//清除中断标志
}
}