你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

新手求教为什么串口接收数据总丢包

[复制链接]
益达zZ 提问时间:2017-10-30 11:06 /

接收数据为:BB 97 11 30 00 11 22 33 44 55 66 77 88 99 00 11 22 FD 6F 03 1A 0D 0A 1.png

发送端一直不定时发此类数据

但是我用STM32F103RCT6单片机接收丢包挺多,丢包的频率很规律  应该是我程序代码没写严谨,求大神指点





void Init_NVIC(void)
{         
        NVIC_InitTypeDef NVIC_InitStructure;                        //定义一个NVIC向量表结构体变量


        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //设置中断组 为2
  
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                                //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器
        
        
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;                                //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =        0;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器


        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;                                  //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器
        
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                                //配置串口1为中断源
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;           //设置占先优先级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                               //设置副优先级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能串口1中断
        NVIC_Init(&NVIC_InitStructure);                                                                                //根据参数初始化中断寄存器


        
}


void Init_Usart2(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;                                        //定义一个GPIO结构体变量


        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO ,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 ,ENABLE);               
                                                                                                                        //使能各个端口时钟,重要!!!


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                                 //配置串口发送端口挂接到9端口
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                           //复用功能输出开漏
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                   //配置端口速度为50M
  GPIO_Init(GPIOA, &GPIO_InitStructure);                                           //根据参数初始化GPIOA寄存器        


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;          //接收
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //浮空输入(复位状态);                                          
  GPIO_Init(GPIOA, &GPIO_InitStructure);                                           //根据参数初始化GPIOA寄存器        
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: Usart_Configuration
** 功能描述: 串口配置函数
** 参数描述: BaudRate设置波特率
** 作   者: Dream
** 日   期: 2011年6月20日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void Usart2_Configuration(uint32_t BaudRate)
{
        USART_InitTypeDef USART_InitStructure;                                                                    //定义一个串口结构体


        USART_InitStructure.USART_BaudRate            = BaudRate ;                                  //波特率115200
        USART_InitStructure.USART_WordLength          = USART_WordLength_8b;         //传输过程中使用8位数据
        USART_InitStructure.USART_StopBits            = USART_StopBits_1;                 //在帧结尾传输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);                                                                //根据参数初始化串口寄存器
        USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);                                                        //使能串口中断接收
        USART_Cmd(USART2, ENABLE);                                                                                             //使能串口外设
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: USART1_IRQHandler
** 功能描述: 串口中断函数
** 参数描述: 无
** 作   者: Dream
** 日   期: 2011年6月20日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void USART2_IRQHandler()        
{
        int i=0;
        u8 a=0;
        extern u8 UART2_Save_data_box[UART2_Save_data_box_number];                          //放置UART2接收到的字节  需要溢出归0
        extern u16 UART2_Save_data_box_pointer;                                                                  //放置UART2接收到的字节盒子下一个数据放置的位置指向标志        需要溢出归0
        extern u32 EPC_box[EPC_number];
        extern u16 EPC_box_pointer;
        extern u8 back_correct;
        extern u32 error1;
        extern u32 error2;
        extern u32 error3;
        extern u32 EPC_count_l;
        extern u32 EPC_count_h;
        extern u32 timer1;
        extern u8 zisuo3;
        
        
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)           //读取接收中断标志位USART_IT_RXNE
                                                                                                                //USART_FLAG_RXNE:接收数据寄存器非空标志位
                                                                                                                //1:忙状态  0:空闲(没收到数据,等待。。。)
        {
               
               
                if(UART2_Save_data_box[0]==0xBB)                                                                                          //判断数据包头
                {
                        UART2_Save_data_box[UART2_Save_data_box_pointer]=USART_ReceiveData(USART2);       //继续存储数据
                        UART2_Save_data_box_pointer++;
                        
                        
                        /*
                        if(UART2_Save_data_box[1]==0x98&&UART2_Save_data_box[5]==0x0D && UART2_Save_data_box[6]==0x0A)   //判断数据包尾
                        {
                                for(i=1;i<4;i++)                                                  //计算校验值
                                {
                                        a+=(u8)UART2_Save_data_box;
                                }
                                if(a==UART2_Save_data_box[4])                            //校验成功
                                {
                                        if(UART2_Save_data_box[3]==0x01)
                                        {
                                                back_correct=1;
                                                OUT2_LED=0;
                                        }
                                        else
                                        {
                                                back_correct=2;
                                        }
                                }
                                for(i=0;i<UART2_Save_data_box_number;i++)
                                {
                                        UART2_Save_data_box=0;                                   //一旦判断到数据包的尾部则数组初始化
                                }
                                UART2_Save_data_box_pointer=1;                                //一旦判断到数据包的尾部则置1
                        }
                        
                        
                        
                        else */if(UART2_Save_data_box[1]==0x97&&UART2_Save_data_box[21]==0x0D && UART2_Save_data_box[22]==0x0A)   //判断数据包尾
                        {
                                for(i=1;i<20;i++)                                                  //计算校验值
                                {
                                        a+=(u8)UART2_Save_data_box;
                                }
                                if(a==UART2_Save_data_box[20])                            //校验成功
                                {
                                        for(i=0;i<3;i++)
                                        {
                                                EPC_box[EPC_box_pointer]=(UART2_Save_data_box[i*4+5]<<24)+(UART2_Save_data_box[i*4+1+5]<<16)+(UART2_Save_data_box[i*4+2+5]<<8)+(UART2_Save_data_box[i*4+3+5]<<0);                  //存储EPC
                                                EPC_box_pointer++;
                                        }
                                        zisuo3=0;
                                        OUT1_jingbao=1;             //输出报警
                                        timer1=0;                                //计时清0
                                                
                                        EPC_count_l++;              //标签总数+1
                                        if(EPC_count_l>=1000000000)
                                        {
                                                EPC_count_l=0;
                                                EPC_count_h++;
                                        }
                                }
                                else
                                {
                                        error1++;                                                      //偶然错误 错误标志加1
                                }
                                for(i=0;i<UART2_Save_data_box_number;i++)
                                {
                                        UART2_Save_data_box=0;                                   //一旦判断到数据包的尾部则数组初始化
                                }
                                UART2_Save_data_box_pointer=1;                                //一旦判断到数据包的尾部则置1
                        }
                        
                        
                        
                        
                        
                        else if(UART2_Save_data_box_pointer>=23)                                                                                                //偶尔性的数据错误   开始清0
                        {
                                for(i=0;i<UART2_Save_data_box_number;i++)
                                {
                                        UART2_Save_data_box=0;                             
                                }
                                UART2_Save_data_box_pointer=1;     
                                error2++;                                                      //偶然错误 错误标志加1
                        }
                        
                        
                        
                        if(EPC_box_pointer>=EPC_number)
                        {
                                EPC_box_pointer=0;
                        }
                }
               
               
               
                else if(UART2_Save_data_box[0]==0x00)                                                              //如果上个数据不是数据包头
                {
                        UART2_Save_data_box[0]=USART_ReceiveData(USART2);                 //储存数据到UART2
                }
                else
                {
                        error3++;
                        UART2_Save_data_box[0]=USART_ReceiveData(USART2);                 //储存数据到UART2
                }
                USART_ClearITPendingBit(USART2,USART_IT_RXNE);                                                                                   //清除中断标志位
        }
}



