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

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

[复制链接]
益达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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版