常用的中断包括外部中断、串口中断、定时器中断;
1、外部中断:
引脚复用按钮导致的外部中断:
注意:初始化引脚,添加引脚和EXTI输入线的映射;使用外部引脚的中断时需要使用AFIO映射;
操作步骤:
- 启用GPIO时钟:首先,你需要启用连接到EXTI Line 15的GPIO端口的时钟。
- 初始化GPIO引脚:将GPIO引脚配置为输入模式,并可能设置为具有中断能力(这取决于你的HAL库版本和STM32系列)。但是,请注意,不是所有的HAL库版本都允许在GPIO初始化时直接设置EXTI触发方式。
- 配置EXTI线路:使用HAL库提供的函数来配置EXTI线路,指定触发方式(下降沿)和可能的其他参数。但是,请注意,在某些HAL库版本中,你可能需要分别调用函数来设置触发方式和使能线路。
- 配置NVIC:如果你的中断需要特定的优先级或需要被使能,你还需要配置嵌套向量中断控制器(NVIC)。
- 编写中断服务例程(ISR):为EXTI Line 15编写中断服务例程,以便在检测到下降沿时执行特定的代码。
- 使能中断:最后,确保在NVIC中使能了相应的中断。
中断处理:中断服务函数
从中断向量表中取出中断服务函数:
NVIC的作用:
使能/屏蔽中断通道;
设置中断的优先级;
比较优先级
优先级:非负整数--数字小优先级高--0的优先级更高
抢占优先级和响应优先级:
先比较抢占,再比较响应;
优先级分组可以更改:默认0组;
nivc中断寄存器:AIRCR
0 | 0 | 0 | 0 |
中断向量表:中断服务函数的地址;
NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)是ARM Cortex-M系列微控制器中的一个关键组件,用于管理中断和异常。NVIC中断寄存器在中断处理过程中起着至关重要的作用。以下是一些与NVIC中断相关的关键寄存器及其功能概述:
1. 应用中断和复位控制寄存器(AIRCR)
- 功能:设置NVIC的优先级分组、系统复位请求等。
- 关键位:
- VECTKEY:寄存器密钥,写入时需要特定的值(如0x5FA)来解锁寄存器。
- PRIGROUP:用于设置中断优先级的分组模式,决定了抢占优先级和响应优先级的位数分配。
- SYSRESETREQ:系统复位请求位,用于请求系统复位。
2. 中断优先级寄存器(IPRx)
- 功能:设置每个中断的优先级。这些寄存器通常是8位的,但并非所有位都用于设置优先级,具体取决于PRIGROUP的设置。
- 操作:通过写入特定的值来设置每个中断的抢占优先级和响应优先级。
3. 中断使能寄存器(ISERx)
- 功能:使能或禁用特定的中断。每个ISERx寄存器对应一组中断,通过向相应的位写入1来使能中断,写入0则禁用中断。
4. 其他相关寄存器
- 中断挂起寄存器(ISPRx):用于设置中断的挂起状态,即请求CPU响应中断。
- 中断清除挂起寄存器(ICPRx):用于清除中断的挂起状态,即取消中断请求。
- 中断活动位寄存器(IABRx):只读寄存器,用于指示哪些中断当前处于活动状态(即正在被处理或等待被处理)。
5. 优先级屏蔽寄存器(PRIMASK、FAULTMASK、BASEPRI)
- PRIMASK:优先级屏蔽寄存器,用于屏蔽除NMI(非屏蔽中断)和硬fault外的所有异常。
- FAULTMASK:fault异常掩蔽寄存器,用于屏蔽除NMI外的所有异常。
- BASEPRI:基本优先级寄存器,用于设置一个阈值,只有优先级高于此阈值的异常才会被响应。
6. NVIC库函数
在STM32等微控制器的软件开发中,通常会使用HAL库或标准外设库来配置NVIC。这些库提供了丰富的函数来设置中断优先级分组、初始化中断、使能或禁用中断等。例如:
- NVIC_PriorityGroupConfig:用于设置中断优先级分组。
- NVIC_Init:用于初始化中断,包括设置中断通道、抢占优先级、响应优先级和使能状态。
- NVIC_EnableIRQ、NVIC_DisableIRQ:用于使能或禁用特定的中断。
大多数请求挂起寄存器需要手动清空(当中断处理函数结束后加上清空);
事件屏蔽寄存器:
挂起寄存器:
中断事件检测分为上升沿下降沿双边沿检测;
void Exti_Init(void){
// 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//gpiob
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//afio
//button初始化;
GPIO_InitStruct.GPIO_Mode =GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
GPIO_Init(GPIOB,&GPIO_InitStruct);
//pb15和exit15号输入线映射;
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);
//输入线初始化;
EXTI_InitStruct.EXTI_Line = EXTI_Line15;//指定配置的外部中断线为第15条;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;//启用这条外部中断线
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//设置模式为中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//触发方式下降沿触发
EXTI_Init(&EXTI_InitStruct);
//NVIC
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;//中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应优先级
NVIC_Init(&NVIC_InitStructure);
}
void EXTI15_10_IRQHandler(void){
if(SET == EXTI_GetITStatus(EXTI_Line15)){
EXTI_ClearITPendingBit(EXTI_Line15);//清除中断标志位
//中断处理
mode_flag++;
if(mode_flag > 4) mode_flag = 1;
配置gpio端口与exti映射关系 GPIO_EXTILineConfig
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);
GPIO_EXTILineConfig
函数是STM32标准外设库(或HAL库中的类似功能,尽管具体函数名可能有所不同)中的一个函数,用于配置外部中断/事件(EXTI)线与GPIO端口的映射关系。
获取指定EXTI线的中断状态EXTI_GetITStatus
(SET == EXTI_GetITStatus(EXTI_Line15)
EXTI_GetITStatus
函数用于获取指定EXTI线的中断状态。如果指定的中断线已经触发了中断,并且该中断尚未被清除,则该函数将返回一个非零值(通常是SET
宏定义的值,表示中断状态被设置)。否则,它返回零。
清除指定EXTI线(在本例中是EXTI_Line15)上的中断挂(EXTI_ClearITPendingBit(EXTI_Line15)
EXTI_ClearITPendingBit(EXTI_Line15)
是STM32标准外设库(或某些旧版本的HAL库)中的一个函数,用于清除指定EXTI线(在本例中是EXTI_Line15)上的中断挂起位(也称为中断标志)
AFIO:外部中断配置寄存器;
AFIO(Alternate Function I/O)在STM32微控制器中是一个重要的概念,它允许GPIO(通用输入输出)端口的某些引脚被配置为执行除了标准数字I/O以外的其他功能,如外部中断、定时器输出、ADC输入等。在外部中断的配置中,AFIO的作用主要体现在中断线与GPIO引脚的映射关系上。以下是关于AFIO和外部中断配置寄存器的详细解答:
1. AFIO与外部中断
在STM32中,每个GPIO端口都有多个引脚,这些引脚可以通过AFIO配置为外部中断源。外部中断通过EXTI(External Interrupt/Event Controller)控制器管理,它支持多达16条中断线(EXTI0到EXTI15),每条中断线可以映射到多个GPIO引脚上,但每次只能映射到一个引脚上。这种映射关系是通过AFIO的外部中断配置寄存器(AFIO_EXTICRx,其中x=1,2,3,4)来设置的。
2. 外部中断配置寄存器(AFIO_EXTICRx)
寄存器功能:
- AFIO_EXTICRx寄存器用于设置GPIO引脚与EXTI中断线的映射关系。每个寄存器(AFIO_EXTICR1至AFIO_EXTICR4)控制4条中断线(EXTI0-EXTI3, EXTI4-EXTI7, EXTI8-EXTI11, EXTI12-EXTI15)的映射。
寄存器结构:
- 每个AFIO_EXTICRx寄存器都是32位的,但通常只有低16位被使用,高16位保留。低16位被分为4组,每组4位,分别控制一条中断线的映射。
- 每组的4位决定了中断线映射到哪个GPIO端口(PA、PB、PC等)。例如,0000表示PA端口,0001表示PB端口,依此类推。
配置过程:
- 使能IO口时钟:首先,需要使能目标GPIO端口的时钟。
- 开启AFIO时钟:然后,需要开启AFIO的时钟,以便能够访问其寄存器。
- 设置IO口模式为输入:将GPIO引脚配置为输入模式,以便能够接收外部信号。
- 配置中断线与GPIO引脚的映射关系:通过写入AFIO_EXTICRx寄存器,设置中断线与GPIO引脚的映射关系。
- 配置中断分组和优先级:在NVIC(嵌套向量中断控制器)中配置中断的分组和优先级。
- 初始化EXTI:根据需要配置EXTI的触发模式(上升沿、下降沿或边沿触发)等参数。
- 编写中断服务函数:为处理外部中断编写相应的中断服务函数。
串口:
全双工的异步通信方式:
全双工;
异步:异步没有时钟线,
在USB转TTL(Universal Serial Bus to Transistor-Transistor Logic)转换器中,RXD(Receive Data)和TXD(Transmit Data)是两个至关重要的引脚,它们分别承担着数据接收和发送的功能。
RXD(Receive Data)
- 功能:RXD代表接收数据线,用于接收来自另一个设备(如微控制器、单片机等)通过TTL串口发送的数据。
- 连接:在USB转TTL转换器中,RXD引脚需要与目标设备的TXD引脚相连接,以实现数据的接收。
- 作用:在通信过程中,RXD引脚负责捕捉并接收通过TTL串口传输的数据信号,然后将其转换为USB信号,以便计算机或其他USB主机设备能够读取和处理这些数据。
TXD(Transmit Data)
- 功能:TXD代表发送数据线,用于将计算机或其他USB主机设备通过USB接口发送的数据转换为TTL电平的串行信号,并发送给目标设备。
- 连接:在USB转TTL转换器中,TXD引脚需要与目标设备的RXD引脚相连接,以实现数据的发送。
- 作用:TXD引脚负责将计算机或其他USB主机设备产生的数据信号转换为TTL电平信号,并通过串口发送给目标设备。这样,目标设备就能够接收到来自计算机或其他USB主机设备的数据,并进行相应的处理或响应。
同步(Synchronous)
在编程中,同步操作指的是代码的执行按照严格的顺序进行,一个任务完成后才会开始下一个任务。这种执行方式保证了程序的可预测性和顺序性。当执行一个同步操作时,程序会等待该操作完成(比如等待磁盘读写完成、等待网络响应等)之后,才会继续执行后续的代码。这意味着同步操作会阻塞(block)后续代码的执行,直到当前操作完成。
因此,同步操作确实可以看作是在一个“确定的时间线”上发生的事件,因为它们严格按照程序中的顺序执行,且每个操作完成后才会继续下一个。
异步(Asynchronous)
与同步相反,异步操作允许程序在等待某个长时间运行的操作(如文件读写、网络请求等)完成时,继续执行其他任务。异步操作不会阻塞后续代码的执行,而是通过回调函数、Promise、async/await等机制,在操作完成时通知程序。
异步操作中的事件并不遵循一个严格的“确定时间线”,
串口通信:
RS_232电平标准;(高电平-3 ~~~-15)(低电平 +3~~~+15)
电平转换芯片;USB TO TTL (CH340G)
COMS标准;
波特率:单位时间发送的数据位的个数;
数据帧:让通信更稳定更安全;
起始位(不设置,约定为低电平) 数据位(可以设置长度) 可存在的奇偶校验位(奇校验、偶校验、不设置) 停止位(设置长度(1、2)一般为高电平)
串口协议
串口协议是一组规则和标准,用于规范设备之间的通讯行为。它定义了设备之间的信息交换方式、通讯规则、通讯步骤等,以确保设备之间的正确通讯和协作。串口协议的种类繁多,常见的有RS-232、RS-422、RS-485等,它们各自有不同的电气特性和传输距离限制。在实际应用中,选择合适的串口协议对于确保通信的稳定性和可靠性至关重要。
波特率
波特率是指串口通信系统中传输数据的速率,即每秒钟传输的位数(bit)。它是衡量通信速度的重要参数,直接影响到通信的质量和效率。常见的波特率有2400、4800、9600、19200、38400、57600、115200等标准波特率,以及更高如46800、230400、460800、921600等高波特率,这些高波特率适用于对数据传输速度要求较高的应用。需要注意的是,波特率的选择需要考虑到传输速度、传输距离和硬件支持等因素,并且通信两端的波特率设置必须相同,否则会导致通信失败。
数据帧
数据帧是数据在串口通信中的组织形式,它定义了数据在传输过程中的位顺序、位长度、数据位的数量和排列方式、停止位的数量和位置、校验方式等。数据帧格式主要关注的是数据在物理层上的传输细节,它确保了数据的正确传输和解析。在串口通信中,一帧数据通常包括起始位、数据位、可选的校验位和停止位等部分。起始位用于标识数据传输的开始,数据位用于存储实际的数据,校验位用于检测数据传输过程中的错误(尽管并非所有数据帧都包含校验位),而停止位则用于标识数据传输的结束。
流控(数据量大,传输频繁,传输压力大才用)
控制器(USART)--(通用同步异步收发器):
DMA(Direct Memory Access)直接内存访问,
是一种允许某些硬件设备(如磁盘驱动器、网络接口卡等)直接与内存进行数据传输,而不需要通过CPU介入的技术。这种技术大大提高了数据传输的效率,减少了CPU的负担,因为CPU在数据传输过程中可以进行其他任务。
空闲中断;
串口初始化:
void usartInit1(int baud){
//打开时钟,使能gpioA和usart1;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
//对PA9与PA10进行gpio初始化
//PA9--TX--复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//PA10 --RX--浮空输入模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//USART初始化
USART_InitStructure.USART_BaudRate =baud;//设置波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置USART模式
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
USART_Cmd(USART1,ENABLE);//启用USART,使能
}
USART_SendData(USART1,ch);
USART_SendData
函数用于通过USART(通用同步/异步收发传输器)接口发送一个数据字节。
while(RESET == USART_GetFlagStatus(USART1,USART_FLAG_TXE));
USART_GetFlagStatus
函数则用于检查USART的某个标志位的状态;
通信协议-数据协议:
串口:串行通信
串口(Serial Port),也被称为串行端口或串行通信接口,是一种电子接口,用于实现计算机与外部设备之间的串行通信。这种通信方式是以一位接一位的顺序传送数据,与并行通信(Parallel Communication)同时传输多个数据位的方式形成对比。串口通信因其简单性、低成本和广泛的兼容性,在早期的计算机系统中被广泛使用,尽管随着技术的发展,USB、以太网等接口逐渐取代了串口在某些应用中的位置,但在许多工业控制、嵌入式系统、旧式设备连接等领域,串口仍然是一种重要的通信手段。
串口通信的特点
- 简单性:串口通信协议相对简单,不需要复杂的电路或设备。
- 低成本:串口硬件成本较低,适合成本敏感的应用场景。
- 长距离传输:在适当的条件下,串口可以实现较长距离的通信。
- 广泛兼容性:串口接口标准(如RS-232、RS-422、RS-485等)被广泛应用于各种设备中,具有良好的兼容性。
串口通信的协议和标准
- RS-232:是最常见的串口通信标准之一,它定义了数据信号的电平、速率、连接器的物理特性等。RS-232采用负逻辑,即逻辑“1”为-3V至-15V,逻辑“0”为+3V至+15V。然而,由于RS-232的通信距离较短(通常不超过15米),且抗干扰能力较弱,因此在长距离或高噪声环境中使用受限。
- RS-422:是一种改进的串口通信标准,支持更高的数据传输速率和更长的通信距离。RS-422采用差分传输方式,提高了抗干扰能力,适用于多点通信。
- RS-485:是在RS-422基础上进一步发展而来的,它采用差分信号进行传输,支持多点、长距离通信,并且可以在同一总线上连接多达32个设备。
波特率--传输速度
数据帧--数据简易封装(起始位 数据位 可存在的奇偶校验位 停止位)
波特率(Baud Rate) 是衡量数据传输速度的一个重要参数,它表示每秒钟可以传输多少符号(通常指比特,bit)。在串行通信中,波特率直接决定了数据传输的速率。例如,当波特率为9600时,意味着每秒可以传输9600个比特的数据。从宏观上理解,波特率表征了串口的传输速度;从微观上看,它是指在单位时间内(如每秒)传输的码元(在UART通信中,码元通常为二进制位)个数。
波特率的设计和实现依赖于硬件的时钟频率和波特率生成器。例如,在UART(通用异步收发传输器)通信中,波特率是由功能时钟(如26MHz)通过分频得到的。波特率的选择应根据实际应用场景和数据传输需求来确定,高波特率适用于需要快速传输大量数据的场景,但也可能受到传输距离和信号衰减等因素的限制。
数据帧——数据简易封装
数据帧(Data Frame) 是数据在串行通信中的基本传输单元,它由多个部分组成,包括起始位、数据位、可存在的奇偶校验位和停止位。数据帧的封装过程如下:
- 起始位(Start Bit):位于数据帧的最前面,通常为1个逻辑低电平(0),用于表示数据传输的开始。起始位的作用是通知接收设备一个字符的开始,以便同步双方的时钟。
- 数据位(Data Bits):紧随起始位之后,是实际要传输的数据内容。数据位的长度可以根据需要进行设置,常见的长度有5位、6位、7位和8位。例如,在ASCII码通信中,常使用7位或8位数据位来表示一个字符。
- 奇偶校验位(Parity Bit)(可选):位于数据位之后,用于简单的错误检测。奇偶校验位可以是奇校验(确保数据位中1的个数为奇数)或偶校验(确保数据位中1的个数为偶数)。如果传输过程中发生错误(如噪声干扰导致位翻转),接收设备可以通过校验位的值来判断是否发生了错误。然而,需要注意的是,奇偶校验位只能检测出奇数个位的错误,对于偶数个位的错误则无法检测。
- 停止位(Stop Bit):位于数据帧的最后,用于表示数据传输的结束。停止位通常是1个或2个逻辑高电平(1),其作用是确保接收设备有足够的时间来正确识别数据帧的结束,并准备接收下一个数据帧。停止位还可以提供时钟同步的机会,帮助接收设备调整其内部时钟以匹配发送设备的时钟。
流控——流量控制
流控(Flow Control),即流量控制,是通信过程中用于管理数据传输速率和防止数据丢失的一种机制。在串行通信中,由于传输线路的限制和设备的处理能力差异,如果发送方发送数据的速度过快而接收方无法及时处理,就可能导致数据丢失或缓冲区溢出。因此,需要采用流量控制机制来确保数据的可靠传输。
流量控制的方法有多种,包括硬件流控和软件流控。硬件流控通常使用专门的信号线(如RS-232接口中的RTS和CTS信号线)来实现发送方和接收方之间的速度匹配;而软件流控则通过特定的字符(如XON/XOFF字符)来控制数据传输的开始和停止。在实际应用中,可以根据具体需求和通信协议来选择合适的流量控制方法。
printf移植
使用c语言库函数要勾选Use MicroLIB
Printf-->fputc(决定以哪个文件进行输出)重新定义fputc的功能
要打印的数据通过串口发送到电脑;
使用中断解决串口接收异步:
异步:
接收时间不确定--------解决:接收端接收中断
数据量不确定----------解决:约定数据的大小
通过串口调试助手发指令控制灯泡的模式:
中断处理函数(经常修改的函数放头部):
中断配置:
//打开时钟,使能gpioA和usart1;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
//对PA9与PA10进行gpio初始化
//PA9--TX--复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//PA10 --RX--浮空输入模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//USART初始化
USART_InitStructure.USART_BaudRate =baud;//设置波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//设置硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置USART模式
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
//使能串口中断RXNE 接收非空中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//使能串口中断IDLE 空闲线路检测中断
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
//NVIC的初始化
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART1,ENABLE);//启用USART,使能
}
使能串口接收非空中断(RXNE):
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
这行代码配置了USART1以使其能够在接收到数据并且接收数据寄存器非空时产生中断。
USART_IT_RXNE
是接收非空中断的标志,ENABLE
表示启用此中断。使能串口空闲线路检测中断(IDLE):
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
这行代码配置了USART1以使其能够在检测到空闲线路(即接收到一个停止位之后的一段时间内没有接收到任何数据)时产生中断。这对于检测帧的结束或长时间没有数据传输的情况特别有用。
NVIC初始化:
通过NVIC初始化结构体NVIC_InitStructure
来配置USART1的中断优先级,并使能USART1的中断。
NVIC_IRQChannel = USART1_IRQn;
指定中断源为USART1的中断请求。NVIC_IRQChannelCmd = ENABLE;
使能该中断请求。NVIC_IRQChannelPreemptionPriority = 2;
设置抢占优先级为2。抢占优先级决定了在多个中断同时发生时哪个中断首先被处理。NVIC_IRQChannelSubPriority = 2;
设置子优先级为2。当两个中断具有相同的抢占优先级时,子优先级决定了哪个中断先被处理。NVIC_Init(&NVIC_InitStructure);
应用这些配置。启用USART:
USART_Cmd(USART1, ENABLE);
中断函数:
检查指定的USART中断标志位是否被设置
SET == USART_GetITStatus(USART1,USART_IT_RXNE)//接收中断;
USART_GetITStatus
函数用于检查指定的USART中断标志位是否被设置。如果中断标志位被设置(即,如果相应的中断已经发生并且还没有被清除),则该函数返回一个非零值(通常是 SET
的定义,但在直接比较时通常不直接使用 SET
)
SET == USART_GetITStatus(USART1,USART_IT_IDLE)//空闲中断检测
USART1->SR
和 USART1->DR
寄存器分别用于访问USART1的状态寄存器和数据寄存器。
USART1->SR
寄存器包含了USART的状态信息,包括各种中断标志位和错误标志位。IDLE中断的标志位是USART状态寄存器中的一个位,当检测到空闲线路(即接收数据线上持续了一段时间的高电平,表示帧的结束)时,该位会被硬件设置。
USART1->SR
和 USART1->DR(同时访问SR状态寄存器和DR数据寄存器的读取来自动清除中断标志)
数据协议--自定义协议(包头--功能位--包尾)
通过对数据进行封装,形成数据协议;
ADC数模转换:
在STM32微控制器的ADC(模拟数字转换器)中,存在两种类型的转换通道:规则通道(Regular Channels)和注入通道(Injected Channels)。这两种通道在ADC的转换过程中扮演着不同的角色,并且可以根据需要被单独配置和使用。
规则通道(Regular Channels)
规则通道是ADC转换的主要通道类型。它们按照在ADC配置中指定的顺序进行转换。规则通道的转换可以由软件触发、外部事件触发或自动重复触发。规则通道的转换结果存储在ADC的数据寄存器中,并可以通过读取该寄存器来获取。
规则通道通常用于需要定期或连续采样的应用场景,如读取传感器数据、监测电压或电流等。在STM32的ADC中,规则通道的数量和具体配置取决于ADC的型号和配置。
注入通道(Injected Channels)
注入通道提供了一种在规则通道转换过程中插入额外转换的方法。当注入通道被触发时,ADC会立即停止当前的规则通道转换(如果正在进行的话),并开始注入通道的转换。注入通道的转换优先级高于规则通道,因此它们会优先完成。
注入通道通常用于需要快速响应的紧急情况或重要事件,如中断服务例程中需要立即读取的模拟信号。在注入通道转换完成后,ADC会自动恢复规则通道的转换(如果之前被中断的话)。
使用场景和区别
- 使用场景:规则通道适用于常规的、周期性的模拟信号采样;而注入通道则适用于需要快速响应的特殊情况。
- 优先级:注入通道的转换优先级高于规则通道,可以在规则通道转换过程中被插入。
- 触发方式:规则通道和注入通道都可以由软件、外部事件或自动重复触发,但它们的触发源和条件可能有所不同。
- 数据读取:规则通道和注入通道的转换结果都存储在ADC的数据寄存器中,但可能需要通过不同的方式或寄存器来读取。
ADC初始化;光敏电阻
ADC的输入为引脚,要使用gpio的模拟输入通道;
x/4096 = 2/3.3;//扩大精度
在STM32微控制器上初始化ADC(模拟到数字转换器)并使用它来读取光敏电阻的模拟信号值是一个常见的应用,特别是在需要测量环境光强或进行光敏控制的系统中。光敏电阻(也称为光敏变阻器或LDR)的阻值会随着光照强度的变化而变化,光照越强,阻值越小;光照越弱,阻值越大。
以下是一个基本的步骤指南,用于在STM32上初始化ADC并读取光敏电阻的值:
1. 硬件连接
- 将光敏电阻的一端连接到ADC的一个输入通道(例如,STM32的PA0,但具体取决于你的开发板和ADC配置)。
- 将光敏电阻的另一端连接到地(GND)。
- 可以在光敏电阻和地之间添加一个电阻(例如10KΩ),形成分压电路,以提高测量的准确性或调整测量范围。
2. ADC初始化
在STM32的HAL库或标准外设库中,ADC的初始化通常涉及以下几个步骤:
- 启用ADC时钟:通过RCC(复位和时钟控制)模块启用ADC的时钟。
- 配置ADC参数:设置ADC的分辨率、扫描模式、连续转换模式等。
- 配置ADC通道:选择你要使用的ADC通道,并设置其采样时间等参数。
- 启动ADC校准(如果需要):一些STM32系列要求在校准后使用ADC。
- 使能ADC:启动ADC,准备进行转换。
3. 读取ADC值
- 触发ADC转换(可以通过软件触发或外部事件触发)。
- 等待ADC转换完成(可以通过轮询ADC状态寄存器或使用中断)。
- 读取ADC转换结果。
4. 转换ADC值到光强
由于ADC输出的是数字值,而你需要的是光强的某种表示(可能是相对值或绝对光强),因此你可能需要将ADC值转换为一个更有意义的单位。这通常涉及到一些校准步骤,包括在不同光照条件下测量ADC值,并建立一个ADC值与光强之间的映射关系。
adc的时钟频率不能超过14Mhz;所以需要分屏;
void lightInit(void){ //打开时钟 adc1 gpioa RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA,ENABLE); //设置APi GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//模拟输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOA,&GPIO_InitStructure); //设置ADC的时钟频率,最大不能超过14MHZ,来自apb2时钟72MHZ; RCC_ADCCLKConfig(RCC_PCLK2_Div6);//72/6 = 12Mhz; //初始化ADC ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//连续和单次的选择 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换结果对齐方式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件或硬件触发 ADC_InitStructure.ADC_Mode =ADC_Mode_Independent;//双ADC模式与独立模式的选择 ADC_InitStructure.ADC_NbrOfChannel = 1;//转换通道的数量 ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描模式开启 ADC_Init(ADC1,&ADC_InitStructure); ADC_Cmd(ADC1,ENABLE); //复位校验 ADC_ResetCalibration(ADC1); //等待复位校准结束 while(SET == ADC_GetResetCalibrationStatus(ADC1)); //开始校准 ADC_StartCalibration(ADC1); //等待校准结束 while(SET == ADC_GetCalibrationStatus(ADC1)); }
adc的使用获取转换结果:
void lightGetVal(u8 *light_val){
//规则通道的设置 对通道的顺序 采样时间
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_41Cycles5);
//软件触发,开始转换
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
//等待转换完成 EOC标志(转换完成的标志位)
while(RESET == ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
//获取规则通道的转换结果
u16 val = ADC_GetConversionValue(ADC1);
*light_val = 100 - val/41;//
}
-
通道编号:在
ADC_RegularChannelConfig
函数中,ADC_Channel_1
指的是ADC1的第一个输入通道。如果您的光敏电阻连接到了ADC1的第一个通道(这取决于您的硬件连接),那么这段代码就是正确的。但是,如果光敏电阻连接到了其他通道(比如ADC_Channel_2、ADC_Channel_3等),则需要相应地更改通道编号。
ADC_RegularChannelConfig
是 STM32 微控制器中用于配置 ADC(模拟数字转换器)的常规(或规则)转换序列中的通道的函数。这个函数通常在 ADC 初始化过程中被调用,用于指定哪些通道将被包含在 ADC 的常规转换序列中,以及它们在序列中的顺序。函数原型(对于 STM32F1 系列,但其他系列的原型可能略有不同)大致如下:
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
ADCx
:指向要配置的 ADC 模块的指针。例如,ADC1
表示 ADC1 模块。ADC_Channel
:要配置的 ADC 通道编号。这个编号是根据您的 STM32 系列的引脚映射来确定的。例如,ADC_Channel_1
表示第一个 ADC 通道。Rank
:通道在常规转换序列中的排名(或顺序)。排名越低的通道将越早被转换。排名的范围通常是 1 到 16,具体取决于 STM32 的型号和 ADC 的配置。ADC_SampleTime
:采样时间。这是 ADC 在开始转换之前用于采样输入信号的时间长度。采样时间的选择会影响 ADC 转换的精度和速度。较长的采样时间可以提供更高的精度,但会减慢转换速度。
ADC_SoftwareStartConvCmd
是 STM32 微控制器中用于通过软件触发 ADC 开始转换的函数。这个函数允许您在不依赖于外部事件或定时器触发的情况下,手动启动 ADC 的转换过程。函数原型(对于 STM32F1 系列,但其他系列的原型可能略有不同)大致如下:
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
ADCx
:指向要启动转换的 ADC 模块的指针。例如,ADC1
表示 ADC1 模块。NewState
:新的功能状态。这个参数用于控制 ADC 的转换启动。通常,您会传递ENABLE
来启动转换,或者DISABLE
来停止转换(尽管ADC_SoftwareStartConvCmd
主要用于启动转换,而停止转换可能由其他机制控制)。
FunctionalState
是一个枚举类型,通常定义在 STM32 的标准外设库中,用于表示外设的功能状态(启用或禁用)。ENABLE
和DISABLE
是这个枚举类型的两个可能值。在STM32微控制器的ADC(模拟数字转换器)编程中,
ADC_GetFlagStatus
函数用于检查ADC的某个标志位的状态,而ADC_FLAG_EOC
是指“End Of Conversion”(转换结束)标志位。这个标志位在ADC完成一次模拟到数字的转换后会被设置。
ADC_SoftwareStartConvCmd
函数则用于通过软件触发的方式来启动ADC的转换。当这个函数被调用时,并且如果ADC已经准备好(例如,没有正在进行的转换,并且ADC已经使能等),ADC就会开始一次新的转换。
ADC_GetConversionValue(ADC1);
是一个在STM32微控制器编程中用于获取ADC1模块最近一次转换结果的函数调用。这个函数通常在你已经启动了ADC转换(通过软件触发、外部触发或自动扫描等方式)并且转换已经完成(通过检查ADC_FLAG_EOC
标志位或等待ADC中断等方式确认)之后被调用。当你调用
ADC_GetConversionValue(ADC1);
时,它会返回ADC1模块当前存储的转换结果。这个转换结果是一个数字值,表示了ADC输入引脚上模拟信号的电压水平。具体的数字值范围取决于ADC的分辨率配置。例如,如果ADC配置为12位分辨率,那么转换结果将是一个0到4095之间的数字(对于大多数STM32 ADCs,当参考电压为3.3V或Vref+时)。
校准:
校准是硬件校准,硬件电路校准结束自动把寄存器置0,通过软件层面去读这个寄存器的值来判断是否校准结束;