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

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

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,通过软件层面去读这个寄存器的值来判断是否校准结束;

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值