OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 1630|回复: 1

修改了原来别人的工程,原来队列数据没有进行分帧处理,读队列数据读2次,清空队列数据;现在改成分帧,有时候不受控。

[复制链接]

20

主题

450

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4638
金钱
4638
注册时间
2017-7-6
在线时间
705 小时
发表于 2023-7-26 11:04:37 | 显示全部楼层 |阅读模式
10金钱
main:里面创建多个任务
static  void  AppTaskStart (void *p_arg)
{
        p_arg = p_arg;
               
        BSP_Init();            
        OS_CPU_SysTickInit();                

#if (OS_TASK_STAT_EN > 0)
    OSStatInit();         
#endif

    initAppStartData();

        DeviceInit();

        QueueCreate(CABuf,CABUF_QUEUE_ALL_SIZE, CABUF_QUEUE_SIZE, 0, 0);       
       
        OSTaskCreate(TaskBMS,                  0, StackBMS              +  (APP_TASK_START_STK_SIZE - 1),   APP_TASK_BMS_PRIO);
        OSTaskCreate(TaskTouch,          0, StackTouch            +  (APP_TASK_START_STK_SIZE - 1),   APP_TASK_TOUCH_PRIO);
        OSTaskCreate(Monitor,                  0, StackMonitor    +  (APP_TASK_START_STK_SIZE - 1),   APP_TASK_PEROIDSEND_PRIO);
        OSTaskCreate(SendTouch,          0, StackSend                    +  (APP_TASK_START_STK_SIZE - 1),   APP_TASK_SEND_PRIO);
        OSTaskCreate(AdcProcess,         0, StackADCProcess +  (APP_TASK_START_STK_SIZE - 1),   APP_ADC_PROCESS_PRIO);


        while(1)
        {
                RunJ1939Interface();
                DelayMs(1);       
        }  
}


和上位机通信的任务:
上面的#if 0是原来工程师搞的,读2次队列并读空,打开CAN报文标志if(g_CatchCanDataFlag)和透传CAN报文UartWrite(1, g_RS232SendBuf2, sendSize2);也是在ProModbusRTU_Frame2解析函数里面,可能就是这个读2次的原因。
后面发现上位机稍微数据发送太快,通过串口打印,发现会导致多帧数据叠加在一起,所以后面把他的改了,改成下面的分帧处理,并把透传CAN报文的函数移出来;发现打开CAN报文透传标志后,上位机控制下位机的某些动作失效,偶然性的,可能关机再开机还有可能是测试久了也会。
经过仿真也没看到具体原因,希望大佬指点一下,初次接触ucos。
void Monitor(void *p_arg)
{
    CPU_INT08U  os_err;
    uint16_t len2 = 0;
    uint8_t i;
    g_pUart232Sem2 = OSSemCreate(1);

    uint8_t tempBuffer[128];
    uint8_t index = 0;
    uint8_t RecvBuf;
    uint8_t sendSize2 = 0;
    ModbusRTU_Frame_t2 tempBuffer2;
    uint16_t DataCRC16 = 0;
       
    while(1)
    {     
        #if 0   
        OSSemPend(g_pUart232Sem2,0,&os_err);    //cnt信号量,大于0,执行该任务;等于0,等待信号量的队列
        len2 = ReadComFifo(&g_RS232Fifo2, g_RS232RecvBuf2, sizeof(g_RS232RecvBuf2));
        ProModbusRTU_Frame2(g_RS232RecvBuf2, len2);

        while(len2 = ReadComFifo(&g_RS232Fifo2, g_RS232RecvBuf2, sizeof(g_RS232RecvBuf2)))
        {
            ProModbusRTU_Frame2(g_RS232RecvBuf2, len2);                                       
        }
        if(g_CatchCanDataFlag)
        {
            OSSemPost(g_pUart232Sem2);  //释放信号量,有多少任务等待该g_pUart232Sem2信号量,最高优先级将得到信号量
        }   
        #endif


//        #if 0      
        OSSemPend(g_pUart232Sem2,0,&os_err);

        len2 = ReadComFifo(&g_RS232Fifo2, (char *)g_RS232RecvBuf2, sizeof(g_RS232RecvBuf2));  //读取队列多个数据,分帧处理

        for(i = 0;i < len2;i++)     //循环读取队列所有的数据,分帧处理
        {
           switch (m_frmAlaysisStep)
           {
               case 0:
               {
                    if (g_RS232RecvBuf2[i] == 0x7e)
                    {
                        index = 0;
                        tempBuffer[index++] = g_RS232RecvBuf2[i];
                        m_frmAlaysisStep = 1;
                    }
               }
               break;

               case 1:
               {
                    tempBuffer[index++] = g_RS232RecvBuf2[i];


                    if(tempBuffer[index-1] == 0x0D)
                    {
                        DataCRC16 = crc16(tempBuffer, index);

                        if (i+2 < len2)
                        {
                            tempBuffer[index++] = g_RS232RecvBuf2[i+1];
                            tempBuffer[index++] = g_RS232RecvBuf2[i+2];

                            if(DataCRC16 == ((tempBuffer[index - 2] << 8) + tempBuffer[index - 1]))
                            {
                                i += 2;   //校验成功,下一帧数据从上一帧校验后面开始循环    不加也行,多执行2次,浪费点时间而已
                                m_frmAlaysisStep = 0;
                                ProModbusRTU_Frame2(tempBuffer, index);
                            }                                 
                        }
                        else
                        {
                            m_frmAlaysisStep = 0;
                            break;
                        }
                    }
                }
                break;

                default:
                {
                    m_frmAlaysisStep = 0;
                }
                break;
            }
        }

        if(g_CatchCanDataFlag)
        {      
            if (UsartQueuePop(&buffer, &tempBuffer2) == TRUE)
            {
                sendSize2 = modbusRTU_Frame2Buf2(&tempBuffer2, g_RS232SendBuf2);
                UartWrite(1, g_RS232SendBuf2, sendSize2);                  //透传CAN报文                               
            }
            OSSemPost(g_pUart232Sem2);  //释放信号量,有多少任务等待该g_pUart232Sem2信号量,最高优先级将得到信号量
        }
//       #endif

        DelayMs(1);         
    }   
}



