⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 j1939_dl.c

📁 基于ucosSAEj1939的汽车组合仪表,硬件是MC9S12H128
💻 C
字号:

/**************************************************************************************
*                                                                                       
*                      北京航空航大学 706教研室                         
*                   All rights reserved.       2005                                                 
*                                                                                       
*======================================================================================
*                                                                                       
*       文件名:         J1939_DL.c                                                        
*       大纲:           J1939协议栈                  
*       文件标识:                                                                       
*       摘 要:                                                                                                                                                              
*                                                                                      
*======================================================================================
*                                                                                      
*       描述:           链路层文档                                                                                      
*                                                                                      
*       控制器:         Freescale MC9s12H256                                         
*                                                                                      
*       编译器:         Metrowerks CodeWarrior IDE v5.2.1149                            
*                                                                                      
*======================================================================================
*                                                                                      
*       当前版本:   1.0.0                                                                   
*       编程人员:   孙进                                                                 
*       完成日期:   2006年2月                                                                                                                                                                                                   
*                                                                                       
*======================================================================================                                                                          
*
*       更新历史记录:                                                                   
*                                                                                      
***************************************************************************************/

#include "J1939_includes.h"
#include "\driver\printp.h"	 //testbug

CAN_PACKET_T InBoundBuffer[IN_BUFFER_SIZE];

CAN_PACKET_T OutBoundBuffer[OUT_BUFFER_SIZE];

RING_T RingInBuffer;
RING_T RingOutBuffer;

U08 DL_state;

//==========================================================================================
//Datalink Modular Interfaces
//==========================================================================================
/****************************************************************************************
@函数名称           : void DL_init(void)           
@参数               : None 
@返回值             : None
@描述               : 初始化函数,设置 the datalink layer's packet buffers
                      和设置the datalink module into a "not primed" state
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/
void DL_init(void)
{
    U08 i,j;

    for(i=0;i<IN_BUFFER_SIZE;i++)
    {
        InBoundBuffer[i].byte_count = 0;
        InBoundBuffer[i].identifier = 0;
        for(j=0;j<CAN_MAX_BYTE_COUNT;j++)
        {
            InBoundBuffer[i].data[j] = 0; 
        }
    }

    for(i=0;i<OUT_BUFFER_SIZE;i++)
    {
        OutBoundBuffer[i].byte_count = 0;
        OutBoundBuffer[i].identifier = 0;
        for(j=0;j<CAN_MAX_BYTE_COUNT;j++)
        {
            OutBoundBuffer[i].data[j] = 0;
        }
    }

    RingInBuffer.buffer = &InBoundBuffer[0];
    RingInBuffer.head = 0;
    RingInBuffer.tail = 0;
    RingInBuffer.buffer_size = IN_BUFFER_SIZE - 1; 
      
    RingOutBuffer.buffer = &OutBoundBuffer[0];
    RingOutBuffer.head = 0;
    RingOutBuffer.tail = 0;
    RingOutBuffer.buffer_size = OUT_BUFFER_SIZE - 1;
   
    //设置链路层状态机
    DL_state = NOTPRIMED; 
    
    return;  
}

/****************************************************************************************
@函数名称           : void Rev_CANpkt( const CAN_PACKET_T* pkt_ptr )             
@参数               : const CAN_PACKET_T* pkt_ptr
@返回值             : None
@描述               : 入栈接口函数在数据链路层和物理层之间。物理层调用在接收中断函数中调用
                      这个函数,当调用时函数把 CAN_PACKET_T 镜像拷贝到数据链路层入栈环形缓
                      冲区中
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/

#pragma CODE_SEG NON_BANKED
void Rev_CANpkt(const CAN_PACKET_T *pkt_ptr)
{
    rng_enqueue(*pkt_ptr,&RingInBuffer);
    return; 
}

/****************************************************************************************
@函数名称           : void J1939_DL_periodic(void)           
@参数               : 
@返回值             : 
@描述               : J1939周起函数,调用TICK。函数驱动数据链路层内部处理
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/

#pragma CODE_SEG NON_BANKED
void DL_periodic(void)
{ 
    U08 m_DA,m_SA,m_PF,i;
    U32 m_ID;
    PGN_T m_PGN;
    CAN_PACKET_T *rpkt_ptr;
    CAN_PACKET_T *tpkt_ptr;
    J1939_PDU_T pdu;

    m_DA = 0;//初始化
    m_SA = 0;
    m_PF = 0;
    m_ID = 0;
    m_PGN = 0;
    
    i = 0;
    /*ringoutbuffer出队,报文发送*/
    tpkt_ptr = rng_dequeue(&RingOutBuffer);
    if(tpkt_ptr != NULL) 
    {
        Trans_CANpkt(tpkt_ptr);
    }
    
        
    /*调用传输层函数,报文接收*/    
    while(TRUE)
    {
        rpkt_ptr = rng_dequeue(&RingInBuffer);
        if(rpkt_ptr == NULL)                     //接收缓冲区空
        {
            break;
        }
        else
        {
            m_ID = rpkt_ptr->identifier;      
            m_SA = (U08)m_ID;
            m_DA = (U08)(m_ID>>8);
            m_PGN = (PGN_T)(m_ID>>8);
            m_PF = (U08)(m_ID>>16);

            if (m_PF < 240)                     //PDU1格式
            {
                if(m_DA==GLOBADDR)
                {
                    //continue;
                    pdu.PGN = m_PGN & 0xFF00;
                    pdu.byte_count = rpkt_ptr->byte_count;
                    pdu.dest_addr = GLOBADDR;
                    pdu.source_addr = m_SA; 
                    for(i=0;i<pdu.byte_count;i++)
                    {
                        pdu.data[i] = rpkt_ptr->data[i];
                    }
                }
                else if(m_DA==NODEADDR)
                {
                    //continue;
                    pdu.PGN = m_PGN & 0xFF00;
                    pdu.byte_count = rpkt_ptr->byte_count;
                    pdu.dest_addr = m_DA;
                    pdu.source_addr = m_SA; 
                    for(i=0;i<pdu.byte_count;i++)
                    {
                        pdu.data[i] = rpkt_ptr->data[i];
                    }
                }
                else
                {
                    continue;
                }
            }
            else                                    //PDU2格式
            {
                pdu.PGN = m_PGN;
                pdu.byte_count = rpkt_ptr->byte_count;
                pdu.dest_addr = GLOBADDR;
                pdu.source_addr = m_SA;
                for(i=0;i<pdu.byte_count;i++)
                {
                    pdu.data[i] = rpkt_ptr->data[i];
                }          
            }
     	}
     	TL_process(&pdu); 
    }
    return;
}

