历史上的今天
返回首页

历史上的今天

今天是:2025年04月17日(星期四)

正在发生

2018年04月17日 | NVIC中断优先级管理+串口通信基本原理+串口通信

2018-04-17 来源:eefocus

今天主要总结和复习三个知识点,NVIC中断优先级管理、串口通信、及串口通信的简单配置实例:

第一部分:

NVIC中断优先级管理:

首先是中断分组,我们知道所用的CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。然而STM32并没有使用CM3内核的全部东西,而是只用了它的一部分。STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级。而我所用的STM32F103系列上面,又只有60个可屏蔽中断(在107系列才有68个),而STM系列把中断分为5个组,如下图一所示

图一

这么多大概60个中断如何管理,这是我一开始想到的问题,当然是用寄存器进行管理,有七组寄存器对所有的中断进行管理,中断寄存器分别如下,引用MDK对寄存器组的分类:

typedef struct
{
  __IO uint32_t ISER[8];                   //中断使能寄存器组:设置为:8个32位寄存器来控制256个中断,由于我用的只有60个故只需设置ISER[0]-ISER[2]即可
       uint32_t RESERVED0[24];                                   
  __IO uint32_t ICER[8];                      //中断除能寄存器组:设置和中断使能一样
       uint32_t RSERVED1[24];                                    
  __IO uint32_t ISPR[8];                      //中断挂起寄存器组:设置和中断使能一样,通过置一把正在执行的中断挂起从而执行同级别或更高级别的中断,写0无效
       uint32_t RESERVED2[24];                                   
  __IO uint32_t ICPR[8];                      //中断解挂控制寄存器组:设置和中断使能一样作用和挂起寄存器组相反
       uint32_t RESERVED3[24];                                   
  __IO uint32_t IABR[8];                   //   中断激活标志位寄存器组:这是一个只读寄存器,如果置一可以知道该位所对应的正在运行的中断,运行完毕由硬件自动清零
       uint32_t RESERVED4[56];                                   
  __IO uint8_t  IP[240];                   //  中断优先级控制寄存器组:这是非常重要的一个寄存器,总共有240个8位的寄存器组成,每8位代表一个中断,而每八位只用了其高八位,我所用的103系列只用了0-//67即可,详细的会在下面给出
       uint32_t RESERVED5[644];                                  
  __O  uint32_t STIR;                      // 软件触发中断寄存器组
}  NVIC_Type;      

中断优先级控制寄存器组,说这个之前得明白一个概念,优先级概念,STM系列的中断优先级分为两级,抢占优先级和响应优先级。而又得知道两者的区别,其中区别如下:

1、高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

2、抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

3、抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。

4、如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

抢占优先级和响应优先级中,数字越小说明级别越大。举个例子,假定设置中断优先级组为2,然后设置中断1(RTC中断)的抢占优先级为2,响应优先级为1。  中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断4(外部中断1)的抢占优先级为2,响应优先级为0。则中断优先级为中断4>中断1>中断6.

在详细弄懂了上述所有知识后,就可以设置自己我们自己的中断,具体步骤如下:

①系统运行后先设置中断优先级分组。调用函数:

voidNVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);/

 整个系统执行过程中,只设置一次中断分组。

②针对每个中断,设置对应的抢占优先级和响应优先级:

voidNVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

③ 如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。

第二部分:串口通信基本原理

这个复习得从通信的背景开始阐述,处理器与外部的通信分为两种方式并行和串行方式:并行的优点是速度快缺点为占用IO口较多,串行则速度慢优点为占用的IO口较少。串行通信按照传输方向又有三种方式,单工,半双工,全双工如图二所示:


图二

看完图应该就很清晰了,再解释一下

1、单工:数据传输只支持数据在一个方向上传输

2、半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;

3、全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。 

按照是否带时钟分为同步和异步,其中STM32的串口通信接口,UART:通用异步收发器,USART:通用同步异步收发器

我所用的板子中的大概电路如图三:


图三

STM32串口异步通信主要的参数定义为:起始位,数据位,硬件流位,停止位,波特率设置。举个例子如图四:


图四

第三部分:

下面进行第三部分,实例演示,在这之前得明白所用的三个寄存器

1、USART_SR状态寄存器

2、USART_DR数据寄存器

