| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2602 人关注过本帖
标题:CAN接口卡读取数据线程问题?
只看楼主 加入收藏
喜鹊王子
Rank: 1
等 级:新手上路
帖 子:105
专家分:0
注 册:2012-12-25
结帖率:89.74%
收藏
已结贴  问题点数:20 回复次数:4 
CAN接口卡读取数据线程问题?
点击“启动CAN”按钮会开启“CAN接收数据”线程,
1. 但是记得《VC++深入详解》这本书上介绍过:只有主线程处于睡眠状态时,辅助线程才工作,但是OnBtnStartcan()函数中没有Sleep();那么ReceiveThread怎么还会工作,此时,能将数据显示在列表控件中;
2. 如果将红色部分的Sleep(8000)不注释的话,列表控件要等8秒钟才会有显示,这是什么原因?
3. 红色部分的Sleep(500)和Sleep(1)只是停顿作用吧?

void CCOMMUNICATIONSet::OnBtnStartcan() //“启动CAN”按钮
{
    // TODO: Add your control notification handler code here
    if(m_connect==1)  //如果已经连接
    {
        m_connect=0;
        m_startcanlight.SetIcon(m_hIConGrey1);
        Sleep(500);
        GetDlgItem(IDC_EDIT_BTR)->EnableWindow(!m_connect);
        GetDlgItem(IDC_EDIT_STARTID)->EnableWindow(!m_connect);
        GetDlgItem(IDC_EDIT_ENDID)->EnableWindow(!m_connect);
        GetDlgItem(IDC_COMBO_BAUD)->EnableWindow(!m_connect);
        GetDlgItem(IDC_COMBO_FILTER)->EnableWindow(!m_connect);
        GetDlgItem(IDC_COMBO_MODE)->EnableWindow(!m_connect);
        OnSelchangeComboBaud();
        OnSelchangeComboFilter();
        GetDlgItem(IDC_BTN_STARTCAN)->SetWindowText("启动CAN");
        VCI_ResetCAN(m_devtype,m_devind,m_cannum);
        VCI_CloseDevice(m_devtype,m_devind);// 此函数用以关闭设备。
        return;
    }

    //如果未连接
    VCI_INIT_CONFIG init_config;//定义初始化CAN的数据类型的结构体
    int index,mode,cannum,baud;   
    UpdateData(true);//控件的值->变量

    index=m_ComboIndex.GetCurSel();//设备索引号
    mode=m_ComboMode.GetCurSel();//工作模式
    cannum=m_ComboCANInd.GetCurSel();//第几路CAN
    sscanf(m_strBTR, _T("%x"), &baud);
    m_devind=index;//设备类型
    m_cannum=cannum;//第几路CAN

    UpdateData(false);//变量值->控件显示
    init_config.Mode=mode;//模式        

        //滤波设置
    DWORD filterMode=m_ComboFilterMode.GetCurSel();//"滤波模式"
    if (filterMode!=2)
    {
        VCI_FILTER_RECORD filterRecord;   
        filterRecord.ExtFrame=filterMode;
        UpdateData(TRUE);//控件的值->变量
        DWORD IDtemp;
        IDtemp=atoi(m_strStartID);//"滤波范围起始帧ID"字符转换为整形
        //_stscanf_s(m_strStartID, _T("%d"), &IDtemp);
        filterRecord.Start = IDtemp;//Start:滤波范围的起始帧ID
        IDtemp=atoi(m_strEndID);//"滤波范围结束帧ID"字符转换为整形
        //_stscanf_s(m_strEndID, _T("%d"), &IDtemp);
        filterRecord.End= IDtemp;//End:滤波范围的结束帧ID        
        VCI_SetReference(m_devtype, m_devind, cannum, 1, &filterRecord);// 设置报文滤波。为1表示操作成功,0表示操作失败
        //使滤波表格生效
        if (VCI_SetReference(m_devtype, m_devind, cannum, 2, NULL)!=STATUS_OK)//参数类型为2????????????????????
        {
            MessageBox(_T("设置滤波失败!"), _T("警告"), MB_OK | MB_ICONQUESTION);
            VCI_CloseDevice(m_devtype,index);
            return;
        }
    }
   
    m_connect=1;
    GetDlgItem(IDC_EDIT_BTR)->EnableWindow(!m_connect);//不激活"自定义波特率寄存器"编辑框
    GetDlgItem(IDC_EDIT_STARTID)->EnableWindow(!m_connect);//不激活"滤波范围起始帧ID"编辑框
    GetDlgItem(IDC_EDIT_ENDID)->EnableWindow(!m_connect);//不激活"滤波范围结束帧ID"编辑框
    GetDlgItem(IDC_COMBO_BAUD)->EnableWindow(!m_connect);//不激活"波特率"组合框
    GetDlgItem(IDC_COMBO_FILTER)->EnableWindow(!m_connect);//不激活"滤波模式"组合框
    GetDlgItem(IDC_COMBO_MODE)->EnableWindow(!m_connect);//不激活"工作模式"组合框
    GetDlgItem(IDC_BTN_STARTCAN)->SetWindowText("关闭CAN");//改变控件的文本内容
    m_startcanlight.SetIcon(m_hIConGreen1);
    VCI_StartCAN(m_devtype,m_devind,m_cannum);
    AfxBeginThread(ReceiveThread,this);//启动线程,ReceiveThread为线程函数
    //Sleep(8000);  
      
}

