精华内容
下载资源
问答
  • STM32的DMA+IDLE中断可用来接收不定长数据包,十分的方便。但当数据发送端在发送数据时,系统发生线程调度或因其他原因打断发送,会使的单片机仅接收到部分数据变发生空闲中断,如果程序设计的不好,会导致接收不到...
    展开全文
  • //进入中断接收数据的数组 uint8_t DataBuff[5000]; //保存接收到的数据的数组 int RxLine=0; //接收到的数据长度 int Rx_flag=0; //接受到数据标志 int Rx_flag_finish=0; //接受完成或者时间溢出 void user_uart_...

    概述

    本篇文章主要介绍如何使用e2studio对瑞萨单片机进行USRT通过定时器中断方式接收不定长数据。

    在这里插入图片描述

    硬件准备

    首先需要准备一个开发板,这里我准备的是芯片型号R7FA2L1AB2DFL的开发板:

    在这里插入图片描述

    新建工程

    在这里插入图片描述

    工程模板

    在这里插入图片描述

    保存工程路径

    在这里插入图片描述

    芯片配置

    本文中使用R7FA2L1AB2DFL来进行演示。
    在这里插入图片描述

    工程模板选择

    在这里插入图片描述

    UART配置

    点击Stacks->New Stack->Driver->Connectivity -> UART Driver on r_sci_uart。

    在这里插入图片描述

    UART属性配置

    在这里插入图片描述

    PRINTF重定向

    PRINTF重定向已经在上述文章中讲述,故可以查看往期文章进行学习。
    打印最常用的方法是printf,所以要解决的问题是将printf的输出重定向到串口,然后通过串口将数据发送出去。
    注意一定要加上头文件#include <stdio.h>

    #ifdef __GNUC__                                 //串口重定向
        #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
        #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif
    
    PUTCHAR_PROTOTYPE
    {
            err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);
            if(FSP_SUCCESS != err) __BKPT();
            while(uart_send_complete_flag == false){}
            uart_send_complete_flag = false;
            return ch;
    }
    int _write(int fd,char *pBuffer,int size)
    {
        for(int i=0;i<size;i++)
        {
            __io_putchar(*pBuffer++);
        }
        return size;
    }
    

    回调函数user_uart_callback ()

    设置接受到0xff则输出已经输入的数据。
    若接收到新的数据,使用R_GPT_Reset进行充值定时器计数。

    volatile bool uart_send_complete_flag = false;
    
    uint8_t RxBuff[1];      //进入中断接收数据的数组
    uint8_t DataBuff[5000]; //保存接收到的数据的数组
    int RxLine=0;           //接收到的数据长度
    int Rx_flag=0;                  //接受到数据标志
    int Rx_flag_finish=0; //接受完成或者时间溢出
    
    void user_uart_callback (uart_callback_args_t * p_args)
    {
        if(p_args->event == UART_EVENT_TX_COMPLETE)
        {
            uart_send_complete_flag = true;
        }
     if(p_args->event ==     UART_EVENT_RX_CHAR)
        {
            RxBuff[0] = p_args->data;
            RxLine++;                      //每接收到一个数据,进入回调数据长度加1
            DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组
            Rx_flag=1;
            if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
            {
                Rx_flag_finish=1;
            }
            RxBuff[0]=0;
            err = R_GPT_Reset(&g_timer0_ctrl);
            assert(FSP_SUCCESS == err);
        }
    }
    
    

    printf_usart打印函数

    打印已经接受的数据以及其长度。

    void printf_usart(void)
    {
    
        printf("length=%d\r\n",RxLine);
        for(int i=0;i<RxLine;i++)
            printf("data:[%d] = 0x%x\r\n",i,DataBuff[i]);
        memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
        //memset()作用:可以方便的清空一个结构类型的变量或数组。
        //例句:memset(aTxbuffer,0,sizeof(aTxbuffer))  用memset清空aTxbuffer。
        RxLine=0;  //清空接收长度
        Rx_flag_finish=0;
        Rx_flag = 0;
    }
    
    

    定时器设置

    点击Stacks->New Stack->Driver->Timers -> Timers Driver on r_gpt。
    在这里插入图片描述
    设置500ms无输入则输出已经输入的数据。
    频率=时钟源/period,若设置计数时间为500ms一次,频率为1Hz,则period=48M/1=48000000

    在这里插入图片描述

    定时器回调函数timer0_callback()

     /* Callback function */
        void timer0_callback(timer_callback_args_t *p_args)
        {
            /* TODO: add your own code here */
            if (TIMER_EVENT_CYCLE_END == p_args->event)
            {
                if(Rx_flag==1)
                {
                    printf_usart();
                    Rx_flag=0;
                }
            }
    }
    
    

    完整代码

    #include "hal_data.h"
    #include <stdio.h>
    FSP_CPP_HEADER
    void R_BSP_WarmStart(bsp_warm_start_event_t event);
    FSP_CPP_FOOTER
    
    void printf_usart(void);
    
    fsp_err_t err = FSP_SUCCESS;
    volatile bool uart_send_complete_flag = false;
    
    uint8_t RxBuff[1];      //进入中断接收数据的数组
    uint8_t DataBuff[5000]; //保存接收到的数据的数组
    int RxLine=0;           //接收到的数据长度
    int Rx_flag=0;                  //接受到数据标志
    int Rx_flag_finish=0;                  //接受完成或者时间溢出
    void user_uart_callback (uart_callback_args_t * p_args)
    {
        if(p_args->event == UART_EVENT_TX_COMPLETE)
        {
            uart_send_complete_flag = true;
        }
        if(p_args->event ==     UART_EVENT_RX_CHAR)
        {
            RxBuff[0] = p_args->data;
            RxLine++;                      //每接收到一个数据,进入回调数据长度加1
            DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组
            Rx_flag=1;
            if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
            {
                Rx_flag_finish=1;
            }
            RxBuff[0]=0;
            err = R_GPT_Reset(&g_timer0_ctrl);
            assert(FSP_SUCCESS == err);
        }
    }
    #ifdef __GNUC__                                 //串口重定向
        #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
        #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif
    PUTCHAR_PROTOTYPE
    {
            err = R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)&ch, 1);
            if(FSP_SUCCESS != err) __BKPT();
            while(uart_send_complete_flag == false){}
            uart_send_complete_flag = false;
            return ch;
    }
    int _write(int fd,char *pBuffer,int size)
    {
        for(int i=0;i<size;i++)
        {
            __io_putchar(*pBuffer++);
        }
        return size;
    }
    /* Callback function */
        void timer0_callback(timer_callback_args_t *p_args)
        {
            /* TODO: add your own code here */
            if (TIMER_EVENT_CYCLE_END == p_args->event)
            {
                if(Rx_flag==1)
                {
                    printf_usart();
                    Rx_flag=0;
                }
            }
    }
    void hal_entry(void)
    {
        /* TODO: add your own code here */
        /* Open the transfer instance with initial configuration. */
        err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
        assert(FSP_SUCCESS == err);
        /* Initializes the module. */
        err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
        /* Handle any errors. This function should be defined by the user. */
        assert(FSP_SUCCESS == err);
        /* Start the timer. */
        (void) R_GPT_Start(&g_timer0_ctrl);
              while(1)
              {
                  R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS); // NOLINT100->160
                  if(Rx_flag_finish==1)
                  {
                          printf_usart();
                  }
              }
    
     #if BSP_TZ_SECURE_BUILD
           /* Enter non-secure code */
           R_BSP_NonSecureEnter();
       #endif
       }
    
    void printf_usart(void)
    {
    
        printf("length=%d\r\n",RxLine);
        for(int i=0;i<RxLine;i++)
            printf("data:[%d] = 0x%x\r\n",i,DataBuff[i]);
        memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
        //memset()作用:可以方便的清空一个结构类型的变量或数组。
        //例句:memset(aTxbuffer,0,sizeof(aTxbuffer))  用memset清空aTxbuffer。
        RxLine=0;  //清空接收长度
        Rx_flag_finish=0;
        Rx_flag = 0;
    }
    
    

    发送数据,并且以0xff结尾

    在这里插入图片描述

    发送数据,延时500ms后打印

    在这里插入图片描述

    最后

    以上的代码会在Q群里分享。QQ群:615061293。
    或者关注微信公众号『记帖』,持续更新文章和学习资料,可加作者的微信交流学习!
    在这里插入图片描述

    展开全文
  • 串口接收中断程序配置过程(HAL) 初始化相关参数,使能串口: HAL_UART_Init(); 串口相关IO口配置,复用配置。在HAL_UART_MspInit中调用HAL_GPIO_Init函数 串口接收中断优先级配置和使能 HAL_NVIC_...

    串口接收中断程序配置过程(HAL)

    1. 初始化相关参数,使能串口:
    HAL_UART_Init();
    

    该函数的参数是串口的基址,在stm32f429xx.h文件中,定义了8个UART_HandleTypeDef的值,分别是USART1、USART2、USART3、UART4、UART5、USART6、UART7、UART8,可以用HAL_UART_Init对这8个串口进行初始化,我们要用USART1,就填USART1

    1. 串口相关IO口配置,复用配置。在HAL_UART_MspInit中调用HAL_GPIO_Init函数

    2. 串口接收中断优先级配置和使能

    HAL_NVIC_EnableIRQ();
    HAL_NVIC_SetPriority();
    
    1. 使能串口接收中断
      所有的串口都使用HAL_UART_Receive_IT使能接收中断
    HAL_UART_Receive_IT();
    
    1. 编写中断服务函数:USARTx_IRQHandler
      这个函数在startup_stm32f429xx.s中可以找到。
      不同的串口有不同的中断服务函数
    void USARTx_IRQHandler(void) ;//(x=1~3,6)
    void USARTx_IRQHandler(void) ;//(x=4,5,7,8)
    

    具体配置过程

    我们通过电脑把数据发送给STM32,STM32收到数据之后再把数据发送给电脑

    1. 初始化相关参数,使能串口
    UART_HandleTypeDef usart_handler;	//定义为全局变量
    void usart1_init(void)
    {
    	
    	
    	usart_handler.Instance = USART1;						//指定用哪个串口
    	usart_handler.Init.BaudRate = 115200;					//波特率设置
    	usart_handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;		//硬件流控制
    	usart_handler.Init.Mode = UART_MODE_TX_RX;				//接收or发送or接收发送
    	//usart_handler.Init.OverSampling = 
    	usart_handler.Init.Parity = UART_PARITY_NONE;			//奇偶校验
    	usart_handler.Init.StopBits = UART_STOPBITS_1;			//停止位
    	usart_handler.Init.WordLength = UART_WORDLENGTH_8B;		//字长
    	HAL_UART_Init(&usart_handler);
    	
    }
    
    1. 串口相关IO口配置,复用配置。在HAL_UART_MspInit中调用HAL_GPIO_Init函数
    //HAL_UART_Init会自动调用HAL_UART_MspInit
    
    void HAL_UART_MspInit(UART_HandleTypeDef *huart)
    {
    	if(huart->Instance == USART1)
    	{
    		GPIO_InitTypeDef GPIO_Initure;
    		__HAL_RCC_GPIOA_CLK_ENABLE();
    		__HAL_RCC_USART1_CLK_ENABLE();
    		//GPIO口初始化就配置好了复用功能
    		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
    		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
    		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
    		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
    		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
    		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9
    		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
    		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
    		HAL_NVIC_EnableIRQ(USART1_IRQn);
    		HAL_NVIC_SetPriority(USART1_IRQn,3,3);
    	}
    }
    

    HAL_UART_Init初始化串口后,会自动调用HAL_UART_MspInit,我们在HAL_UART_MspInit里面初始化相关GPIO、设置中断优先级以及使能中断。

    1. 串口接收中断优先级配置和使能,在步骤2实现了

    2. 使能接收中断,我们在main函数里面加入一行代码来使能接收中断,该中断对所有的UART中断都产生影响。

    HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
    

    第一个参数usart_handler是UART_HandleTypeDef类型的句柄,第二个参数是接收数据存放的位置,第三个是位置大小。经过这四个步骤,我们就配置好了接收中断。

    1. 编写中断服务函数:USARTx_IRQHandler
    void USART1_IRQHandler(void)	
    {
    	HAL_UART_IRQHandler(&usart_handler);
    	HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
    }
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    	if(huart->Instance == USART1)
    	{
    		HAL_UART_Transmit(huart,rdata,sizeof(rdata),1000);
    		
    	}
    	
    }
    

    HAL提供了中断处理函数HAL_UART_IRQHandler,具体流程如下:
    在这里插入图片描述

    前面四个步骤是配置接收中断的,那么什么时候产生中断呢?
    我们使能接收中断函数是:

    HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
    

    当接收的数据为sizeof(rdate)字节时,就会产生中断,进入USART1_IRQHandler函数,USART1_IRQHandler调用HAL库提供的中断处理函数HAL_UART_IRQHandler来判断中断类型,进而调用不同的处理函数。我们这里是接收中断,所以会进入UART_Receive_IT函数,把数据放到rdata,处理完毕后,UART_Receive_IT会自动调用HAL_UART_RxCpltCallback回调函数,这个函数我们是可以重写的,我们可以写出我们想要的逻辑处理功能函数,在这里调用HAL_UART_Transmit发送数据。

    当接收完数据之后,系统会关闭中断,所以我们还需要打开中断,接收下一位数据,USART1_IRQHandler中调用HAL_UART_Receive_IT开启中断

    具体main函数代码:

    int main(void)
    {
    	//u8 buff[] = "send to rec";
    	
    	HAL_Init();
    	Stm32_Clock_Init(360,25,2,8);
    	delay_init(180);
    	usart1_init();
    	HAL_UART_Receive_IT(&usart_handler,rdata,sizeof(rdata));
    	while(1)
    	{
    		
    	}
    	
    }
    

    结果

    在这里插入图片描述

    展开全文
  • 配置串口通信模式时设置成了同步模式,改成异步模式就好了 有些串口调试助手(如win10商店的免费的串口调试助手)不能正确显示接收的字符,需要换调试软件。

    配置串口通信模式时设置成了同步模式,改成异步模式就好了

    有些串口调试助手(如win10商店的免费的串口调试助手)不能正确显示接收的字符,需要换调试软件。

     

    展开全文
  • STM32串口中断接收一帧数据

    千次阅读 2021-01-03 22:52:57
    STM32串口中断接收一帧数据 IDLE即串口空闲中断,串口收到一帧数据后,发生的中断。比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据。因为只有接收...
  • 在使用STM32的串口接收数据的时候,我们常常会使用接收中断方式接收数据,常用的是RXNE。这里分享另一种接收数据的方式——IDLE中断(PS:本文的例子运行在STM32F103ZET6上)。一、IDLE中断什么时候发生?IDLE就是...
  • 请教大家关于CAN中断接收的问题。

    千次阅读 2020-12-24 11:49:58
    我现在是让一个板子一直发消息,另一个板子产生接收中断,进入接收中断服务程序。但是一直进不去。还请大家帮忙看看问题出在哪里?可能就是一语惊醒梦中人啊。下面这部分是发送程序。应该没什么问题,在串口显示是...
  • 1、使能接收中断 IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x0080); //使能接收中断 2、中断定义如下 char *p; alt_ic_isr_register (UART_0_IRQ_INTERRUPT_CONTROLLER_ID, //ID ...
  • 串口接收 串口接收流程 编程USARTx_CR1的M位来定义字长。...如果要使能接收中断接收到数据后产生中断),使能USARTx_CR1的RXNEIE位为1。 当串口接收到数据时 USARTx_SR(ISR)的RXNE位置1。表明移
  • 串口进不了接收中断

    2021-05-25 02:05:30
    } //串行接收结束中断服务程序 //#pragma interrupt_handler usart_rx_isr:14 //void usart_rx_isr(void) SIGNAL(_VECTOR(13)) { data = UDR; flag = 1; } void uart_put_c(char data_c) { while ( !( UCSRA & (1; ...
  • 文章目录前言第一步:用于保存数据的数组和变量第二步:定义串口初始化函数第三步:定义串口数据发送函数第四步:重写中断服务函数第五步:在 main 函数中处理接收到的数据并通过串口发送出去 前言 测试过程中使用...
  • 内容来自SJTU,IPADS OS-16-Networklinux既然要讲,那就把一个包的整个包生都说了算了触发中断在非虚拟化环境下,网卡通过DMA将packet写入内核的rx_ring环形队列缓冲区,并触发中断。如果在虚拟化环境下,VMM配置GIC ...
  • 目录一、CubeMX配置1、时钟设置2、CAN1设置1)引脚修改2)中断使能3)波特率计算3、SYS设置4、GPIO设置5、软件包版本二、手动添加代码1、添加屏蔽器设置代码2、添加CAN发送代码3、添加CAN代码的初始化函数4、添加CAN...
  • LWIP中断接收调试

    2020-12-30 15:03:19
    在POLL模式转为中断模式的时候发现ping时间很久而且经常超时,屏蔽掉如下耗时的打印代码就好了 PRINT_INFO("receive frame %d len buffer : %s\n", len, buffer);
  • 1,电脑通过串口1给STM32F407芯片发送数据(不定长,按照645格式来),芯片根据串口接收中断接收到数据后,通过DMA将数据存储在内存。当检测到数据接受完毕,产生接收完成标志位置位。当407检测到这个中断标志位后从...
  • 51命令接收
  • 现在有很多数据处理都要用到不定长数据,而单片机串口的RXNE中断一次只能接收一个字节的数据,没有缓冲区,无法接收一帧多个数据,现提供两种利用串口IDLE空闲中断方式接收一帧数据,方法如下:方法1:实现思路:...
  • stm32串口的中断接收

    2021-04-09 10:30:21
    在找中断服务函数,使用了USART1就用1的函数,定义为void类型 USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);//得到中断标志函数 USART_ReceiveData(USART1);//串口数据接收函数
  • STM32HAL库USART中断接收不定长数据——空闲中断法STM32cubeMX软件配置好串口中断,导出工程并打开,定义串口接收缓冲区和接收长度的全局变量:uint8_tRX_data[1000];uint16_tRX_len;在main函数的初始化中开启IDLE...
  • 二、通信接口的数据接收方式 相信有过单片机、微控制器或者微处理器开发经验的人都知道(以下都简称微控制器吧),微控制器有各种通信接口,比如说UART、CAN、I2C、SPI、DCMI等等,这些通信接口在通信速度、通信稳定...
  • #include "DSP28x_Project.h"// Device Headerfile and Examples Include Fileinterrupt void scibTxFifoIsr(void);//fifo发送中断函数interrupt void ...//fifo接收中断函数void scib_fifo_init(void);//scib ...
  • 微信接收文件中断(解决方法)

    千次阅读 2021-12-15 20:36:54
    微信接收文件中断|文件中断|无法接收微信文件
  • 并不是说不使能串口接受中断就无法接收数据,只是为了在串口接收数据的时候防止其程序打扰串口数据的接收,所以跑到中断中去接收数据。 不使用串口接收中断的情况下,数据会到DR,然后你及时把DR的数据读出来,不然...
  • 软件:采用库函数开发,开发工具为IAR 7.10,485接的是stm32的串口1(收发都是用中断方式),半双工模式, 协议是MODBUS RTU。先说明本人是菜鸟,在不断得学习中,欢迎指出错误。最近在调试RS485时发现一个问题,如果...
  • W5500收到数据后会产生RECV中断,当回环测试时,正常清掉RECV中断后,由于采用的回环测试方式,W5500又将同一包数据发送了出去,所以又会产生SEND_OK中断。 解决方案: 此时需要再次清SEND_OK中断,或者改用单向测试...
  • STM32串口中断接收实验的详细说明准备代码实现总结 准备 材料:STM32F407ZGT6最小系统板,串口1通过跳线帽连接到了CH340上。 需求:从电脑向板子的串口1发送一个字符串(以回车和换行结尾,字符串末尾两个字符为0x0...
  • 本文介绍串口中断接收不定长字符串的方法。采用定时中断给串口2的接收提供定时,再一次中断内(1ms)接收数据的长度不变则认为接收完成。 board_uart.h /**=======================================================...
  • ESP8266 Arduino 串口中断接收 #include <ESP8266WiFi.h> String rx_data; void setup() { Serial.begin(115200); delay(10); Serial.println(); Serial.println(); Serial.println("start: "); } ...
  • CA1N1、CAN2总线接收,中断接收。 平台:STM32F405RGT6、标准库。 CAN1配置 void CAN1_Mode_Init(u8 mode) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_...
  • 本文介绍串口中断接收不定长字符串的方法。将串口1配置接收中断使能、空闲中断使能来接收不定长数据。 也就是在配置串口中断的时候使能接收中断和空闲中断。如下: ... USART_ITConfig(USART1, USART_IT_RXNE, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 255,993
精华内容 102,397
关键字:

中断方式接收