3、USART_BRR波特率寄存器

而我们在运用库函数编写串口代码过程一般会运用到下面的几个库函数:

voidUSART_Init();//串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能

voidUSART_Cmd();//使能串口

voidUSART_ITConfig();//使能相关中断

voidUSART_SendData();//发送数据到串口,DR

uint16_tUSART_ReceiveData();//接受数据,从DR读取接受到的数据

FlagStatusUSART_GetFlagStatus();//获取状态标志位

voidUSART_ClearFlag();//清除状态标志位

ITStatusUSART_GetITStatus();//获取中断状态标志位

voidUSART_ClearITPendingBit();//清除中断状态标志位

其中提出一点波特率的计算方式如图5所示:


图五


最后就可以进行实例操作:总结步骤如下:

①串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();

②串口复位:USART_DeInit(); 这一步不是必须的

③GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF_PP

④串口参数初始化:USART_Init();

⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)

      NVIC_Init();

      USART_ITConfig();

⑥使能串口:USART_Cmd();

⑦编写中断处理函数:USARTx_IRQHandler();

⑧串口数据收发:

void USART_SendData();//发送数据到串口,DR

uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

⑨串口传输状态获取:

FlagStatusUSART_GetFlagStatus(USART_TypeDef* USARTx,uint16_t USART_FLAG);

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

编写得主函数代码如下:

#include "stm32f10x.h"
//串口通信实验1
void my_usart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructA;
USART_InitTypeDef USART_InitStructA;
NVIC_InitTypeDef NVIC_InitStructA;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);//enable GPIOA和USART1 的时钟
//初始化GPIOA,查表可知串口1发送模式下是全双工,GPIO口设置为推挽复用模式
GPIO_InitStructA.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructA.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructA.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructA); 
//初始化GPIOA,查表可知串口1接受模式下是全双工,GPIO口设置为浮空输入模式
GPIO_InitStructA.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructA.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructA.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructA); 
//初始化串口参数
USART_InitStructA.USART_BaudRate=115200;
USART_InitStructA.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructA.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructA.USART_Parity=USART_Parity_No;
USART_InitStructA.USART_StopBits=USART_StopBits_1;
USART_InitStructA.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStructA);

//开启接受中断且初始化NVIC
NVIC_InitStructA.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructA.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructA.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructA.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructA);

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//设置串口状态
USART_Cmd(USART1, ENABLE);                    //使能串口1 
}
void USART1_IRQHandler(void)
{
u8 res;
if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//由于有可能开启了很多中断故需要判断是否是我们所要的中断函数
{
res=USART_ReceiveData(USART1);//接受来自串口一的数据
USART_SendData(USART1,res);//
}
}
 int main(void)
 {
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
my_usart_Init();
while(1);
//运行以后就一直在主函数等待,当电脑给单片机发送数据时就跳到中断
 
 }
由于我没有JLINK在线调试,故用USB直接下载到单片机进行调试,最后用串口助手可以得到所设想达到的输出:结果如图六


图六


其中白色的发送是先经过PC先发送给单片机,如然后单片机又发送给PC由串口助手在打印得出;


推荐阅读

史海拾趣

德力康(DLK)公司的发展小趣事

德力康(DLK)公司自1985年成立以来,最初专注于电视机用CRT插座的生产。凭借其卓越的产品质量和稳定的性能,逐渐在市场中树立了良好的口碑。随着电子行业的快速发展,DLK公司敏锐地捕捉到了连接器市场的巨大潜力,并开始逐步扩大产品线,涵盖D-SUB、DVI、HDMI、USB等多种连接器类型。通过不断的技术创新和市场拓展,DLK逐渐成为了国内连接器行业的重要供应商之一。

AF International公司的发展小趣事

作为一家具有社会责任感的企业,AF International始终关注社会公益事业的发展。公司积极参与扶贫、教育等公益活动,捐资助学、扶贫济困,为社会做出积极贡献。此外,AF International还注重环保和可持续发展,采用环保材料和节能技术,降低生产过程中的能耗和排放。这些举措不仅体现了公司的社会责任感,也为公司的可持续发展奠定了坚实基础。

这五个故事分别从不同角度展现了AF International在电子行业中的发展历程和取得的成就,体现了公司的创新精神、国际化视野、社会责任感等优秀品质。