收藏 1 评论8 发布时间:2017-10-30 11:06

举报

8个回答
anywill 回答时间:2017-12-5 09:25:09

数据包接收完UART2_Save_data_box_pointer应置0  

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

dzwwzd6699 回答时间:2017-12-5 10:41:21
是不是每次接收完没有清除标志位USART_IT_RXNE?
无薪税绵 回答时间:2017-12-5 10:48:25
请添加一个超时复位 UART2_Save_data_box_pointer 的功能。
因为,当数据接收不够 23 组时,你的程序没有做处理。
导致 UART2_Save_data_box_pointer 一直累加到大于等于23组时,你的程序才做处理。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

黑皮男 回答时间:2017-12-5 13:39:03
感觉楼主可以改下代码的结构,使用个万能的环形队列,中断只负责接收,数据放到主程序中进行解析,只要缓冲区内有完整的数据包就做相应的处理

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

党国特派员 回答时间:2017-12-5 16:22:26
丢包一般是时钟配置有点问题……

评分

参与人数 1ST金币 +1 收起 理由
zero99 + 1

查看全部评分

ctang 回答时间:2017-12-5 16:55:13
串口传输一次性不能超过64个字节,多余的要做分包处理。

评分

参与人数 1ST金币 +1 收起 理由
zero99 + 1

查看全部评分

kylongmu 回答时间:2017-12-5 17:18:40
额,你的串口中断太复杂了,根本不能这样写中断,中断只能进去判断有无,有就放到一个fifo结构里,立即退出。外面程序空闲时来处理fifo里的数据流。
就是这么垃圾的中断代码居然也是抄别人的:
** 作   者: Dream
** 日   期: 2011年6月20日

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

harvardx 回答时间:2017-12-5 18:02:56
语法上还是要尽量规范, 函数内 一般不提倡用extern ,可以通过包含头文件的形式搞定.

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版