精华内容
下载资源
问答
  • 串口中断接收的常见处理方法

    千次阅读 2016-06-08 13:49:51
    本例程通过PC机的串口调试助手将数据发送至STM32,接收数据后将所接收数据又发送至PC机,具体下面详谈。。。 实例一: void USART1_IRQHandler(u8 GetData) { u8 BackData; if(USART_GetITStatus

    原文地址:http://www.51hei.com/bbs/dpj-26383-1.html 作者:wangyin

    本例程通过PC机的串口调试助手将数据发送至STM32,接收数据后将所接收的数据又发送至PC机,具体下面详谈。。。


    实例一:
    void USART1_IRQHandler(u8 GetData)
    {
    u8 BackData;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //中断产生
    {  
    USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志.
    GetData = UART1_GetByte(BackData);   //也行GetData=USART1->DR;   
    USART1_SendByte(GetData);      //发送数据
    GPIO_SetBits(GPIOE, GPIO_Pin_8 ); //LED闪烁,接收成功发送完成
    delay(1000);
    GPIO_ResetBits(GPIOE, GPIO_Pin_8 );
    }
    }  
    这是最基本的,将数据接收完成后又发送出去,接收和发送在中断函数里执行,main函数里无其他要处理的。
    优点:简单,适合很少量数据传输。
    缺点:无缓存区,并且对数据的正确性没有判断,数据量稍大可能导致数据丢失 。


    实例二:
    void USART2_IRQHandler()  
    {
    if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生
    {  
    USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志
    Uart2_Buffer[Uart2_Rx_Num] = USART_ReceiveData(USART2);
    Uart2_Rx_Num++;
    }

    if((Uart2_Buffer[0] == 0x5A)&&(Uart2_Buffer[Uart2_Rx_Num-1] == 0xA5))  //判断最后接收的数据是否为设定值,确定数据正确性
    Uart2_Sta=1;
    if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) //溢出
    {
    USART_ClearFlag(USART2,USART_FLAG_ORE);  //读SR
    USART_ReceiveData(USART2); //读DR  
    }     
    }

    if( Uart2_Sta )
    {
    for(Uart2_Tx_Num=0;Uart2_Tx_Num < Uart2_Rx_Num;Uart2_Tx_Num++)
    USART2_SendByte(Uart2_Buffer[Uart2_Tx_Num]); //发送数据

    Uart2_Rx_Num = 0; //初始化
    Uart2_Tx_Num = 0;
    Uart2_Sta = 0;
    }
    这是加了数据头和数据尾的接收方式,数据头和尾的个数可增加,此处只用于调试之用。中断函数用于接收数据以及判断数据的头尾,第二个函数在main函数里按照查询方式执行。
    优点:较简单,采用缓存区接收,对提高数据的正确行有一定的改善 。
    缺点:要是第一次数据接收错误,回不到初始化状态,必须复位操作 。

    实例三:
    vvoid USART2_IRQHandler() 

         if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生 
         { 
            USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志. 
            Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2); 
            Uart2_Rx++; 
            Uart2_Rx &= 0x3F; //判断是否计数到最大
          } 
          if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) //溢出 
          { 
              USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR 
              USART_ReceiveData(USART2); //读DR 
           } 
    }

    if( Uart2_Tx != Uart2_Rx ) 

        USART2_SendByte(Uart2_Buffer[Uart2_Tx]); //发送数据 
        Uart2_Tx++; 
        Uart2_Tx &= 0x3F; //判断是否计数到最大
    }  
    采用FIFO方式接收数据,由0x3F可知此处最大接收量为64个,可变,中断函数只负责收,另一函数在main函数里执行,FIFO方式发送。
    优点:发送和接收都很自由,中断占用时间少,有利于MCU处理其它。
    缺点:对数据的正确性没有判断,一概全部接收。

    实例四: 
    void USART2_IRQHandler() 

         if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生 
         { 
            USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志
            Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2); 
            Uart2_Rx++; 
            Uart2_Rx &= 0xFF; 
         } 
         if(Uart2_Buffer[Uart2_Rx-1] == 0x5A) //头 
            Uart2_Tx = Uart2_Rx-1; 
         if((Uart2_Buffer[Uart2_Tx] == 0x5A)&&(Uart2_Buffer[Uart2_Rx-1] == 0xA5)) //检测到头的情况下检测到尾 
         { 
                Uart2_Len = Uart2_Rx-1- Uart2_Tx; //长度 
                Uart2_Sta=1; //标志位 
         } 
         if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) //溢出 
         { 
                USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR 
                USART_ReceiveData(USART2); //读DR 
         } 
    }

    if( Uart2_Sta ) 

            for(tx2=0;tx2 <= Uart2_Len;tx2++,Uart2_Tx++) 
            USART2_SendByte(Uart2_Buffer[Uart2_Tx]); //发送数据 
            Uart2_Rx = 0; //初始化 
            Uart2_Tx = 0; 
            Uart2_Sta = 0; 
    }

    数据采用数据包的形式接收,接收后存放于缓存区,通过判断数据头和数据尾(可变)来判断数据的“包”及有效性,中断函数用于接收数据和判断头尾以及数据包长度,另一函数在main函数里执行,负责发送该段数据。
    优点:适合打包传输,稳定性和可靠性很有保证,可随意发送,自动挑选有效数据。
    缺点:缓存区数据长度要根据“包裹”长度设定, 要是多次接收后无头无尾,到有头有尾的那一段数据恰好跨越缓存区最前和最后位置时,可能导致本次数据丢失,不过这种情况几乎没有可能。
    展开全文
  • 本例程通过PC机的串口调试助手将数据发送至STM32,接收数据后将所接收数据又发送至PC机,具体下面详谈。 实例一: void USART1_IRQHandler(u8 GetData) { u8 BackData; if(USART_GetITStatus(USART1, USART_IT_...

    本例程通过PC机的串口调试助手将数据发送至STM32,接收数据后将所接收的数据又发送至PC机,具体下面详谈。

    实例一:

    void USART1_IRQHandler(u8 GetData)
    {
    u8 BackData;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //中断产生
    {  
    USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志.
    GetData = UART1_GetByte(BackData);   //也可GetData=USART1->DR;   
    USART1_SendByte(GetData);      //发送数据
    GPIO_SetBits(GPIOE, GPIO_Pin_8 ); //LED闪烁,接收成功发送完成
    delay(1000);
    GPIO_ResetBits(GPIOE, GPIO_Pin_8 );
    }
    }  
    

    这是最基本的,将数据接收完成后又发送出去,接收和发送在中断函数里执行,main函数里无其他要处理的。
    优点:简单,适合很少量数据传输。
    缺点:无缓存区,并且对数据的正确性没有判断,数据量稍大可能导致数据丢失 。

    实例二:

    void USART2_IRQHandler()  
    {
    if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生
    {  
    USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志
    Uart2_Buffer[Uart2_Rx_Num] = USART_ReceiveData(USART2);
    Uart2_Rx_Num++;
    }
    
    if((Uart2_Buffer[0] == 0x5A)&&(Uart2_Buffer[Uart2_Rx_Num-1] == 0xA5))  //判断最后接收的数据是否为设定值,确定数据正确性
    Uart2_Sta=1;
    if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) //溢出
    {
    USART_ClearFlag(USART2,USART_FLAG_ORE);  //读SR
    USART_ReceiveData(USART2); //读DR  
    }     
    }
    
    if( Uart2_Sta )
    {
    for(Uart2_Tx_Num=0;Uart2_Tx_Num < Uart2_Rx_Num;Uart2_Tx_Num++)
    USART2_SendByte(Uart2_Buffer[Uart2_Tx_Num]); //发送数据
    
    Uart2_Rx_Num = 0; //初始化
    Uart2_Tx_Num = 0;
    Uart2_Sta = 0;
    }
    

    这是加了数据头和数据尾的接收方式,数据头和尾的个数可增加,此处只用于调试之用。中断函数用于接收数据以及判断数据的头尾,第二个函数在main函数里按照查询方式执行。
    优点:较简单,采用缓存区接收,对提高数据的正确行有一定的改善 。
    缺点:要是第一次数据接收错误,回不到初始化状态,必须复位操作 。

    实例三:

    vvoid USART2_IRQHandler() 
    { 
         if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生 
         { 
            USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志. 
            Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2); 
            Uart2_Rx++; 
            Uart2_Rx &= 0x3F; //判断是否计数到最大
          } 
          if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) //溢出 
          { 
              USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR 
              USART_ReceiveData(USART2); //读DR 
           } 
    }
    
    if( Uart2_Tx != Uart2_Rx ) 
    { 
        USART2_SendByte(Uart2_Buffer[Uart2_Tx]); //发送数据 
        Uart2_Tx++; 
        Uart2_Tx &= 0x3F; //判断是否计数到最大
    }  
    

    采用FIFO方式接收数据,由0x3F可知此处最大接收量为64个,可变,中断函数只负责收,另一函数在main函数里执行,FIFO方式发送。
    优点:发送和接收都很自由,中断占用时间少,有利于MCU处理其它。
    缺点:对数据的正确性没有判断,一概全部接收。

    实例四:

    void USART2_IRQHandler() 
    { 
         if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) //中断产生 
         { 
            USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中断标志
            Uart2_Buffer[Uart2_Rx] = USART_ReceiveData(USART2); 
            Uart2_Rx++; 
            Uart2_Rx &= 0xFF; 
         } 
         if(Uart2_Buffer[Uart2_Rx-1] == 0x5A) //头 
            Uart2_Tx = Uart2_Rx-1; 
         if((Uart2_Buffer[Uart2_Tx] == 0x5A)&&(Uart2_Buffer[Uart2_Rx-1] == 0xA5)) //检测到头的情况下检测到尾 
         { 
                Uart2_Len = Uart2_Rx-1- Uart2_Tx; //长度 
                Uart2_Sta=1; //标志位 
         } 
         if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) //溢出 
         { 
                USART_ClearFlag(USART2,USART_FLAG_ORE); //读SR 
                USART_ReceiveData(USART2); //读DR 
         } 
    }
    
    if( Uart2_Sta ) 
    { 
            for(tx2=0;tx2 <= Uart2_Len;tx2++,Uart2_Tx++) 
            USART2_SendByte(Uart2_Buffer[Uart2_Tx]); //发送数据 
            Uart2_Rx = 0; //初始化 
            Uart2_Tx = 0; 
            Uart2_Sta = 0; 
    }
    

    数据采用数据包的形式接收,接收后存放于缓存区,通过判断数据头和数据尾(可变)来判断数据的“包”及有效性,中断函数用于接收数据和判断头尾以及数据包长度,另一函数在main函数里执行,负责发送该段数据。
    优点:适合打包传输,稳定性和可靠性很有保证,可随意发送,自动挑选有效数据。
    缺点:缓存区数据长度要根据“包裹”长度设定, 要是多次接收后无头无尾,到有头有尾的那一段数据恰好跨越缓存区最前和最后位置时,可能导致本次数据丢失,不过这种情况几乎没有可能。

    展开全文
  • 现有一个小需求,使用STM32F1系列单片机做串口2的收发数据的功能,通过PC上的串口调试助手给单片机发一串数据,单片机收到数据后再给PC的串口调试助手发回去。 先前有一篇是通过串口查询方式实现的,本次使用串口...

    现有一个小需求,使用STM32F1系列单片机做串口2的收发数据的功能,通过PC上的串口调试助手给单片机发一串数据,单片机收到数据后再给PC的串口调试助手发回去。

    先前有一篇是通过串口查询方式实现的,本次使用串口中断方式实现。

    STM32使用USART2,对应单片机的PA1控制方向,PA2发送,PA3接收。

    代码如下:

    main.c

    #include "stm32f10x.h"
    
    
    u8 chs[128];
    u8 flag_recv;
    u8 len_recv;
    u8 *p_ch;
    
    void init_hardware_usart2_(u32 bound)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    	
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    	
    	USART_InitStructure.USART_BaudRate = bound;
    	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(USART2, &USART_InitStructure);
    	
    	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    	NVIC_Init(&NVIC_InitStructure);
    	
    	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    	USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
    	USART_Cmd(USART2, ENABLE);
    	USART_ClearFlag(USART2, USART_FLAG_TC);
    	
    	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
    }
    
    void func_usart2_send_a_byte_(u8 abyte)
    {
    	while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
    	USART_SendData(USART2, abyte);
    	while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
    }
    
    void func_usart2_send_bytes_(u8 *bytes, u8 bytes_len)
    {
    	u8 i;
    	GPIO_SetBits(GPIOA, GPIO_Pin_1);
    	for(i = 0; i < bytes_len; i++)
    	{
    		func_usart2_send_a_byte_(bytes[i]);
    	}
    	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
    }
    
    int main()
    {
    	//u8 recv_ch;
    	p_ch = chs;
    	len_recv = 0;
    	init_hardware_usart2_(9600);
    	
    	while(1)
    	{
    		
    	}
    }
    
    void USART2_IRQHandler(void)
    {
      u8 rx_dat;
      
      if(USART_GetITStatus(USART2,USART_IT_RXNE) == SET)
      {
    		flag_recv = 1;
        rx_dat = USART_ReceiveData(USART2);
    		if(p_ch < &chs[127])
    		{
    			*p_ch ++ = rx_dat;
    			len_recv ++;
    		}
    		
      }
    	if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
    	{
    		if(flag_recv == 1)
    		{
    			func_usart2_send_bytes_(chs, len_recv);
    			len_recv = 0;
    			p_ch = chs;
    		}
    		flag_recv = 0;
    	}
    }
    

    效果如下:

    测试1万多次,STM32都收到了,并成功转发了。

    测试代码,仅供参考。

    展开全文
  • 可能接收数据的时候会分成两次接收,即触发了两次串口中断,一次中断接收01 02 03 FF FF ,然后再一次中断接收37 12 53 75 12 FA AA 12 AA AA 52 73 57 12 53 AA AA 73 01 0F ,因为从打印结果如下! ![图片说明...
  • verilog串口接收多数据进行处理的实现方法

    万次阅读 热门讨论 2016-05-24 16:25:57
    关于使用串口接收多数据进行处理的问题,目前网上存在的关于verilog串口通信的资料都是属于讲解对于使用串口实现单个字符的接收与发送。而往往在使用串口进行通信时,接数据端都需要通过串口接收多数据,然后...

    关于使用串口接收多个数据进行处理的问题,目前网上存在的关于verilog串口通信的资料都是属于讲解对于使用串口实现单个字符的接收与发送。而往往在使用串口进行通信时,接数据端都需要通过串口来接收很多数据,然后当所有数据都接收完或者达到某种条件后开始自己的后续工作。所以在这里我把自己的一些具体实现过程以及verilog源代码分享一下,希望对大家有帮助。
    (这里只讲利用串口接收数据并处理的部分,发送那部分后面再分享)
    先贴上网上很多的串口接收的代码,如下;

    module my_uart_rx(
                    clk,rst_n,
                    rs232_rx,rx_data,rx_int,
                    clk_bps,bps_start
                );
    
    input clk;      // 50MHz主时钟
    input rst_n;    //低电平复位信号
    input rs232_rx; // RS232接收数据信号
    input clk_bps;  // clk_bps的高电平为接收或者发送数据位的中间采样点
    output bps_start;       //接收到数据后,波特率时钟启动信号置位
    output[7:0] rx_data;    //接收数据寄存器,保存直至下一个数据来到 
    output rx_int;  //接收数据中断信号,接收到数据期间始终为高电平
    
    //----------------------------------------------------------------
    reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;    //接收数据寄存器,滤波用
    wire neg_rs232_rx;  //表示数据线接收到下降沿
    
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
                rs232_rx0 <= 1'b0;
                rs232_rx1 <= 1'b0;
                rs232_rx2 <= 1'b0;
                rs232_rx3 <= 1'b0;
            end
        else begin
                rs232_rx0 <= rs232_rx;
                rs232_rx1 <= rs232_rx0;
                rs232_rx2 <= rs232_rx1;
                rs232_rx3 <= rs232_rx2;
            end
    end
        //下面的下降沿检测可以滤掉<20ns-40ns的毛刺(包括高脉冲和低脉冲毛刺),
        //这里就是用资源换稳定(前提是我们对时间要求不是那么苛刻,因为输入信号打了好几拍) 
        //(当然我们的有效低脉冲信号肯定是远远大于40ns的)
    assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0;    //接收到下降沿后neg_rs232_rx置高一个时钟周期
    
    //----------------------------------------------------------------
    reg bps_start_r;
    reg[3:0] num;   //移位次数
    reg rx_int;     //接收数据中断信号,接收到数据期间始终为高电平
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                bps_start_r <= 1'bz;
                rx_int <= 1'b0;
            end
        else if(neg_rs232_rx) begin     //接收到串口接收线rs232_rx的下降沿标志信号
                bps_start_r <= 1'b1;    //启动串口准备数据接收
                rx_int <= 1'b1;         //接收数据中断信号使能
            end
        else if(num==4'd11) begin       //接收完有用数据信息 ///将这个地方的num后面的数字改为了11.原来是12!!
                bps_start_r <= 1'b0;    //数据接收完毕,释放波特率启动信号
                rx_int <= 1'b0;         //接收数据中断信号关闭
            end
    
    assign bps_start = bps_start_r;
    
    //----------------------------------------------------------------
    reg[7:0] rx_data_r;     //串口接收数据寄存器,保存直至下一个数据来到
    //----------------------------------------------------------------
    
    reg[7:0] rx_temp_data;  //当前接收数据寄存器
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                rx_temp_data <= 8'd0;
                num <= 4'd0;
                rx_data_r <= 8'd0;
            end
        else if(rx_int) begin   //接收数据处理
            if(clk_bps) begin   //读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位     
                    num <= num+1'b1;
                    case (num)
                            4'd1: rx_temp_data[0] <= rs232_rx;  //锁存第0bit
                            4'd2: rx_temp_data[1] <= rs232_rx;  //锁存第1bit
                            4'd3: rx_temp_data[2] <= rs232_rx;  //锁存第2bit
                            4'd4: rx_temp_data[3] <= rs232_rx;  //锁存第3bit
                            4'd5: rx_temp_data[4] <= rs232_rx;  //锁存第4bit
                            4'd6: rx_temp_data[5] <= rs232_rx;  //锁存第5bit
                            4'd7: rx_temp_data[6] <= rs232_rx;  //锁存第6bit
                            4'd8: rx_temp_data[7] <= rs232_rx;  //锁存第7bit
                            default: ;
                        endcase
                end
            else if(num == 4'd11) begin     //我们的标准接收模式下只有1+8+1(2)=11bit的有效数据///将这个地方的num后面的数字改为了11.原来是12!!
                    num <= 4'd0;            //接收到STOP位后结束,num清零
                    rx_data_r <= rx_temp_data;  //把数据锁存到数据寄存器rx_data中
                end
            end
    
    assign rx_data = rx_data_r; 
    
    endmodule

    这里大致就是说串口接收单次数据的处理过程,接收完数据后产生发送标志位,开始发送数据,而对于这里要说的数据缓存处理有两种解决方法,
    第一种:十六进制传送,所以每次传送有效数据为八位,因此定义一个寄存器 reg [23:0] rx_cnt;长度为8的整数倍,然后使用移位的方式对数据进行存储,上述代码中NUM计数到11即完成一次数据传输,所以在num=11的地方加入

                    rx_cnt[7:0] <= rx_data_r;
                    rx_cnt[23:8] <= rx_cnt[15:0] ;
                    cnt <= cnt+1;//传送数据计数作用
                    if(cnt==NUMBER)//当传送数据达到NUMBER个时候,执行后续程序
                    begin
                    cnt<=cnt;
                    end
    assign rx_data_out = (cnt==NUMBER)?rx_cnt:rx_data_out;  
                      //传送数据达到NUMBER个时候,输出寄存器的数,
                      //此时寄存器含有传送的所有数据。

    然后把原本的输出口assign rx_data = rx_data_r;去掉,写新的输出
    接收的完整代码如下:

    //`timescale 1ns / 1ps
    
    module my_uart_rx(
                    clk,
                    rst_n,
                    rs232_rx,
                    rx_data,
                    rx_int,
                    start,
                    clk_bps,
                    bps_start,
                    rom_en,
                    rx_data_out
    
                );
    
    input clk;      // 50MHz主时钟
    input rst_n;    //低电平复位信号
    input rs232_rx; // RS232接收数据信号
    input clk_bps;  // clk_bps的高电平为接收或者发送数据位的中间采样点
    output bps_start;       //接收到数据后,波特率时钟启动信号置位
    output[7:0] rx_data;    //接收数据寄存器,保存直至下一个数据来到 
    output rx_int;  //接收数据中断信号,接收到数据期间始终为高电平
    output reg start;
    output wire [23:0] rx_data_out;
    //----------------------------------------------------------------
    reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;    //接收数据寄存器,滤波用
    wire neg_rs232_rx;  //表示数据线接收到下降沿
    reg [23:0] rx_cnt;
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n) begin
                rs232_rx0 <= 1'b0;
                rs232_rx1 <= 1'b0;
                rs232_rx2 <= 1'b0;
                rs232_rx3 <= 1'b0;
            end
        else begin
                rs232_rx0 <= rs232_rx;
                rs232_rx1 <= rs232_rx0;
                rs232_rx2 <= rs232_rx1;
                rs232_rx3 <= rs232_rx2;
            end
    end
        //下面的下降沿检测可以滤掉<20ns-40ns的毛刺(包括高脉冲和低脉冲毛刺),
        //这里就是用资源换稳定(前提是我们对时间要求不是那么苛刻,因为输入信号打了好几拍) 
        //(当然我们的有效低脉冲信号肯定是远远大于40ns的)
    assign neg_rs232_rx = rs232_rx3 & rs232_rx2 & ~rs232_rx1 & ~rs232_rx0;    //接收到下降沿后neg_rs232_rx置高一个时钟周期
    
    //----------------------------------------------------------------
    reg bps_start_r;
    reg[3:0] num;   //移位次数
    reg rx_int;     //接收数据中断信号,接收到数据期间始终为高电平
    
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                bps_start_r <= 1'bz;
                rx_int <= 1'b0;
            end
        else if(neg_rs232_rx) begin     //接收到串口接收线rs232_rx的下降沿标志信号
                bps_start_r <= 1'b1;    //启动串口准备数据接收
                rx_int <= 1'b1;         //接收数据中断信号使能
            end
        else if(num==4'd9) begin        //接收完有用数据信息 ///将这个地方的num后面的数字改为了11.原来是12!!
                bps_start_r <= 1'b0;    //数据接收完毕,释放波特率启动信号
                rx_int <= 1'b0;         //接收数据中断信号关闭
            end
    
    assign bps_start = bps_start_r;
    
    //----------------------------------------------------------------
    reg[7:0] rx_data_r;     //串口接收数据寄存器,保存直至下一个数据来到
    //----------------------------------------------------------------
    
    reg[7:0] rx_temp_data;  //当前接收数据寄存器
    reg [5:0]cnt;
    
    //assign led = (cnt==10)?1:0;
    always @ (posedge clk or negedge rst_n)
        if(!rst_n) begin
                rx_temp_data <= 8'd0;
                num <= 4'd0;
                cnt<= 0;
                start<=0;
                rx_cnt<=24'b0;
                //rx_data_out <= 384'd0;
                rx_data_r <= 8'd0;
            end
        else if(rx_int) begin   //接收数据处理
            if(clk_bps) begin   //读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位     
                    num <= num+1'b1;
                    case (num)
                            4'd1: rx_temp_data[0] <= rs232_rx;  //锁存第0bit
                            4'd2: rx_temp_data[1] <= rs232_rx;  //锁存第1bit
                            4'd3: rx_temp_data[2] <= rs232_rx;  //锁存第2bit
                            4'd4: rx_temp_data[3] <= rs232_rx;  //锁存第3bit
                            4'd5: rx_temp_data[4] <= rs232_rx;  //锁存第4bit
                            4'd6: rx_temp_data[5] <= rs232_rx;  //锁存第5bit
                            4'd7: rx_temp_data[6] <= rs232_rx;  //锁存第6bit
                            4'd8: rx_temp_data[7] <= rs232_rx;  //锁存第7bit
                            default: ;
                        endcase
                end
            else if(num == 4'd9) begin      //我们的标准接收模式下只有1+8+1(2)=11bit的有效数据///将这个地方的num后面的数字改为了11.原来是12!!
                    num <= 4'd0;            //接收到STOP位后结束,num清零
                    rx_data_r <= rx_temp_data;  //把数据锁存到数据寄存器rx_data中
                    cnt <= cnt+1;
                    rx_cnt[7:0] <= rx_data_r;
                    rx_cnt[23:8] <= rx_cnt[15:0] ;
                    if(cnt==NUMBER)//当传送数据达到NUMBER个时候,执行后续程序
                    begin
                    cnt<=cnt;
                    start<=1;//数据接收完成信号
                    end
                end
            end
    assign rx_data_out = (cnt==6'd48)?rx_cnt:rx_data_out;   
    endmodule
    

    波特率配置程序网上代码很多,这里就不贴出来了。

    展开全文
  • 最近没事瞎研究起来了STM32的串口接收功能,按照以前我的解决方案是 使用串口中断接收一个字符然后进中断处理,然后再手动写代码实现空闲读取,代码如下 // 全局数据定义 char rxBuff[64], *pRxBuff; char rxData...
  • CubeMX STM32串口1DMA使用IDLE中断接收串口2DMA接收DMX512信号(标准)DMX512协议CubeMX代码部分串口1生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚...
  • 之前在做项目的时候,串口接收数据要及时进行处理,虽然采用了自定义的串口协议,但是协议的包尾只有一个字节,经常判断不准数据是否接受完毕,所以就采用计时器+串口的方式来判定串口是否接受完成。 核心思想 ...
  • STM32CubeMX串口接收数据中断方式,HAL库)

    万次阅读 多人点赞 2018-01-31 16:30:13
    系统:linux mint 18.3 xfce 64bit 软件: STM32CubeMX 4.24 SW4STM32 2.4 ... 开发板芯片:STM32F103RCT6,STM32F407VET6...实现效果:打开两个串口助手窗口,一个是USART1的,一个是USART2的,任意一个串口串口1
  • 在使用单片机的串口通信功能时,常用的接收数据方法是通过固定的字节数来判断一帧数是否发送完成,或者是通过固定的结束标志位来表示一帧数据发送完成。但是有时候会遇到发送的数据长度不固定,也没有固定的结束标志...
  • 在我目前负责的项目,之前是使用串口接收中断来判断是否完成数据接收,项目的坑货前任最开始的方法是在串口接收中断里面清除标志,在微系统的数据处理里面对标志位++,判断如果两没进到接收中断就认为接收数据完成...
  • stm32的串口空闲中断接收数据

    千次阅读 2014-10-06 00:37:20
    整体的思路是这样的,一开始设置好DMA接收,可以把缓冲区长度设置为帧最大长度,我们可以把RX连接到定时器的管脚输入端,并且一开始设置输入并且使能引脚下降沿中断,当帧的第一个字节发送时,因为起始位为低电平,...
  • stm32串口中断接收一帧数据

    万次阅读 多人点赞 2017-02-18 17:11:53
    最近用到stm32的串口中断一个字符一个字符接收好心累,网上度了一下发现了一篇好的帖子,和大家分享一下,原贴地址:http://www.51hei.com/bbs/dpj-39885-1.html 再次感谢原贴楼主的分享,为了方便大家,我把原文...
  • 串口是一种很常见的通讯接口,通过串口回传数据是很智能型的传感器都拥有的特点。...主要思想: 配置一个串口DMA接收 任务,任务搬运的数据量要大于一通讯的总数据量(也就是DMA 的搬运工作还没结束 我...
  • STM32串口中断接收一帧数据 IDLE即串口空闲中断串口收到一帧数据后,发生的中断。比如说给单片机一发来1个字节,或者一发来8个字节,这些一发来的数据,就称为一帧数据,也可以叫做一包数据。因为只有接收...
  • STM32使用HAL库DMA+空闲中断实现串口不定长数据接收

    千次阅读 多人点赞 2020-09-03 16:48:12
    STM32使用HAL库DMA+空闲中断实现串口不定长数据接收 环境: STM32CubeIDE STM32F103RB WIN10 HAL库V1.8 首先配置串口: 开启串口中断: 开启DMA接收: 配置中断分组: 取消自动生成串口1的中断服务程序,...
  • 串口接收中断中断标志为:USART_IT_RXNE,即rx none empty,串口只要接收到数据就触发中断,如果是接收一个字符串,则每接收到一个字符就触发一中断。串口空闲中断中断标志为:USART_IT_IDLE,idle即空闲的意思,...
  • 2、中断接收代码: #define RECVSIZE 50 #define SET_GPIO5_HIGH GPIO_SetPins(GPIO_PIN_5); #define SET_GPIO5_LOW GPIO_ResetPins(GPIO_PIN_5); unsigned char receivedata[RECVSIZE]={0},datatemp, icount,...
  • 》中鱼鹰分析了串口接收的一些坑,这些经验对于写一个好的串口接收程序是很有帮助的,而且笔记中最后得出一个串口接收的总结“空闲中断 + DMA + 队列 + 内存管理 + 定时控制”。因为空闲中断的误触发,导致我们不得...
  • DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候,CPU 可以干其他的事情,好像是线程一样。 数据传输支持从外设到存储器或者...
  • STM32串口接收中断溢出问题解决

    万次阅读 多人点赞 2017-07-29 23:45:58
    在使用一个串口数据的传感器过程中,发现程序第一进入串口中断之后不再执行主函数的内容,中断中的内容也不执行。...ORE标志位在USART_SR寄存器,但值得注意的是,当我们打开串口接收中断时,同时也就打开了ORE中
  • 串口接收中断 中断标志为:USART_IT_RXNE,即rx none empty,串口只要接收到数据就触发中断,如果是接收一个字符串,则每接收到一个字符就触发一中断。 串口空闲中断 中断标志为:USART_IT_IDLE,idle即空闲的意思...
  • 以前串口中断接收串口数据都是利用了裸机程序,今天把ucos系统在STM32跑了起来,当然也想利用串口中断接收一下串口数据,下面看看具体步骤。 第一步:在OS系统的start任务中,调用USART1的初始化程序。串口1的初始...
  • 2021/07/20 悍匠暑假集训第三天单个串口收发1、串口在cubeMX中配置2、串口接收中断与空闲中断3、串口发送数据4、串口中断接收字符串数据注意:每次中断只能接收一个字符!!!为了实现多次数据返回,我们要在中断...
  • 串口接收处理思路

    千次阅读 2017-01-10 15:13:27
    串口接收处理思路
  • STM32之串口DMA接收不定长数据

    万次阅读 多人点赞 2018-09-17 15:49:25
    STM32之串口DMA接收不定长数据 本文为杰杰原创,如需转载请说明出处 引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? ...
  • 今天说一下STM32单片机的接收不定长度字节数据的方法。...IDLE就是串口收到一帧数据后,发生的中断。什么是一帧数据呢?比如说给单片机一发来1个字节,或者一发来8个字节,这些一发来的数据,就称为一帧数据,也
  • 最近调试过程中遇到一个小问题,也是大问题 网上的资料很少,记录一下,...数据只能执行一,估计是缓冲区被占位,必须读取出来才能继续接收 日后有时间再研究一下 解决方法 加上Res = UART_ReceiveData(UART2); ...
  • 在前两篇文章中我们介绍了IO口模拟串口发送数据接收数据,前两种方法都是使用定时器来进行发送和接收,没有用到中断,优点是逻辑简单,但是缺点很明显,只能进行单个字节的发送和接收,而且不能同时工作。...
  •   此工程的硬件环境为尚学STM32F103ZET6核心板+正点原子3.5寸TFTLCD ...  在实际做项目的时候,经常需要用串口接收数据,一般是使用串口中断接收数据。但是用这种方法的话,就要频繁进入串口中断,效率...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,254
精华内容 5,301
关键字:

串口多次接收数据中断处理