STM32-外部中断-AFIO-串口-串口通信-串口中断(空闲中断和接收中断)-printf移植-ADC数模转换-初始化和读取光敏电阻AO

news2024/9/23 2:23:01

常用的中断包括外部中断、串口中断、定时器中断;

1、外部中断:

引脚复用按钮导致的外部中断:

               注意:初始化引脚,添加引脚和EXTI输入线的映射;使用外部引脚的中断时需要使用AFIO映射;

操作步骤:

  1. 启用GPIO时钟:首先,你需要启用连接到EXTI Line 15的GPIO端口的时钟。
  2. 初始化GPIO引脚:将GPIO引脚配置为输入模式,并可能设置为具有中断能力(这取决于你的HAL库版本和STM32系列)。但是,请注意,不是所有的HAL库版本都允许在GPIO初始化时直接设置EXTI触发方式。
  3. 配置EXTI线路:使用HAL库提供的函数来配置EXTI线路,指定触发方式(下降沿)和可能的其他参数。但是,请注意,在某些HAL库版本中,你可能需要分别调用函数来设置触发方式和使能线路。
  4. 配置NVIC:如果你的中断需要特定的优先级或需要被使能,你还需要配置嵌套向量中断控制器(NVIC)。
  5. 编写中断服务例程(ISR):为EXTI Line 15编写中断服务例程,以便在检测到下降沿时执行特定的代码。
  6. 使能中断:最后,确保在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_EnableIRQNVIC_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端口,依此类推。

配置过程

  1. 使能IO口时钟:首先,需要使能目标GPIO端口的时钟。
  2. 开启AFIO时钟:然后,需要开启AFIO的时钟,以便能够访问其寄存器。
  3. 设置IO口模式为输入:将GPIO引脚配置为输入模式,以便能够接收外部信号。
  4. 配置中断线与GPIO引脚的映射关系:通过写入AFIO_EXTICRx寄存器,设置中断线与GPIO引脚的映射关系。
  5. 配置中断分组和优先级:在NVIC(嵌套向量中断控制器)中配置中断的分组和优先级。
  6. 初始化EXTI:根据需要配置EXTI的触发模式(上升沿、下降沿或边沿触发)等参数。
  7. 编写中断服务函数:为处理外部中断编写相应的中断服务函数。

         


串口:

  全双工的异步通信方式:      

全双工;

异步:异步没有时钟线,

在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、以太网等接口逐渐取代了串口在某些应用中的位置,但在许多工业控制、嵌入式系统、旧式设备连接等领域,串口仍然是一种重要的通信手段。

串口通信的特点

  1. 简单性:串口通信协议相对简单,不需要复杂的电路或设备。
  2. 低成本:串口硬件成本较低,适合成本敏感的应用场景。
  3. 长距离传输:在适当的条件下,串口可以实现较长距离的通信。
  4. 广泛兼容性:串口接口标准(如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) 是数据在串行通信中的基本传输单元,它由多个部分组成,包括起始位、数据位、可存在的奇偶校验位和停止位。数据帧的封装过程如下:

  1. 起始位(Start Bit):位于数据帧的最前面,通常为1个逻辑低电平(0),用于表示数据传输的开始。起始位的作用是通知接收设备一个字符的开始,以便同步双方的时钟。
  2. 数据位(Data Bits):紧随起始位之后,是实际要传输的数据内容。数据位的长度可以根据需要进行设置,常见的长度有5位、6位、7位和8位。例如,在ASCII码通信中,常使用7位或8位数据位来表示一个字符。
  3. 奇偶校验位(Parity Bit)(可选):位于数据位之后,用于简单的错误检测。奇偶校验位可以是奇校验(确保数据位中1的个数为奇数)或偶校验(确保数据位中1的个数为偶数)。如果传输过程中发生错误(如噪声干扰导致位翻转),接收设备可以通过校验位的值来判断是否发生了错误。然而,需要注意的是,奇偶校验位只能检测出奇数个位的错误,对于偶数个位的错误则无法检测。
  4. 停止位(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,使能

}
  1. 使能串口接收非空中断(RXNE)

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    这行代码配置了USART1以使其能够在接收到数据并且接收数据寄存器非空时产生中断。USART_IT_RXNE是接收非空中断的标志,ENABLE表示启用此中断。

  2. 使能串口空闲线路检测中断(IDLE)

    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);

    这行代码配置了USART1以使其能够在检测到空闲线路(即接收到一个停止位之后的一段时间内没有接收到任何数据)时产生中断。这对于检测帧的结束或长时间没有数据传输的情况特别有用。

  3. 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); 应用这些配置。
  4. 启用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;//
	
}
  1. 通道编号:在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,通过软件层面去读这个寄存器的值来判断是否校准结束;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2036856.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何获取android的SHA1或SHA256