ProModbusRTU_Frame2的函数:

void ProModbusRTU_Frame2 (uint8_t *pReqFrameBuf2, uint16_t reqFrameBufSize2)
{
    uint16_t sendSize2 = 0,value = 0;
    uint16_t i = 0;
       
                ModbusRTU_Frame_t2 *pReqFrame2 = &g_ReqFrame2;
       
//                if(g_CatchCanDataFlag)    //用了分帧处理,把这个屏蔽,放外面去
//                {
//                        if (UsartQueuePop(&buffer, &g_RepFrame2) == TRUE)
//                        {
//                                sendSize2 = modbusRTU_Frame2Buf2(&g_RepFrame2, g_RS232SendBuf2);
//                                UartWrite(1, g_RS232SendBuf2, sendSize2);                                               
//                        }
//                }
        if (FALSE == buf2ModbusRTU_Frame2(pReqFrameBuf2, reqFrameBufSize2, pReqFrame2))//解析帧失败则直接返回
                return;

                g_MonitorTimer                         = 0;
                g_MonitorComFlag                 = 1;
                g_usartsendflag                 = 1;
               
                g_RepFrame2.SOI                 = g_SOI;
                g_RepFrame2.Addr1         = pReqFrame2->Addr1;
                g_RepFrame2.Addr2         = pReqFrame2->Addr2;
                g_RepFrame2.CMDType = pReqFrame2->CMDType | 0x40;
                g_RepFrame2.CMD                 = (uint8_t)pReqFrame2->CMD;
                g_RepFrame2.EOI                 = g_EOI;

                if(pReqFrame2->CMDType == FC_CMDTYPERead)
。。。。。。。。。。。。。逻辑处理的等语句
}

我是小白,很白很白的小白!!!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

20

主题

450

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4638
金钱
4638
注册时间
2017-7-6
在线时间
705 小时
 楼主| 发表于 2023-7-28 15:36:26 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 11:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表