打印
[嵌入式Linux]

AM335X工控板应用,一个具有协议转换功能的应用(转贴)

[复制链接]
1015|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 双盈科技 于 2015-11-9 12:18 编辑

我对整个测试过程做了一个视频,可惜不会直接发视频。把优酷的链接发上来,有兴趣的看看吧。
v.youku.com/v_show/id_XMTM3ODg0ODU1Mg==.html

一个具有协议转换功能的应用(一)
CANOP类的实现
这个是我的目标应用,基于EVB-335x-2开发板,完成CAN和以太网的通讯协议转换功能。系统应用的主要功能描述:
l  采用多线程技术处理CAN总线数据收发;
l  采用多线程技术处理以太网数据收发;
l  转换主机为TCPServer,可以客户机的连接;
l  通过以太网进行CAN总线控制器的打开,关闭,波特率修改和状态查询;
l  通过以太网完成CAN总线数据的收发。
第一部分:CAN总线驱动类的开发
根据资料光盘中的测试程序例子,经过修改完成了CANOP类,完成CAN总线接口的打开,关闭,波特率修改,状态查询,数据发送,数据接收等功能。
源代码分析如下:
1)       采用独立的CAN总线数据接收线程
接收线程中采用循环队列完成接收数据帧的缓存。
int canop::canListenThread(void *lparam)
{
         canop *pSocket;
         pSocket = (canop*)lparam;
         int nbytes;
    struct can_frame frame;
         while( 1 )
         {
        //收到退出事件,结束线程
                   if( pSocket->m_ExitThreadFlag )
                   {
                            break;
                   }
        memset(&frame, 0, sizeof(struct can_frame));
        nbytes = read(pSocket->sockwfd, &frame, sizeof(struct can_frame));
        if (nbytes > 0)
        {
                 memcpy(pSocket->wframe + pSocket->can_recv_head++,&frame,sizeof(struct can_frame));
                            if(pSocket->can_recv_head >= CAN_MAX_RECV_ITEM)
                                     pSocket->can_recv_head = 0;
//              printf("can recv from id %x: ", frame.can_id);
//            for (int i=0; i<frame.can_dlc; i++){
//                  printf("%3x", frame.data);
//                baRecv = frame.data;
//            }
//            printf("n");
//            emit signalRecvMsg(baRecv, frame.can_id);
        }
         }
         printf( "SocketLisenThread finishedn");
         pthread_exit( NULL );
         return 0;
}
2) CAN总线的初始化和接收线程的创建
CAN总线控制器的初始化,系统提供两个接口CAN0和CAN1,默认波特率为11个,分别为5Kbps,10Kbps,20Kbps,50Kbps,62.5Kbps,100Kbps,125Kbps,250Kbps,500Kbps,800Kbps,1Mbps。目前设计不支持自定义波特率。
int canop::canopen(CAN_NAME ifname,CAN_BAUD baud)
{
         string ibaud = "50000 ";
         pthread_attr_t                 attr;
         int    res;
    if ((sockwfd = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
    {
             printf("Error while opening socket");
        return 0;
    }
    //start can device
    string strcmd("ifconfig can0 down;ip link set can0 type can bitrate ");
    switch(baud)
    {
             case _CAN_BAUD_5K:
                       ibaud = "5000 ";
                       break;
             case _CAN_BAUD_10K:
                       ibaud = "10000 ";
                       break;
             case _CAN_BAUD_20K:
                       ibaud = "20000 ";
                       break;
             case _CAN_BAUD_50K:
                       ibaud = "50000 ";
                       break;
             case _CAN_BAUD_62_5K:
                       ibaud = "62500 ";



相关帖子

沙发
双盈科技|  楼主 | 2015-11-9 12:15 | 只看该作者
一个具有协议转换功能的应用(二)
TCP服务器类的实现
第二部分:以太网服务器设计
TCPServer类直接使用了例程中的代码,这里就不再列出来了。这里重点说明一下TCPCustom类的修改。
         修改TCPCustom类增加CAN总线操作方面的代码,在进行代码修改前,先将通讯数据格式进行一下定义。
前导同步码
有效数据长度
命令码
数据
0xEB 0x90 0xEB 0x90 0xEB 0x90
0x00 0x00
0x01 命令
0x02 数据
若干
源码分析如下:
1)  客户端通讯接收数据线程
采用原TCPCustom的内容基本不用做特别修改,尽在线程退出的地方,判断如果已经打开CAN总线,线程退出后应该关闭CAN总线接口。
/*--------------------------------------------------------------------
【函数介绍】: 此线程用于监听与客户端连接的socket通讯的事件,例如当接收到数据、
                               连接断开和通讯过程发生错误等事件
【入口参数】: lparam:无类型指针,可以通过此参数,向线程中传入需要用到的资源。
                               在这里我们将CTCPCustom类实例指针传进来
【出口参数】:  (无)
【返回  值】:   无
---------------------------------------------------------------------*/
void* CTCPCustom::SocketDataThread(void* lparam)
{
         CTCPCustom *pSocket;
         char          TxBuf[2000];
         int                       TxLen;
         //得到CTCPCustom类实例指针
         pSocket = (CTCPCustom*)lparam;
         //定义读事件集合
         fd_set fdRead;
         int ret;
         struct timeval  aTime;
         aTime.tv_sec = 1;
         aTime.tv_usec = 0;
         while( 1 )
         {
        //收到退出事件,结束线程
                   if( pSocket->m_ExitThreadFlag )
                   {
                            break;
                   }
                   //置空读事件集合
                   FD_ZERO(&fdRead);
                   //给pSocket设置读事件
                   FD_SET(pSocket->m_socketfd, &fdRead );
                   //调用select函数,判断是否有读事件发生
                   aTime.tv_sec = 1;
                   aTime.tv_usec = 0;
                   ret = select(0, &fdRead, NULL, NULL, &aTime);
                   if( ret<0 )
                   {
                            //关闭socket
                            close( pSocket->m_socketfd );
                            break;
                   }
                   else
                   {
                            //判断是否读事件
                            if(FD_ISSET(pSocket->m_socketfd,&fdRead))
                            {
                                     pSocket->RecvLen = recv(pSocket->m_socketfd, pSocket->RecvBuf, 1024,0);
                                     if (pSocket->RecvLen < 0 )
                                     {
                                               //与客户端端连接的Socket错误
                                               printf( "Socket errorn");
                                               //关闭socket
                                               close(pSocket->m_socketfd);
                                               break;
                                     }
                                     //表示连接已经从容关闭
                                     else if( pSocket->RecvLen == 0)
                                     {
                                               printf( "Close socket %dn", pSocket->m_socketfd );
                                               //关闭socket
                                               close(pSocket->m_socketfd);
                                               break;
                                     }
                                     else
                                     {
                                               //对接收的数据进行处理,这里为简单处理数据回发
                                               pSocket->RecvBuf[pSocket->RecvLen]=0;
                                               printf( "RCV:%sn", pSocket->RecvBuf);
                                               TxLen = pSocket->DataPro( TxBuf );
                                               if( TxLen>0 )
                                               {
                                                        pSocket->SendData( TxBuf, TxLen );
                                               }
                                               //处理完毕
                                     }
                            }
                   }
         }

使用特权

评论回复
板凳
双盈科技|  楼主 | 2015-11-9 12:17 | 只看该作者
有代码呢!需要的赶快下载!

EVB-335X-ii_X.png (236 KB )

EVB-335X-ii_X.png

EVB-335X-2.jpg (437.82 KB )

EVB-335X-2.jpg

test2.rar

269.68 KB

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:am335x应用专家 qq:259134942 artcor.taobao.com

10

主题

34

帖子

0

粉丝