在使用地图类的功能时,例如百度地图或者高德地图,会需要在开发者平台里填写SHA1或SHA256的指纹密钥,很多开发者小伙伴还不知道如何获取。当然关于如何获取android的SHA1或SHA256,网络上进行搜索已经有很多图文教程了,本…

mfc140u.dll丢失的科学修复手段,简单又方便的mfc140u.dll修复

遇到 "缺失 mfc140u.dll 文件" 的提示时可能会让你疑惑,但不用担心。这个文件是 Microsoft Visual C 2015 的重要组成部分,对运行特定程序非常关键。幸运的是,解决这一问题并不难。本文将简单指导你如何恢复或修复丢失的 mfc140u.d…

多台PC网络ADB连接同一台RK3399 Android7.1.2设备

在RK3399 Android7.1.2上面,进行网络ADB调试时,如果多台电脑连接同一台Android设备,第一台连接上的能正常操作,之后连接的看到设备状态为OFFLINE,分析了下ADBD相关代码,发现在ACCEPT Client的时候没有区分别…

设计师必备:2024最新PDF转CAD软件盘点

随着科技的飞速发展,设计师们不再受限于传统的设计流程,可以利用一些新欣的工具来提升工作效率、优化工作流程的新工具。其中,PDF转CAD工具成为了设计行业的一大热门话题。面对海量的数据和复杂的设计需求,一款高效、精准的PDF转C…

11、MySQL-SQL优化

目录 1、插入数据 1.1、批量插入 1.2、手动提交事务 1.3、主键顺序插入 1.4、大批量插入数据 2、主键优化 2.1 页分裂 2.2 主键顺序插入 2.3 主键乱序插入 2.4 页合并 2.5 主键的设计原则 3、order by优化 4、group by优化 5、limit优化 6、count优化 6.1 coun…

【Bifrost】ubuntu24.04 远程构建及clion设置编码风格google

Bifrost 构建通过clion 远程到ubuntu24.04 构建感觉是不认识这种写法,这种至少是c++11 fix : 修改absl 的构建cmakelist,明确c++17 好像还是不行error: ‘uint8_t’ was not declared in this scope加入:#include <stdint.h>可以解决一部分。那么,这种呢?/home/zha…

浅谈 DNS 篡改劫持

故事背景&#xff1a;产品反馈线上站点操作后跳转至空白页面&#xff0c;浏览器 URL 地址异常&#xff0c;ping 命令测试后定位可能是 DNS 解析异常&#xff0c;联系七牛云技术人员排查&#xff0c;反馈是由于带宽突变&#xff0c;触发节点防攻击策略所致&#xff0c;后续先调整…

keepalived安装-集群部署

1.服务器信息 服务器版本服务器IP介质版本安装用户CentOS Linux release 7.9.2009 (Core)192.168.10.244keepalived-2.2.8.tar.gz nginx-1.26.1 rootCentOS Linux release 7.9.2009 (Core)192.168.10.245keepalived-2.2.8.tar.gz nginx-1.26.1 root2.服务器基础配置 参考:Lin…

二、AI工作流(低代码)-输入-文本组件详解

对工作流感兴趣的小伙伴可以去试一试。&#x1f525;偷偷的告诉你&#xff0c;它的GPTo4.0 mini 不要&#x1f4b0;。传送门&#xff1a;https://www.nyai.chat/chat?invitenyai_1141439 一、能用AI工作流介绍 能用AI-工作流是一个“低代码”工具、它也是个人或者中小企业的…

Spring源码调试环境搭建(IDEA)