/****************************************************************************************
@函数名称           : const CAN_PACKET_T* Req_CANpkt(void)           
@参数               : None
@返回值             : const CAN_PACKET_T
@描述               : 硬件抽象层在发送中断函数中调用这个函数获取新的数据帧
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/
const CAN_PACKET_T* Req_CANpkt(void)
{
    CAN_PACKET_T *pkt_ptr;
    pkt_ptr = rng_dequeue(&RingOutBuffer);
    if (pkt_ptr == NULL)
    {
        DL_state = NOTPRIMED;
        return NULL;
    }
    else
    {
        DL_state = PRIMED;
        return pkt_ptr;
    }
}

/****************************************************************************************
@函数名称           : void Build_CANpkt(J1939_TX_MESSAGE_T *msg_ptr, U08 tflag)          
@参数               : None
@返回值             : J1939_TX_MESSAGE_T *msg_ptr, U08 tflag
@描述               : 传输层调用此函数将数据帧放入链路层发送缓冲区中
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/
void Build_CANpkt(J1939_TX_MESSAGE_T *msg_ptr,U08 tflag)
{
    CAN_PACKET_T pkt_ptr;
    U08 i;
    
    if(tflag == 0)
    {
        pkt_ptr.byte_count = (U08)msg_ptr->byte_count;
        pkt_ptr.identifier = msg_ptr->priority;
        pkt_ptr.identifier = (pkt_ptr.identifier<<18) + msg_ptr->PGN;
        if (msg_ptr->PGN < 0xF000)
        {
            pkt_ptr.identifier = pkt_ptr.identifier + msg_ptr->dest_addr;
        }
        pkt_ptr.identifier = (pkt_ptr.identifier<<8) + NODEADDR;
        for(i=0;i<pkt_ptr.byte_count;i++)
        {
            pkt_ptr.data[i] = msg_ptr->data[i];
        }
        rng_enqueue(pkt_ptr,&RingOutBuffer);
        
        //关中断
        DL_state = PRIMED;
        //开中断
    }
    else
    {}
    return;   
}

/****************************************************************************************
@函数名称           : void rng_enqueue(CAN_PACKET_T msg, RING_T *ring)           
@参数               : CAN_PACKET_T msg
                      RING_T *ring
@返回值             : 
@描述               : 函数把CAN_PACKET_T msg加到RING_T *ring指向的结构的尾部
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/

#pragma CODE_SEG NON_BANKED
void rng_enqueue(CAN_PACKET_T msg, RING_T *ring)
{
    if(((ring->tail+1)==ring->head)||((ring->tail==ring->buffer_size)&&(ring->head==0)))//环形队列满
    {
        return;
    }
    else
    {
        ring->buffer[ring->tail] = msg;                         //enqueue CAN message
        ring->tail++;
        if(ring->tail > ring->buffer_size)                      //wrap,CAN_BUF_MAX ->0
            ring->tail = 0;                             
        return;
    }
}

/****************************************************************************************
@函数名称           : CAN_PACKET_T *rng_dequeue(RING_T *ring)            
@参数               : RING_T *ring
@返回值             : 
@描述               : 从ring中的头部取出一个CAN_PACKET_T,如果是空就返回NULL
@作者               : 孙进
@最后编辑时间       : 2005-11-23
@版本               : V1.0.0
*****************************************************************************************/

#pragma CODE_SEG NON_BANKED
CAN_PACKET_T *rng_dequeue(RING_T *ring)
{
    CAN_PACKET_T *temp;

    if(ring->head == ring->tail)
    {
        return NULL;                                        //ring buffer is empty
    }
    else
    {
        temp = &ring->buffer[ring->head];
        ring->head++;
        if(ring->head > ring->buffer_size)
            ring->head = 0;                                 //wrap,CAN_BUF_MAX ->0
        return temp;
    }   
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -