精华内容
下载资源
问答
  • STM32串口IDLE中断

    2020-07-29 00:45:47
    stm32串口的收发似乎不太一样,发只要你把数据送出去就行了,电脑会自动读取(电脑不知道你啥时候发,总不能一直等你的数据吧),而你的stm32要接受一个数据呢?一直在USART_ReceiveData吗?(当时这个问题也困扰了我,直到...

    stm32串口的收发似乎不太一样,发只要你把数据送出去就行了,电脑会自动读取(电脑不知道你啥时候发,总不能一直等你的数据吧),而你的stm32要接受一个数据呢?一直在USART_ReceiveData吗?(当时这个问题也困扰了我,直到接触了ESP8266才用到接收)
    后面我发现有个很好的东西,串口IDLE中断,能自动响应你从电脑(别的串口)接收到的不定长数据。而不是一直干等着。
    先简单说说原理吧,大概是,你的stm32接收数据时,并不会马上把数据马上处理掉,而是写到你定义的缓冲区里,然后你串口线上一个BYTE长度的时间如果没接收到数据,就会产生了IDLE中断(只会产生一次,别担心一直会卡在里面,除非等下次再接收时)

    代码

    代码很简单,不多说,附上

    static void NVIC_Configuration(void)
    {
    	NVIC_InitTypeDef	NVIC_InitStructure;
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    	NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    	NVIC_Init(&NVIC_InitStructure);
    }	
    //在初始化串口的前提下,调用此函数初始化空闲接收中断
    void Uart_Idle_Receive_Config(void)
    {
    	NVIC_Configuration();
    	USART_ITConfig(DEBUG_USART,USART_IT_RXNE,ENABLE);
    	USART_ITConfig(DEBUG_USART,USART_IT_IDLE,ENABLE);
    }
    

    中断服务函数如下

    #ifdef	USE_IDLE_RECEIVE			//使用串口空闲中断,开启中断服务
    static u16 uart_rec_count = 0;
    uint8_t UART_RECEIVE_BUF[100];
    void USART1_IRQHandler(void)
    {
    	u16 times;
    	if(USART_GetITStatus(DEBUG_USART,USART_IT_RXNE) != RESET)
    	{
    		UART_RECEIVE_BUF[uart_rec_count] = USART_ReceiveData(DEBUG_USART);
    		uart_rec_count++;
    		//USART_ClearITPendingBit(DEBUG_USART,USART_IT_RXNE);//千万别加
    	}
    	if(USART_GetITStatus(DEBUG_USART,USART_IT_IDLE) != RESET)
    	{
    	UART_RECEIVE_BUF[uart_rec_count] = USART_ReceiveData(DEBUG_USART);//这里要读一下才能清空标志位,不然会卡在中断里
    		/*此处加入对接收缓冲区的操作*/
    		
    		
    		/***************************/		
    		uart_rec_count = 0;
    		//USART_ClearITPendingBit(DEBUG_USART,USART_IT_IDLE);//千万别加
    	}
    }
    
    #endif
    

    加个预编译头,避免你不用的时候,写了个中断服务函数程序卡在这里,要用就define一下就好了
    注意:千万别软件清除中断标志位,不然会一直进IDLE中断,不信自己试试。
    就是USART_ClearITPendingBit(),不然程序卡死在中断里了。你读出来,人家硬件会自动清除.

    展开全文
  • 由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。IDLE中断什么时候发生?IDLE就是串口收到一帧数据后,发生的中断。...

    今天说一下STM32单片机的接收不定长度字节数据的方法。由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。

    IDLE中断什么时候发生?

    IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。

    如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。

    看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。这个中断真是太TMD有用了。省去了好多判断的麻烦。

    如何配置好IDLE中断?

    下面我们就配置好串口IDLE中断吧。

    这是串口CR1寄存器,其中,对bit4写1开启IDLE中断,对bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同)

    (RXNE中断和IDLE中断的区别?

    当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。)

    这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1.

    需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。

    IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。(我怎么知道?手册上写的)

    下面以STM32F103为例给出源程序。

    我们先来看程序中的主要部分。

    串口初始化函数片段

    %E7%A9%BA%E9%97%B2%E4%B8%AD%E6%96%AD.png (17.99 KB, 下载次数: 45)

    下载附件 保存到相册

    2015-10-29 23:11 上传

    如果你原来的串口初始化函数具有打开串口接收中断的话,实际上就是在初始化函数中多了一条打开空闲中断的语句。

    串口中断函数

    串口中断函数里面,最重要的两条语句,就是上图中圈出来的两条语句。第一条语句用来判断是否接收到1个字节,第二条语句用来判断是否接收到1帧数据。(是不是感觉超级方便?妈妈再也不用担心我如何判断是否接收完1帧数据了。)

    主函数

    我写的这个主函数,是用来验证接收的正确性的。RxCounter表示的是这一帧数据有几个字节,接收完一帧数据,会在中断函数里面把ReceiveState置1,然后,通过串口把接收到的数据发送回串口。这样,既验证了接收了多少字节的正确性,又验证了接收到的数据是否正确。

     

    上图是结果验证。

    /**

    ******************************************************************************

    * @file    串口接收不定长字节数据

    * @author  瑞生

    * @version V1.0

    * @date    2015.10.23

    * @brief   Main program body

    ******************************************************************************

    ******************************************************************************

    */

    /* Includes ------------------------------------------------------------------*/

    #include "stm32f10x.h"

    #include "uart.h"

    volatile uint8_t aRxBuffer[100]={0x00};

    volatile uint8_t RxCounter=0;

    volatile uint8_t ReceiveState=0;

    /**

    * @brief  Main program.

    * @param  None

    * @retval None

    */

    int main(void)

    {

    uint8_t i=0;

    USART1_Init();

    while (1)

    {

    if(ReceiveState==1)//如果接收到1帧数据

    {

    ReceiveState=0;

    i=0;

    while(RxCounter--)// 把接收到数据发送回串口

    {

    USART_SendData(USART1, aRxBuffer[i++]);

    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

    }

    RxCounter=0;

    }

    }

    }

    本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

    展开全文
  • ALIENTEK战舰STM32开发板所使用的STM32F103ZET6最多可提供5路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持LIN、支持调制解调器操作、智能卡协议和IrDASIRENDEC规范、具有DMA等。 用过单片机的...

    串口作为MCU的重要外部接口,同时也是软件开发重要的调试手段,其重要性不言而喻。STM32的串口资源相当丰富的,功能也相当强劲。ALIENTEK战舰STM32开发板所使用的STM32F103ZET6最多可提供5路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持LIN、支持调制解调器操作、智能卡协议和IrDASIRENDEC规范、具有DMA等。 用过单片机的人肯定都接触过串口,设置串口无非就是设置波特率、数据位、停止位、奇偶校验位。发送接收也就三种基本方式,轮询、中断和DMA。STM32F10x 的USART 模块也不过如此。

    STM32单片机的接收不定长度字节数据的方法。由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。

    IDLE中断什么时候发生?

    IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。

    如何判断一帧数据结束,就是我们今天讨论的问题。因为很多项目中都要用到这个,因为只有接收到一帧数据以后,你才可以判断这次收了几个字节和每个字节的内容是否符合协议要求。

    看了前面IDLE中断的定义,你就会明白了,一帧数据结束后,就会产生IDLE中断。这个中断真是太TMD有用了。省去了好多判断的麻烦。

    如何配置好IDLE中断?

    下面我们就配置好串口IDLE中断吧。

    这是串口CR1寄存器,其中,对bit4写1开启IDLE中断,对bit5写1开启接收数据中断。(注意:不同系列的STM32,对应的寄存器位可能不同)

    (RXNE中断和IDLE中断的区别?

    当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。)

    这是状态寄存器,当串口接收到数据时,bit5就会自动变成1,当接收完一帧数据后,bit4就会变成1.

    需要注意的是,在中断函数里面,需要把对应的位清0,否则会影响下一次数据的接收。比如RXNE接收数据中断,只要把接收到的一个字节读出来,就会清除这个中断。IDLE中断,如何是F0系列的单片机,需要用ICR寄存器来清除,如果是F1系列的单片机,清除方法是“先读SR寄存器,再读DR寄存器”。(我怎么知道?手册上写的)

    下面以STM32F103为例给出源程序。

    我们先来看程序中的主要部分。

    串口初始化函数片段

    如果你原来的串口初始化函数具有打开串口接收中断的话,实际上就是在初始化函数中多了一条打开空闲中断的语句。

    串口中断函数

    串口中断函数里面,最重要的两条语句,就是上图中圈出来的两条语句。第一条语句用来判断是否接收到1个字节,第二条语句用来判断是否接收到1帧数据。(是不是感觉超级方便?妈妈再也不用担心我如何判断是否接收完1帧数据了。)

    主函数

    我写的这个主函数,是用来验证接收的正确性的。RxCounter表示的是这一帧数据有几个字节,接收完一帧数据,会在中断函数里面把ReceiveState置1,然后,通过串口把接收到的数据发送回串口。这样,既验证了接收了多少字节的正确性,又验证了接收到的数据是否正确。

    上图是结果验证。

    STM32串口接收不定长数据源程序

    /**

    ******************************************************************************

    * @file 串口接收不定长字节数据

    ******************************************************************************

    ******************************************************************************

    */

    /* Includes ------------------------------------------------------------------*/

    #include “stm32f10x.h”

    #include “uart.h”

    volaTIle uint8_t aRxBuffer[100]={0x00};

    volaTIle uint8_t RxCounter=0;

    volaTIle uint8_t ReceiveState=0;

    /**

    * @brief Main program.

    * @param None

    * @retval None

    */

    int main(void)

    {

    uint8_t i=0;

    USART1_Init();

    while (1)

    {

    if(ReceiveState==1)//如果接收到1帧数据

    {

    ReceiveState=0;

    i=0;

    while(RxCounter--)// 把接收到数据发送回串口

    {

    USART_SendData(USART1, aRxBuffer[i++]);

    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

    }

    RxCounter=0;

    }

    }

    }

    展开全文
  • 串口的时序和工作原理就不写了,主要写如何应用 串口的设置除了GPIO外,需要设置的参数有波特率、数据位、停止位,校验方式; GPIO输出配置AF_PP复用推挽输出 GPIO出入配置IN_FLAOTING浮空输入 USART的配置为115200...

    串口的设置

    串口的时序和工作原理就不写了,主要写如何应用
    串口的设置除了GPIO外,需要设置的参数有波特率、数据位、停止位,校验方式;
    GPIO输出配置AF_PP复用推挽输出
    GPIO出入配置IN_FLAOTING浮空输入
    USART的配置为115200的波特率,8位数据长度,1位停止位,无校验,无硬件流控制

    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    /* config USART1 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);//打开GPIO和USART1时钟
    
    /* USART1 GPIO config */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    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);    
    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* USART1 mode config */
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    
    /*使能串口1的接收中断 */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    //使能串口1
    USART_Cmd(USART1, ENABLE);
    

    配置接收中断的中断等级

    	
    NVIC_InitTypeDef NVIC_InitStructure; 
    /* Configure the NVIC Preemption Priority Bits */  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
    
    /* Enable the USARTy Interrupt */
    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);
    

    接收中断函数的实现

    void USART1_IRQHandler(void)
    {
    	uint8_t ch;
    	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    	{ 	
    	    //ch = USART1->DR;
    		ch = USART_ReceiveData(USART1);
    	  	printf( "%c", ch );    //将受到的内容发送出去
    	}  
    }
    

    发送数据的实现

    /* 发送一个字节到串口 */
    USART_SendData(USART1, (uint8_t) ch);
    /*等待发送完成*/
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    

    实现调试的printf,scanf函数

    实现printf和scanf函数必须要重写,并包含#include <stdio.h>

    /// 重定向c库中printf到USART1
    int fputc(int ch, FILE *f)
    {
    		USART_SendData(USART1, (uint8_t) ch);
    		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		
    	
    		return (ch);
    }
    
    /// 重定向c库中scanf到USART1
    int fgetc(FILE *f)
    {
    		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);//等待串口函数
    
    		return (int)USART_ReceiveData(USART1);
    }
    
    展开全文
  • 由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。 IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断。...
  • **STM32串口接收不定长数据原理与源程序** CSDN上有很多关于STM32串口接收不定长数据的文章,但实际使用后发现照搬他们的代码,程序根本就不能正确接收数据,其中最关键的一句有问题。其余内容完全正确。 文章...
  • STM32用CubeMx生成的HAL库效率很低,利用HAL自带的串口中断在接收大量数据时很容易出现数据丢失。一般来说,串口所接受的数据长度可能是不固定的。然而在一串数据的连续接收中,串口接收中断内实现的程序应尽可能...
  • STM32 IDLE中断

    千次阅读 2018-02-03 22:59:46
    STM32串口使用IDLE中断接收不定长数据原理与源程序 转载 2016年07月16日 18:20:24 原文来自 http://www.51hei.com/bbs/dpj-39885-1.html 今天说一下STM32单片机的接收不定长度字节数据的方法。...
  • STM32串口功能

    2019-01-23 21:58:56
    前言 实现与电脑调试助手相互透传,通过电脑发送字符0,关闭LED,通过电脑发送字符1,打开LED。 原理图1: ...3,配置中断,4写串口接收中断 void GPIO_Config() { GPIO_InitTypeDef GPIO_InitStrue; G...
  • 由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。 IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断...
  • 由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。IDLE中断什么时候发生?IDLE就是串口收到一帧数据后,发生的中断。...
  • 由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的ARM单片机。 IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断...
  • 中断原理讲解例程流程详解库函数分析详解对应寄存器介绍对应函数介绍对应注释详解本篇文章提供两种方法:一种是 :IDLE 接收空闲中断+DMA一种是: IDLE 接收空闲中断+RXNE接收数据中断都可完成串口数据的收发知识点...
  • 只说结果,uart原理 设置 网上介绍的都很详细了, 自己搜,这里使用的uart2 1、在uart.c里的uart初始化函数HAL_UART_MspInit 末端使能uart中断 /* USER CODE BEGIN USART2_MspInit 1 */ //使能uart中断 __...
  • STM32串口USART小结

    2019-03-02 08:14:39
    目录 5 串口USART 5.1 基本原理 (1)USART (2)/USART框图 (3)/波特率计算 5.2 硬件连接 ...5 串口USART ...端口复用+中断+USART 5.1 基本原理 (1)USART 通信方式 ...
  • STM32定时器中断显示时间

    千次阅读 2020-01-07 11:21:34
    利用STM32的定时器中断,实现时间的显示。我们知道利用定时器中断只能进行tick的计算,然而用来显示时间我们应该怎么办呢?经过项目的实际运用,我发现利用定时器中断配合串口通讯也能实现时间显示。 这种方法应用...
  • HAL库版本:v1.9.0(STM32Cube MCU Package for STM32F0 Series) 本文内容: 不定长数据接收的原理 串口接收中断的配置 串口接收DMA线的配置 示例程序及起运行流程 附件:代码工程(MDK) ...
  • STM32 HAL CubeMX 串口IDLE接收空闲中断+DMA

    千次阅读 多人点赞 2020-03-22 11:01:56
    STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收) 本篇文章我们仅针对例程进行详解剖析 本篇文章提供两种方法: 一种是 :IDLE 接收空闲中断+DMA 一种是: IDLE 接收空闲中断+RXNE接收数据中断 都可完成...
  • STM32 外部中断使用方法总结

    千次阅读 2018-03-23 13:18:55
    STM32 中断分为外部中断,定时器中断、串口中断。虽然名字不同,但是原理都是相同的,这一节我们将主要介绍一下外部中断以及中断函数的编写。按照如下步骤去编写函数和配置函数即可完成对外部中断函数的配置。第一步...
  • stm32F1的串口DMA和stm32F4的大同小异,使用时要区分通道和数据流区别。 直接上代码 usart.c #include "usart.h" uint8_t Uart1_Rx_Buff[DMA_UART1_RX_SIZE]; uint8_t Uart1_Tx_Buff[DMA_UART1_TX_SIZE]; ...
  • 针对STM32f1系列的代码,实现原理:ADC采集的数据在ADC的中断服务函数中通过串口通信发送出去,这样发送有一定的缺点,下面将分享两个资源,资源一:是通过中断标志位置位,然后在主函数中通过串口发送,提高ADC采样...
  • 原理:设置一个倒计时标志和接收完成标志,需要开启串口接收中断串口接收数据的时候重置倒计时时间,在定时器中递减该时间计数值,如果没有数据收发,时间计数值会减为0,证明数据接收完成,置位接收完成标志。 ...
  • 制定串口通信协议并定时发送一帧数据,常见的处理方法是利用空闲中断,但STM32 HAL库好像没有专用的空闲中断,自己实现起来比较麻烦,这里利用非空中断可以实现同样的功能,缺点是效率比较低,具体实现过程如下 ...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 124
精华内容 49
关键字:

stm32串口中断原理