Exel Microelectronics Inc公司的发展小趣事

XXXX年,Exel Microsystems Inc公司意识到了品质管理对于企业发展的重要性。于是,公司开始引进先进的品质管理理念和体系,加强了对产品从研发到生产的全过程控制。通过严格的品质管理,Exel的产品质量得到了显著提升,客户满意度也随之提高。这一举措不仅增强了公司的市场竞争力,也为公司的长期发展奠定了坚实基础。

Arco Electronics公司的发展小趣事

近年来,电子行业面临着技术更新换代快、市场竞争激烈等挑战。Arco Electronics公司敏锐地捕捉到了这些变化,及时调整了公司的战略方向。公司加大了对新兴技术的研发投入,如物联网、人工智能等领域,以保持技术上的领先地位。同时,公司还通过优化生产流程、提高产品质量等方式来降低成本,增强市场竞争力。

DIOTECH公司的发展小趣事

为了进一步提升市场份额和品牌影响力,DIOTECH公司开始加大市场拓展力度。通过参加国际电子展会、举办新品发布会等活动,公司成功吸引了全球范围内的客户和合作伙伴的关注。同时,公司还加强了品牌建设,通过一系列营销活动提升了品牌知名度和美誉度。这些努力使得DIOTECH逐渐成为了电子行业内的知名品牌。

Genisco Electronics公司的发展小趣事
根据使用环境的温度、湿度、海拔等因素选择适合的发电机型号和配置。

问答坊 | AI 解惑

外企面试如何应对

外企招聘已经形成了一套完整严格的录用员工制度,面试当然也有成熟的程序,而国内的用人单位则没有规范的模式,一般不会提太难太刁的问题。        △自我介绍要简短          面试中碰到的 ...…

查看全部问答>

斯图曼蓝牙不能连接美国麦测探测仪的蓝牙

在Wince下写了个程序实现蓝牙搜索、连接,使用的是Serialport串口类,现在能正常搜索周边的蓝牙并连接获取数据,但是遇到美国麦测的探测仪时可以搜索到,却连不上,不知何故,特此发帖询问各高手们,谢谢!…

查看全部问答>

WIN CE 5.0 的问题 已经问了很多群和论坛了,一直没人回答!谢谢大家啦!

D:\\1.jpg D:\\2.jpg 已经按照上面的提示做了 但还是不管用! 请高手指点! 谢谢啦 !…

查看全部问答>

dsp&ccs学习

小牛今年大三,学过了单片机,现在想学习dsp硬件,理论课程如《数字信号处理》、《随机信号》、《信号与系统》都已经学完了,但实验课程一直没有老师能够知道,学校有硬件,但师资不行,想从大虾那里讨些视频资料学习一下,主要是ccs及dsp硬件视频 ...…

查看全部问答>

如何向U盘扇区写大文件

如何向U盘扇区写大文件?大于256M,如何写?writefile?deviceiocontrol?内存映射?这些都怎么用?我用了WRITEFILE(),但写进去的都不对,没有成功过,不知道怎么写,项目急用,困惑了好久,真诚向各位请教,谢谢!…

查看全部问答>

mobile的启动方式(类似于PC的BIOS中选择系统启动方式)

我想问一下,在mobile中可以选择启动方式吗?比如用CD-ROM启动或网络启动等。 可否绕过windows mobile系统来操作PDA中的硬件? 比如在PC中,用光盘启动后,可以不通过windows xp来格式化硬盘等。 是否可以用类似的方法来操作windows mobile的F ...…

查看全部问答>

毕业季

最近要忙着找工作了,希望各位电子工程师们,指点迷津,如何应对笔试和面试,后辈不慎感激!…

查看全部问答>

在LM3S8962移植FreeRTOS和ucGUI

希望申请能通过,谢谢…

查看全部问答>

maple:arduino兼容的 stm32f103 开发板入门

maple是一个和arduino兼容的arm32开发平台使用简便,适合进行验证设计、做小制作等等同时也可以使用flashloader通过isp下载或是jtag调试IDE下载:win32 :   http://static.leaflabs.com/pub/leaflabs/maple-ide/maple-ide-LATEST-windowsxp32.z ...…

查看全部问答>