文章目录 引言开发环境搭建步骤步骤一&#xff1a;下载 Spring Boot 源码步骤二&#xff1a;导入项目到 IntelliJ IDEA步骤三&#xff1a;处理build报错报错一报错二 测试步骤新建module修改build.gradle新建测试类启动测试 引言 无论是面试&#xff0c;还是工作&#xff0c;S…

政安晨【零基础玩转各类开源AI项目】基于本地Ubuntu系统部署及应用歌唱语音转换框架NeuCoSVC:歌曲音色转换工具

目录 论文简介 部署 模型下载 编译REAPER 最后 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 本文目标&#xff1a;《Neural Concate…

模拟三层--控制层、业务层和数据访问层

三层的概念:https://developer.aliyun.com/article/1390024 一、新建一个项目 我新建好的项目名为spring__ioc_02,然后在 src-main-java 下建立三层&#xff08;数据访问层、业务层和控制层&#xff09;的包 dao、service 和controller、并在包下建立相应的接口和实现类 Proje…

网络命令之查看网口最大网速的一些方法?(/sys/class/net/ethx/speed、ethtool ethx)

文章目录 背景方法1: sysfs的net方法2&#xff1a;ethtool方法3&#xff1a;通过网卡型号获取方法4&#xff1a;通过网卡lspci输出信息直接获取方法5&#xff1a;高性能网卡可以通过物理连线光口信息获取后记 背景 经常需要查看不同网卡的网速&#xff0c;甚至相同大版本型号网…

一个简单的pytorch项目框架

框架的基本功能&#xff1a; 1. 模型的定义、训练与测试 2. 数据生成与数据迭代器 3. 训练日志记录 4. 训练过程实时监控 有了这个框架&#xff0c;后续所有复杂的AI项目都可以在此基础上拓展开发。 项目基本结构&#xff1a; 四个文件&#xff1a; sequence_mean_generate…

C++初阶_2:引用

本节咱们来说说引用&#xff1a; C添加了“引用”&#xff0c;与指针成了两兄弟——这两兄弟对我们今后写C代码可谓各有特点&#xff0c;缺一不可。 何谓引用&#xff1f; 引用&#xff1a;就是取别名 不知诸位可有别名&#xff1f;这里不妨举一本耳熟能详的小说《水浒传》&…

Redis16-批处理优化

目录 Pipeline 集群下的批处理 Pipeline 单个命令的执行流程&#xff1a; N条命令的执行流程&#xff1a; N条命令批量执行&#xff1a; Redis提供了很多Mxxx这样的命令&#xff0c;可以实现批量插入数据&#xff0c;例如&#xff1a; msethmset 利用mset批量插入10万条数…

vivado报错:file ended before end of clause

最近在学习Xilinx FPGA时&#xff0c;遇到 Vivado 报错如下图所示&#xff1a; 刚开始&#xff0c;看到错误是在第1行代码中出现的&#xff0c;我的第一反应是该行代码写错了&#xff0c;然后搜了搜语法&#xff0c;发现没错。 分析报错信息发现&#xff0c;该错误应该是和文件…

VScode + PlatformIO 和 Keil 开发 STM32

以前经常使用 KEIL 写 STM32 的代码&#xff0c;自从使用 VScode 写 ESP32 后感觉 KEIL 的开发环境不美观不智能了&#xff0c;后面学习了 VScode 开发 STM32 。 使用过程中发现 串口重定向在 KEIL 中可以用&#xff0c;搬到 VScode 后不能用&#xff0c;不用勾选 Use Micro LI…

SpringMVC 运行流程

SpringMVC 运行流程 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; SpringMVC的运行流程可概括为以下几个核心步骤&#xff1a; 流程图&#xff1a; #mermaid-svg-l1CeK9JwP5wRQjBL {font-family:"trebuchet ms",verdana,arial,…

医学图像分割新突破:6篇文献带你洞悉最前沿的医学AI技术|顶刊速递·24-08-14

小罗碎碎念 文献日推主题&#xff1a;人工智能在医学图像分割中的最新研究进展 今天这期文章信息量很大&#xff0c;并且不同的人看&#xff0c;获取的信息量也会差距很大。为了缩小这个差距&#xff0c;请在正式阅读前&#xff0c;记住小罗的一句话——模型学会了如何分割图像…