前言
前面介绍的串口通信的方式主要有3种
- 轮询方式的串口通信
- 中断方式的串口通信
- DMA方式的串口通信
这里我将介绍的是中断方式的串口通信,相较于之前的轮询式的串口通信,中断式的串口通信有许多的优点,当接收或者发送一个数据时就申请中断,同时cpu可以执行其它任务,CPU的利用率更高了。
提示:以下是本篇文章正文内容,下面案例可供参考
一、什么是串口通信
关于什么是串口通信这里就不过多的赘述了,因为我前面的博客都有说明,如果还不明白的可以去看看我之前的博客。
链接 : https://blog.csdn.net/wer4567/article/details/127374342?spm=1001.2014.3001.5501
二、什么是中断——STM32
大家可能还不是很了解什么是中断,这里我就来介绍介绍有关中断的相关知识,以及stm32下的中断的一些说明。
1.中断的概念
- 中断实质上就是在CPU正常执行程序时,遇到了内部或者外部的异常情况需要紧急处理,CPU暂时停止正在运行的程序,转而去处理发生的异常事件,当该异常事件处理完毕之后又返回之前暂停的程序处继续执行。**举个简单的例子:**当你在看电视的时候,你妈叫你去买酱油,你妈叫你买酱油就是发生的异常事件,当你买完酱油回来又继续看你的电视。
- STM32F10x芯片内有84个
中断通道 ,包括16个内核中断和68个可屏蔽中断,这些中断通道已经按照不同优先级顺序固定分配相应的外部设备。这一部分就不过多说明,大家可以自己去参考《stm32f0x中文参考手册》,上面都有详细的介绍。
2.STM32下NVIC的介绍
- NVIC英文全称是Nested Vectored Interrupt Controller,中文意思就是嵌套向量中断控制器,它属于M3内核的一个外设,控制着芯片的中断相关功能。由于ARM给NVIC预留了非常多的功能,但对于使用M3内核设计芯片的公司可能就不需要这么多功能,于是就需要在NVIC上裁剪。ST公司的STM32F103芯片内部中断数量就是NVIC裁剪后的结果。
- 中断控制相关的寄存器在固件库
core_cm3.h 。
3.中断优先级的介绍
当CPU在正常执行程序的过程种总是会收到许多的中断,这么的中断如果一股脑的处理的话显然不现实,每个中断都应该有个优先级,优先级高的先执行,执行完之后再跳回之前的程序,这样程序才能井然有序的执行。
- STM32F103芯片支持60个可屏蔽中断通道,每个中断通道都具备自己的中断优先级控制字节(8位,但是STM32F103中只使用4位,高4位有效),用于表达优先级的高4位又被分为组成抢占式优先级和响应式优先级,每个中断源都需要被指定这两种优先级。
- 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等待前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。
- 高抢占式优先级的中断事件会打断当前的主程序或中断程序运行,俗称中断嵌套。在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。
4.外部中断的介绍
- STM32F10x外部中断/事件控制器(EXTI)包含多达20个用于产生事件/中断请求的边沿检测器。EXTI的每根输入线都可单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发),还可独立地被屏蔽。
- 外部中断/事件的线映射
三、串口通信keil工程文件
1.新建工程模板
关于在keil下新建一个stm32f103的的工程模板这里就不过多的说明了,相信大家通过前面的学习,都已经非常清楚了。新建工程模板之后再添加相应的.c ,.h 文件就可以了
注意!下面的代码只是.c文件的相关代码,如果同学们要借鉴的话,需要自己添加相应的.h文件和头文件
2.串口初始化函数,以及串口发送函数定义。
void My_Uart_Init(uint32_t Bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART1,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitStructure.USART_BaudRate = Bound;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_Cmd(USART1,ENABLE);
}
void Usart_SendByte(USART_TypeDef *USARTx,uint8_t ch)
{
USART_SendData(USARTx,ch);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE) == RESET);
}
void Usart_SendArray(USART_TypeDef *USARTx,uint8_t *arry,uint16_t num)
{
uint8_t i;
for(i=0; i<num; i++)
{
Usart_SendByte(USARTx,arry[i]);
}
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == RESET);
}
void Usart_SendByts(USART_TypeDef *USARTx,char *p)
{
while(*p != '\0')
{
Usart_SendByte(USARTx,*p);
p++;
}
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == SET);
}
3.中断服务程序的编写
void USART1_IRQHandler()
{
uint8_t Rx_cnt= 0;
char ch[100];
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
{
GPIO_SetBits(GPIOA,GPIO_Pin_5);
ch[Rx_cnt++] = USART1->DR;
Usart_SendByts(USART1,ch);
if(ch[Rx_cnt-1] == '\0') Rx_cnt = 0;
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
if(strcmp(ch,"s") == 0)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
Global_flag = 1;
}
if(strcmp(ch,"t") == 0) Global_flag = 0;
}
4.主程序的编写
if(Global_flag == 0)
Usart_SendByts(USART1,str);
Delay_ms(500);
将上诉代码添加到自己创建的工程文件目录下编译生成hex文件烧板测试!
四、烧板&Debug
总结
通过本次的学习,我也学习到了许多知识。在做字符串控制的实验中,因为理解错中断的相关知识,导致一直卡壳,当时一位字符串的接收是一个字符串进一次中断,不知道当时是怎么想的,导致一直没做出来,其实是收到一个字符就进一次中断,一直到字符接收完。
|