UINT CCOMMUNICATIONSet::ReceiveThread(void *param)//接收CAN报文 线程函数的定义
{
    CCOMMUNICATIONSet *dlg=(CCOMMUNICATIONSet*)param;
    CListBox *box=(CListBox *)dlg->GetDlgItem(IDC_LIST_INFO);
    VCI_CAN_OBJ frameinfo[50];//定义CAN信息帧数据类型的结构体
    VCI_ERR_INFO errinfo;//定义错误信息数据类型的结构体
    int len=1;
    int i=0;
    CString str,tmpstr;   
    while(1)
    {
        Sleep(1);
        if(dlg->m_connect==0)//未连接
            break;
        len=VCI_Receive(dlg->m_devtype,dlg->m_devind,dlg->m_cannum,frameinfo,50,200);//从指定的设备读取数据        
        if(len<=0)//没有读到数据
        {            
            VCI_ReadErrInfo(dlg->m_devtype,dlg->m_devind,dlg->m_cannum,&errinfo);//获取最后一次错误信息
        }
        else//读到数据
        {
            for(i=0;i<len;i++)
            {
                str="接收到数据帧:  ";

                if(frameinfo[i].TimeFlag==0)//无时间标识
                    tmpstr="时间标识:无  ";
                else
                    tmpstr.Format("时间标识:%08x ",frameinfo[i].TimeStamp);
                str+=tmpstr;//接收到信息帧时的时间标识

                tmpstr.Format("帧ID:%08x ",frameinfo[i].ID);
                str+=tmpstr;//报文ID

                str+="帧格式:";
                if(frameinfo[i].RemoteFlag==0)
                    tmpstr="数据帧 ";
                else
                    tmpstr="远程帧 ";
                str+=tmpstr;

                str+="帧类型:";
                if(frameinfo[i].ExternFlag==0)
                    tmpstr="标准帧 ";
                else
                    tmpstr="扩展帧 ";
                str+=tmpstr;

                box->InsertString(box->GetCount(),str);//插入字符串

                if(frameinfo[i].RemoteFlag==0)//不是远程帧?
                {
                    str="数据:";
                    if(frameinfo[i].DataLen>8)
                        frameinfo[i].DataLen=8;
                    for(int j=0;j<frameinfo[i].DataLen;j++)
                    {
                        tmpstr.Format("%02x ",frameinfo[i].Data[j]);
                        str+=tmpstr;
                    }
                    //EnterCriticalSection(&(dlg->m_Section));//获得指定的临界区对象的所有权
                    //LeaveCriticalSection(&(dlg->m_Section));//释放指定的临界区对象的所有权
                    box->InsertString(box->GetCount(),str);                    
                }
                CNaS_BMSDlg *m_Host = (CNaS_BMSDlg*)AfxGetMainWnd();//获取主界面的指针   
                if(frameinfo[7].Data[2]!=1)
                m_Host->xxx->m_page1.SendMessage(UM_ALARM,0,0);  
            
            }
            box->SetCurSel(box->GetCount()-1);//box->GetCount():返回列表框中的字符串数目        
        }
    }   
    return 0;   
}

[ 本帖最后由 喜鹊王子 于 2013-3-12 12:34 编辑 ]
搜索更多相关主题的帖子: 数据 睡眠状态 control 接口 
2013-03-12 11:59
yuccn
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:何方
等 级:版主
威 望:167
帖 子:6815
专家分:42393
注 册:2010-12-16
收藏
得分:0 
Sleep(8000)就是让ui线程休眠了8秒了,还问为什么?
你知道sleep()是干什么的吧,如果不知道去查下msdn就行了

我行我乐
公众号:逻辑客栈
我的博客:
https://blog.yuccn. net
2013-03-12 12:12
喜鹊王子
Rank: 1
等 级:新手上路
帖 子:105
专家分:0
注 册:2012-12-25
收藏
得分:0 
回复 2楼 yuccn
其实我是不明白注释掉Sleep(8000); 为什么还会执行ReceiveThread这个线程,因为书上都是在main()函数中加上sleep()才会执行自己定义的线程的.

路漫漫其修远兮,吾将上下而求索。
2013-03-12 12:17
yuccn
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:何方
等 级:版主
威 望:167
帖 子:6815
专家分:42393
注 册:2010-12-16
收藏
得分:20 
因为书上的是cui程序
你的是gui程序,

书上的那个cui程序 启动线程后,主线程就自己退出了,整个进程也退出了,启动的那个线程还没有来得及启动

而你的gui进程有消息循环,你不关闭它 程序一直都不退出的,所以下面的线程就有时间启动了

我行我乐
公众号:逻辑客栈
我的博客:
https://blog.yuccn. net
2013-03-12 12:27
喜鹊王子
Rank: 1
等 级:新手上路
帖 子:105
专家分:0
注 册:2012-12-25
收藏
得分:0 
回复 4楼 yuccn
嗯,好的,这个问题我弄明白了;还有一个问题啊,我在之前的数据接收线程中添加了紫色的代码,其目的是发送自定义消息给另一个对话框,执行到
m_Host->xxx->m_page1.SendMessage(UM_ALARM,0,0);就会出现非法操作,不知道为什么?如果将紫色部分代码放到OnBtnStartcan()的AfxBeginThread(ReceiveThread,this);后面,就不会出现非法操作。  这两种情况下,编译都没错误的。

m_Host是主对话框的指针;xxx为主对话框的一子对话框的指针,m_page1是该子对话框中添加tab控件中的一个对话框对象。

非常感谢!

路漫漫其修远兮,吾将上下而求索。
2013-03-12 12:41
快速回复:CAN接口卡读取数据线程问题?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029033 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved