rocking2807
驱动牛犊
驱动牛犊
  • 注册日期2006-11-20
  • 最后登录2010-09-09
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望88点
  • 贡献值0点
  • 好评度83点
  • 原创分0分
  • 专家分0分
阅读:1848回复:4

流接口驱动中断的一个问题

楼主#
更多 发布于:2007-03-20 16:08
  我做过一个CAN总线的流接口驱动
全面来说是这样的,当收数收完以后,会有一个中断,通知CPU读取,

原来是用查询方式收数
现在改为中断
问题在这里,
中断处理线程,我按通常的做法放在CAN_INIT里面,
但是中断处里也就是收数啊,那CAN_READ怎么办,两者怎么建立联系
rocking2807
驱动牛犊
驱动牛犊
  • 注册日期2006-11-20
  • 最后登录2010-09-09
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望88点
  • 贡献值0点
  • 好评度83点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-03-21 08:10
大哥们讲一下啊
rocking2807
驱动牛犊
驱动牛犊
  • 注册日期2006-11-20
  • 最后登录2010-09-09
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望88点
  • 贡献值0点
  • 好评度83点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-03-21 08:35
附上程序,大哥们指点下
DWORD CAN_Init(DWORD Index)
{
    GPIOInit();
/*      gCANIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    InterruptInitialize(SYSINTR_CAN, gCANIntrEvent, 0, 0);
    WaitForSingleObject(gCANIntrEvent, INFINITE);
*/    
gCANIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) CAN_IntrThread, 0, 0, &IDThread);

    return 1;
}DWORD CAN_Read(DWORD hOpenContext,LPVOID pBuffer ,DWORD count)
{
    MCP2510_Write(CANINTE, 0xf3);
}

LPVOID pBuffer ;
DWORD count;
U8 in_buff[6];
U8 out_buff[4];

U8 CanID[4];
static HANDLE gCANIntrEvent;
static HANDLE gCANIntrThread;
DWORD   IDThread;
 void      CAN_IntrHander(void)
 {int i;
    U32 id;
    unsigned char dlc;
    int rxRTR, isExt;
    int temp;
    U8 data_read[32];
    if(count==9)
    {
        memcpy(CanID,pBuffer,4);
        count=8;
Read:
        i = Can_Poll();
        
        if((i==0)|(i==1))
        {
            memset(data_read,0,sizeof(data_read) ) ;
            temp = Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
  //                       memcpy(data_read,read_buf,count);
            out_buff[0] = ((id>>24)&0xff);  
            out_buff[1] = ((id>>16)&0xff);                    
            out_buff[2] = ((id>>8)&0xff);
            out_buff[3] = ((id)&0xff);
            if((out_buff[2]!=CanID[2]) || (out_buff[3]!=CanID[3]))
            {    
                goto Read;
            }else
            {            
                memcpy(pBuffer,data_read,count);
            }
        }
        else
        {            
//            return 0;
            }
    }else if(count!=9)
    {
        i = Can_Poll();
                
        if((i==0)|(i==1))
        {
            memset(data_read,0,sizeof(data_read) ) ;
            temp = Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
//            memcpy(pBuffer,read_data,count);
            out_buff[0] = ((id>>24)&0xff);  
            out_buff[1] = ((id>>16)&0xff);
            out_buff[2] = ((id>>8)&0xff);
            out_buff[3] = ((id)&0xff);  
        }
        else
        {
//            return 0;
             }
    }
//    return count ;
  }            
//中断线程式*************************************************************************
DWORD  CAN_IntrThread(void)
{
    gCANIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//    InterruptDisable(SYSINTR_CAN);
    InterruptInitialize(SYSINTR_CAN, gCANIntrEvent, 0, 0);
    WaitForSingleObject(gCANIntrEvent, INFINITE);
        CAN_IntrHander();
        InterruptDone(SYSINTR_CAN);
  }
这里我觉得关键就在于LPVOID pBuffer ,DWORD count这两个参数的问题
我觉得我写得有问题,大哥们说一下
rocking2807
驱动牛犊
驱动牛犊
  • 注册日期2006-11-20
  • 最后登录2010-09-09
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望88点
  • 贡献值0点
  • 好评度83点
  • 原创分0分
  • 专家分0分
地板#
发布于:2007-03-27 10:45
再发一个改过的,大家看看哪里有错误,还是丢数.

U8 in_buff[6];
U8 out_buff[4];

U8 CanID[4];
struct    list
{ int  id;
  int  data_buff[8];
  struct list *next;
  };
  typedef  struct list node;
  typedef  node *link;
  link NEW;
  link pointer;
  link head;
  link temp=head.next;

static HANDLE gCANIntrEvent;
static HANDLE gCANIntrThread;
LPVOID pBuffer;
DWORD count;
DWORD   IDThread;

DWORD CAN_Init(DWORD Index)
{
    GPIOInit();
    link Create_list ( head)
  {
  
  
  
  head=(link) malloc(sizeof(node));
  if(head==NULL)
  RETAILMSG( DEBUGMODE,( TEXT( "MEMORY ALLOCATE FAILURE \n\r" ) ) );
  else
  {
  //gCANIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) CAN_IntrThread, 0, 0, &IDThread);
  head.next=NULL;
  pointer=head;
  while(1)
  {
  NEW=(link) malloc(sizeof(node));
  gCANIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) CAN_IntrThread, 0, 0, &IDThread);
  
  NEW.next=NULL;
  pointer.next=NEW;
  pointer=NEW;
  }
  }
  return head;
  }
    
//gCANIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) CAN_IntrThread, 0, 0, &IDThread);

    return 1;
}

BOOL CAN_Deinit(DWORD dwData)
{
Free_list(link head);
InterruptDisable(SYSINTR_CAN);
CloseHandle(gCANIntrEvent);
CloseHandle(gCANIntrThread);
    return TRUE;

}

DWORD CAN_Read(DWORD hOpenContext,LPVOID pBuffer ,DWORD count)
{
    int i;
    U32 id;
    unsigned char dlc;
    int rxRTR, isExt;
    int temp;
    U8 data_read[32];
    if(count==9)
    {
        memcpy(CanID,pBuffer,4);
        count=8;
Read:
        i = Can_Poll();
        
        if((i==0)|(i==1))
        {
            memset(data_read,0,sizeof(data_read) ) ;
            temp = Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
//            RETAILMSG (1, (TEXT("::: PBT_InitializeAddresses - Fail!!\r\n") ));
//                        UART_printf("0x%x\r\n",data_read);
  //                       sprint(
  RETAILMSG(TRUE, (TEXT("can_data %u\r\n"), data_read));

            out_buff[0] = ((id>>24)&0xff);  
            out_buff[1] = ((id>>16)&0xff);                    
            out_buff[2] = ((id>>8)&0xff);
            out_buff[3] = ((id)&0xff);
            if((out_buff[2]!=CanID[2]) || (out_buff[3]!=CanID[3]))
            {    
                goto Read;
            }else
            {            
                memcpy(pBuffer,data_read,count);
            }
        }
        else
        {
            return 0;
              }
    }else if(count!=9)
    {
        i = Can_Poll();
        
        if((i==0)|(i==1))
        {
            memset(data_read,0,sizeof(data_read) ) ;
            temp = Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
            memcpy(pBuffer,data_read,count);
            out_buff[0] = ((id>>24)&0xff);  
            out_buff[1] = ((id>>16)&0xff);
            out_buff[2] = ((id>>8)&0xff);
            out_buff[3] = ((id)&0xff);  
        }
        else
        {
            return 0;
              }
    }
    return count ;
}
rocking2807
驱动牛犊
驱动牛犊
  • 注册日期2006-11-20
  • 最后登录2010-09-09
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望88点
  • 贡献值0点
  • 好评度83点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2007-03-27 10:46
/***********************************************************
        
                          
                       ***********************************************************/

#include <windows.h>
#include <types.h>
#include <drv_glob.h>
#include <nkintr.h>
#include <oalintr.h>

#include <MCP2510.h>

//unsigned short ReadBuf[256] ;
//TCHAR  read_buf[256] ;  
//U8 read_buf[20];
U8 in_buff[6];
U8 out_buff[4];

U8 CanID[4];
/****************************************************************************
【功能说明】延迟程序
****************************************************************************/
static void Delay(USHORT count)
{
    volatile int i, j = 0;
    volatile static int loop = 400000000/100000;
    
    for(;count > 0;count--)
        for(i=0;i < loop; i++) { j++; }
}

/****************************************************************************
【功能说明】 设置GPIO为SPI模式
****************************************************************************/
void GPIOInit(void)
{
    rGPEUP |= (7 << 11);   //GPE13、GPE12、GPE11禁止上拉
    rGPECON &= (~ (0x3F << 22));
    rGPECON |= (0x2A << 22); //set GPE11,12,13 as SPI0
    rGPGCON &= (~ (0x3 << 4));
    rGPGCON |= (1 << 4);  //GPG2 as output
    rGPGUP |= (1 << 2);  //GPG2禁止上拉
}

/****************************************************************************
【功能说明】初始化SPI,条件:begin为真
****************************************************************************/
void SPIInit(int begin)
{
    if(begin)
    {
        MCP2510_CS_H;
        rSPPRE = 0xff;//spi速度???????
        rSPCON |= 0x18;//master and enable sck
    }
    else rSPCON = 0;
}

/****************************************************************************
【功能说明】向SPI接口写入数据,并返回结果,如果只单独读出SPI内容,写入0xFF。
****************************************************************************/
U8 Spi_Write( U8 Data )
{
    rSPTDAT = Data;
    while(! (rSPSTA & 1));  //判断SPI状态,为1指明总线闲    
    return (U8) rSPRDAT;
    MCP2510_Write(CANINTF,NO_IE);//清缓冲区
}

/****************************************************************************
【功能说明】向MCP2510指定地址写入一个字节
****************************************************************************/
void MCP2510_Write( U8 address, U8 value)
{
    MCP2510_CS_L;
    Spi_Write(MCP2510INSTR_WRITE);
    Spi_Write(address);
    Spi_Write(value);
    MCP2510_CS_H;
}

/****************************************************************************
【功能说明】从MCP2510指定地址中读出一个字节
****************************************************************************/
U8 MCP2510_Read( U8 address )
{
    U8 result;
    MCP2510_CS_L;
    Spi_Write(MCP2510INSTR_READ);
    Spi_Write(address);
    result = Spi_Write(0xFF);
    MCP2510_CS_H;
    return result;
}

/****************************************************************************
【功能说明】修改指定地址寄存器的某些位
****************************************************************************/
void MCP2510_WriteBits( U8 address, U8 data, U8 mask )
{
    MCP2510_CS_L;
    Spi_Write(MCP2510INSTR_BITMDFY);
    Spi_Write(address);
    Spi_Write(mask);
    Spi_Write(data);
    MCP2510_CS_H;
}

/****************************************************************************
【功能说明】序列写入MCP2510数据    
****************************************************************************/
void MCP2510_Swrite( U8 address, U8* pdata, U8 nlength)
{
    MCP2510_CS_L;
    Spi_Write(MCP2510INSTR_WRITE);
    Spi_Write((unsigned char)address);

    while(nlength--)
    {
        Spi_Write(* pdata++);
    }
    MCP2510_CS_H ;
}

/****************************************************************************
【功能说明】序列读取MCP2510数据    
****************************************************************************/
void MCP2510_SRead( U8 address, U8* pdata, U8 nlength )
{
    MCP2510_CS_L;
    Spi_Write(MCP2510INSTR_READ);
    Spi_Write(address);
    while(nlength--)
    {
        * pdata++ = Spi_Write(0xFF);
    }
    MCP2510_CS_H;
}

/****************************************************************************
【功能说明】软件复位MCP2510
****************************************************************************/
void MCP2510_Reset()
{
    MCP2510_CS_L;
    Spi_Write( MCP2510INSTR_RESET );
    MCP2510_CS_H ;
}

/****************************************************************************
【功能说明】状态读指令            
以下图示为状态字位说明
    7        6        5        4        3        2      1    0
//        |    |    |    |    |    |    |    |                                    
//        |    |    |    |    |    |    |    |___CANINTF.RX0IF
//        |    |    |    |    |    |    |_______CANINTF.RX1IF
//        |    |    |    |    |    |___________TXB0CTRL.TXREQ
//        |    |    |    |    |_______________CANINTF.TX0IF
//        |    |    |    |___________________TXB1CTRL.TXREQ
//        |    |    |_______________________CANINTF.TX1IF
//        |    |___________________________TXB2CTRL.TXREQ
//        |_______________________________CANINTF.TX2IF
****************************************************************************/
U8 MCP2510_ReadStatus()
{
    U8 result;
    MCP2510_CS_L;
    Spi_Write(MCP2510INSTR_RDSTAT);
    result = Spi_Write(0xFF) ;
    Spi_Write( 0 ) ;        //数据重复输出
    MCP2510_CS_H ;

    //if( MCP2510_DEBUG )        Uart_Printf( "StatusREG = 0x%x\n", result ) ;
    return result;
}

/****************************************************************************
【功能说明】设置MCP2510的波特率,此处基本配置为底板晶振12MHz
****************************************************************************/
void MCP2510_SetBandRate(CanBandRate bandrate)
{
    U8 value=0;
    U8 ReadBackCNT = 0;
    MCP2510_Write(MCP2510REG_CANCTRL, MODE_CONFIG);
    //if( MCP2510_DEBUG )  RETAILMSG(1,(TEXT( "MCP2510REG_CANCTRL =  0x%x\n"), MCP2510_Read(MCP2510REG_CANCTRL) ));
    while( ReadBackCNT<8 )     //确保进入配置模式
    {
        value = ( MCP2510_Read( MCP2510REG_CANSTAT ) & 0xe0 );
        if(value == MODE_CONFIG ){
            break;
        }
        ReadBackCNT++ ;
    }
    if( ReadBackCNT == 8 )             //Set mcp2510's mode failed,redo it again
    {
        MCP2510_Reset();
        MCP2510_Write(MCP2510REG_CANCTRL, MODE_CONFIG);        //redo to set mcp2510 mode
        Delay( 150 );
        value = ( MCP2510_Read(MCP2510REG_CANCTRL) & 0xe0 );    //read back mode from CANSTAT Register
    }

    switch(bandrate){
    case BandRate_10kbps:
        MCP2510_Write(CNF1, SJW1|BRP50);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG3<<3)|SEG5); // Phase Seg 1 = 3, Prop Seg = 4
        MCP2510_Write(CNF3, SEG3);// Phase Seg 2 = 3    
        break;
    case BandRate_100kbps:
        MCP2510_Write(CNF1, SJW1|BRP5);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG3); // Phase Seg 1 = 4, Prop Seg = 3
        MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4    
        break;
    case BandRate_125kbps:
        MCP2510_Write(CNF1, SJW1|BRP4);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG5<<3)|SEG3); // Phase Seg 1 = 5, Prop Seg = 3
        MCP2510_Write(CNF3, SEG3);// Phase Seg 2 = 3
        break;
    case BandRate_250kbps:
        MCP2510_Write(CNF1, SJW1|BRP2);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG3); // Phase Seg 1 = 4, Prop Seg = 3
        MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4
        break;
    case BandRate_500kbps:
        MCP2510_Write(CNF1, SJW1|BRP1);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG3); // Phase Seg 1 = 4, Prop Seg = 3
        MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4
        break;
    case BandRate_1Mbps:
        MCP2510_Write(CNF1, SJW1|BRP1);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG2<<3)|SEG1); // Phase Seg 1 = 2, Prop Seg = 1
        MCP2510_Write(CNF3, SEG2);// Phase Seg 2 = 2
    case BandRate_833kbps:
        MCP2510_Write(CNF1, SJW1|BRP6);    //Synchronization Jump Width Length =1 TQ
        MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG3); // Phase Seg 1 = 4, Prop Seg = 3
        MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4    
    break;
    }
}

/****************************************************************************
【功能说明】读取MCP2510 CAN总线ID
参数: address为MCP2510寄存器地址
      can_id为返回的ID值
返回值
    TRUE,表示是扩展ID(29位)
    FALSE,表示非扩展ID(11位)
****************************************************************************/
int MCP2510_Read_Can_ID( U8 address, U32* can_id)
{
    U32 tbufdata;
    unsigned char* p=(unsigned char*)&tbufdata;

    MCP2510_SRead(address, p, 4);
    
    *can_id = (tbufdata<<3)|((tbufdata>>13)&0x7);   //先移出SID2-SID0,再把它移到低三位
                                                    //或之后就是SID10~SID0
    *can_id &= 0x7ff;                           //取标准的ID

    if ( (p[MCP2510LREG_SIDL] & TXB_EXIDE_M) ==  TXB_EXIDE_M ) {
        *can_id = (*can_id<<2) | (p[MCP2510LREG_SIDL] & 0x03);
        *can_id <<= 16;
        *can_id |= tbufdata>>16;
        return TRUE;
    }
    return FALSE;
}

/*******************************************
【功能说明】设置MCP2510 CAN总线ID                
参数: address为MCP2510寄存器地址
      can_id为设置的ID值            
      IsExt表示是否为扩展ID    
*******************************************/
void MCP2510_Write_Can_ID(U8 address, U32 can_id, int IsExt)
{
    U32 tbufdata;
    if (IsExt) {
        can_id&=0x1fffffff;    //29位
        tbufdata=(can_id >>21) | ((can_id>>5) & 0xe000) | ((can_id>>8) & 0x300) | ((can_id<<8) & 0xff0000) | (can_id<<24) | 0x800;
    }
    else{
        can_id&=0x7ff;    //11位
        tbufdata= (can_id>>3)|((can_id&0x7)<<13);
    }
    MCP2510_Swrite(address, (unsigned char*)&tbufdata, 4);
}

/***********************************************************
【功能说明】读取MCP2510 接收的数据                            
参数: nbuffer为第几个缓冲区可以为3或者4    
      can_id为返回的ID值                            
      rxRTR表示是否是RXRTR                        
      data表示读取的数据                        
      dlc表示数据长度                            
返回值                                                
      TRUE,表示是扩展总线                        
      FALSE,表示非扩展总线                        
***********************************************************/
int MCP2510_Read_Can(U8 nbuffer, int* rxRTR, U32* can_id, U8* data , U8* dlc)
{

    U8 mcp_addr = (nbuffer<<4) + 0x31, ctrl;
    int IsExt;

    IsExt=MCP2510_Read_Can_ID( mcp_addr, can_id);    
    
    ctrl=MCP2510_Read(mcp_addr-1);
    *dlc=MCP2510_Read( mcp_addr+4);
    if ((ctrl & 0x08)) {
        *rxRTR = TRUE;//扩展
    }
    else{
        *rxRTR = FALSE;
    }
    *dlc &= DLC_MASK;
    MCP2510_SRead(mcp_addr+5, data, *dlc);    
    return IsExt;
}

/***********************************************************************************
【功能说明】查询是否收到数据
返回值:如果没有数据,则返回-1,否则,返回收到数据的缓冲区号
Note: 如果两个缓冲区都收到数据,则返回第一个缓冲区
***********************************************************************************/
int Can_Poll()
{
    if( MCP2510_ReadStatus()&RX0INT )
    {
        return 0;
    }
    
    //if( MCP2510_ReadStatus()&RX1INT )
    //{
    //    return 1;
    //}
    return -1;
}

/****************************************************************************
【功能说明】从MCP2510读数据
****************************************************************************/
int Can_Read(int n, U32* id, U8 *pdata,  U8*dlc, int* rxRTR, int *isExt)
{
    U8 byte;
    byte = MCP2510_Read(CANINTF);
    if(n==0)
    {
        if(byte & RX0INT)
        {
            *isExt=MCP2510_Read_Can(n+3, rxRTR, id, pdata, dlc);
            MCP2510_WriteBits(CANINTF, (U8)(~(RX0INT)), RX0INT); // Clear interrupt
            return TRUE ;
        }
        return FALSE;
    }
    else if(n ==1 )
    {
        if(byte & RX1INT)
        {
            *isExt=MCP2510_Read_Can(n+4, rxRTR, id, pdata, dlc);
            MCP2510_WriteBits(CANINTF, (U8)(~(RX1INT)), RX1INT); // Clear interrupt
            return TRUE ;
        }
        return FALSE;
    }
//    RETAILMSG(1,(TEXT( "Error! Receive channel=0x%x\n"), n )) ;
    return FALSE;
}

/***********************************************************
【功能说明】写入MCP2510 发送的数据                            
参数: nbuffer为第几个缓冲区可以为0、1、2    
      IsExt表示是否是扩展总线,     FALSE表示非扩展总线            
      can_id为写入的ID值                            
      rxRTR表示是否是RXRTR                        
      data表示要写入的数据                        
      dlc表示数据长度                                                    
***********************************************************/
void MCP2510_Write_Can( U8 nbuffer, int IsExt, U32 can_id, int rxRTR, U8* data,U8 dlc )
{
    U8 mcp_addr = (nbuffer<<4) + 0x31;
    MCP2510_Swrite(mcp_addr+5, data, dlc );  // write data bytes
    MCP2510_Write_Can_ID( mcp_addr, can_id,IsExt);  // write CAN id
    if (rxRTR)
        dlc |= RTR_MASK;  // if RTR set bit in byte
    MCP2510_Write((mcp_addr+4), dlc);            // write the RTR and DLC
}


/***********************************************************************************
【功能说明】发送数据
Note: 使用三个缓冲区循环发送,没有做缓冲区有效检测
***********************************************************************************/
void Can_Write(U32 id, U8 *pdata, unsigned char dlc, int IsExt, int rxRTR)
{
    unsigned char err ;
    static int ntxbuffer=0;
    MCP2510_Write_Can(ntxbuffer, IsExt, id, rxRTR, pdata, dlc);
    switch(ntxbuffer){
        case 0:
            MCP2510_WriteBits(TXB0CTRL, (TXB_TXREQ_M|TXB_TXP10_M), 0xff) ;
            do { err = MCP2510_Read(TXB0CTRL) ; }
            while( (err &0x08)==0x08 )  ;
//            if( (err &0x70) != 0 )  RETAILMSG(1,(TEXT( " Can Send Err = 0x%x\n"), err ) );
            ntxbuffer=1;
            break;
        case 1:
            MCP2510_WriteBits(TXB1CTRL, (TXB_TXREQ_M|TXB_TXP10_M), 0xff) ;
            do { err = MCP2510_Read(TXB1CTRL) ; }
            while( (err &0x08)==0x08 )  ;
//            if( (err &0x70) != 0 )  RETAILMSG(1,(TEXT( "  Can Send Err = 0x%x\n"), err ) );
            ntxbuffer=2;
            break;
        case 2:
            MCP2510_WriteBits(TXB2CTRL, (TXB_TXREQ_M|TXB_TXP10_M), 0xff) ;
            do { err = MCP2510_Read(TXB2CTRL) ; }
            while( (err &0x08)==0x08 )  ;
//            if( (err &0x70) != 0 )  RETAILMSG(1,(TEXT( "  Can Send Err = 0x%x\n"), err ) );
            ntxbuffer=0;
            break;
        }
}

/****************************************************************************
【功能说明】关闭屏蔽滤波功能
****************************************************************************/
void Can_Setup(void)
{
    //MCP2510_WriteBits(RXB0CTRL, (RXB_BUKT|RXB_RX_ANY), 0xFF);//关闭屏蔽滤波功能,接收所有报文,允许滚存
    MCP2510_WriteBits(RXB0CTRL, RXB_RX_ANY, 0xFF);        //关闭屏蔽滤波功能,接收所有报文
    //MCP2510_WriteBits(RXB1CTRL, RXB_RX_ANY, 0xFF);        //关闭屏蔽滤波功能,接收所有报文
}

/****************************************************************************
【功能说明】对MCP2510进行初始化,设置波特率。
****************************************************************************/
void Init_MCP2510(CanBandRate bandrate)
{
    SPIInit(1);
    MCP2510_Reset();
    MCP2510_Write(CANINTE, NO_IE);          //禁止所有中断
    MCP2510_SetBandRate(bandrate);        
    MCP2510_Write(CLKCTRL, MODE_NORMAL| CLKEN | CLK8);//标准模式
}
 
             /*以下为流接口驱动程序,上次应用程序应参考此接口函数*/

/****************************************************************************
【功能说明】CAN动态链接库的入口函数定义。
****************************************************************************/
BOOL WINAPI CAN_DllEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved)
{    
    switch(Reason)
    {
    case DLL_PROCESS_ATTACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

/****************************************************************************
【功能说明】打开CAN驱动程序,由系统CreateFile()函数打开CAN,返回驱动程序引用事例句柄。
 参数:DWORD dwData,CAN驱动的句柄,由CAN_Init函数创建的时候返回。
       DWORD dwAccess,传给驱动程序使用的地址。
       DWORD dwShareMode,在本函数中用来传递波特率。
****************************************************************************/
DWORD CAN_Open( DWORD dwData,
                DWORD dwAccess,
                DWORD dwShareMode)
{
    switch(dwShareMode) {
        case 0:
            Init_MCP2510(BandRate_10kbps); break;
        case 1:
            Init_MCP2510(BandRate_100kbps); break;
        case 2:
            Init_MCP2510(BandRate_125kbps); break;
        case 3:
            Init_MCP2510(BandRate_250kbps); break;
        case 4:
            Init_MCP2510(BandRate_500kbps); break;
        case 5:
            Init_MCP2510(BandRate_1Mbps); break;
        case 6:
            Init_MCP2510(BandRate_833kbps); break;
        default:
                        break;
    }
    Can_Setup();
    return 1;
}

/****************************************************************************
【功能说明】关闭CAN驱动程序,应用程序调用CloseHandle来停止使用流接口驱动,
            若调用成功返回TRUE,反之返回FALSE。
  参数:DWORD dwData,驱动的引用事例句柄,由CAN_Init函数创建。
****************************************************************************/
BOOL CAN_Close(DWORD dwData)
{
//    RETAILMSG(1,(TEXT( "CAN_Close\n"))) ;
    SPIInit(0);
    return TRUE;
}

/****************************************************************************
【功能说明】初始化CAN,应用程序不能直接调用此函数,通过ActivateDeviceEx函数
            来调用若调用成功返回1。
  参数:DWORD Index,指向字符串的指针,为流接口驱动在注册表的位置。
****************************************************************************/
DWORD CAN_Init(DWORD Index)
{
    GPIOInit();
    int i;
    U32 id;
    unsigned char dlc;
    int rxRTR, isExt;
    int temp;
    U8 data_read[32];
    while(1)
    {
        i = Can_Poll();
        if((i==0)|(i==1))
        {
        Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
        RETAILMSG(TRUE, (TEXT("can_data %u\r\n"), data_read));
        }
    }
    return 1;
}

/****************************************************************************
【功能说明】用于设备管理器来卸载CAN驱动程序,应用程序不能直接调用此函数,通过
             DeactivateDevice函数来调用
****************************************************************************/
BOOL CAN_Deinit(DWORD dwData)
{
    return TRUE;
}

/****************************************************************************
【功能说明】读接口程序,应用程序通过调用ReadFile函数来调用。
   参数:DWORD hOpenContext,CAN_Open函数返回的句柄。
         LPVOID pBuffer,一个缓冲区地址用于从CAN读数据。
         DWORD count,需要读缓冲区的长度
****************************************************************************/
DWORD CAN_Read(DWORD hOpenContext,LPVOID pBuffer ,DWORD count)
{
    int i;
    U32 id;
    unsigned char dlc;
    int rxRTR, isExt;
    int temp;
    U8 data_read[32];
    if(count==9)
    {
        memcpy(CanID,pBuffer,4);
        count=8;
Read:
        i = Can_Poll();
        
        if((i==0)|(i==1))
        {
            memset(data_read,0,sizeof(data_read) ) ;
            temp = Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
//            RETAILMSG (1, (TEXT("::: PBT_InitializeAddresses - Fail!!\r\n") ));
//                        UART_printf("0x%x\r\n",data_read);
  //                       sprint(
  RETAILMSG(TRUE, (TEXT("can_data %u\r\n"), data_read));

            out_buff[0] = ((id>>24)&0xff);  
            out_buff[1] = ((id>>16)&0xff);                    
            out_buff[2] = ((id>>8)&0xff);
            out_buff[3] = ((id)&0xff);
            if((out_buff[2]!=CanID[2]) || (out_buff[3]!=CanID[3]))
            {    
                goto Read;
            }else
            {            
                memcpy(pBuffer,data_read,count);
            }
        }
        else
        {
            return 0;
              }
    }else if(count!=9)
    {
        i = Can_Poll();
        
        if((i==0)|(i==1))
        {
            memset(data_read,0,sizeof(data_read) ) ;
            temp = Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
            memcpy(pBuffer,data_read,count);
            out_buff[0] = ((id>>24)&0xff);  
            out_buff[1] = ((id>>16)&0xff);
            out_buff[2] = ((id>>8)&0xff);
            out_buff[3] = ((id)&0xff);  
        }
        else
        {
            return 0;
              }
    }
    return count ;
}

/****************************************************************************
【功能说明】写接口程序,应用程序通过调用WriteFile函数来调用。
   参数:DWORD hOpenContext,CAN_Open函数返回的句柄。
         LPCVOID pSourceBytes,指向要写的数据缓冲的指针。
         DWORD NumberOfBytes,定义从pSourceBytes写道CAN的字节数。
****************************************************************************/
DWORD CAN_Write(DWORD hOpenContext,LPCVOID pSourceBytes,DWORD NumberOfBytes)
{
    
    unsigned char * pTmp ;
    U32 ID_data = 0x0;  
    int rxRTR, Ext,i, isExt;
    U32 id;
    unsigned char dlc;
    U8 data_read[32];
    i = Can_Poll();
    if((i==0)|(i==1))
        {            
            Can_Read(i, &id, data_read, &dlc, &rxRTR, &isExt);
        }
    pTmp = (unsigned char *)pSourceBytes ;
    ID_data = in_buff[5]|(in_buff[4]<<8)|(in_buff[3]<<16)|(in_buff[2]<<24);  
    Ext = in_buff[0];  
    rxRTR = in_buff[1];  
    Can_Write( ID_data, (unsigned char *)pTmp, NumberOfBytes, Ext, rxRTR);  
    return 1;
}

/****************************************************************************
【功能说明】移动设备的数据指针。应用程序调用SetFilePointer函数移动设备数据
            指针时,系统会调用CAN_Seek函数。
****************************************************************************/
DWORD CAN_Seek(DWORD hOpenContext, long Amount,WORD Type)
{
   // RETAILMSG(1,(TEXT("ucDragon seek----\r\n")));
    return 1;
}

/****************************************************************************
【功能说明】此函数通常用于向设备发送一个命令,应用程序使用DeviceIoControl
             函数来通知系统调用此函数,在本驱动中用来扩展流接口,用于应用层跟
             底层驱动交互数据。
   参数:DWORD  dwOpenData,CAN的上下文句柄,由CAN_Open函数创建和返回。
         DWORD  dwCode,定义完成此次的I/O控制操作,在本驱动中用来传递
                        读写控制指令,0为写操作,1为读操作。
         PBYTE  pBufIn,缓冲区指针指向需要传给驱动程序使用的数据,本驱动中
                        用来向驱动传递32位的ID号。
         DWORD  dwLenIn,要传给驱动使用数据的长度,本驱动中用来向驱动传递
                         是否扩展帧和远程帧信息,在本产品中一般只需值为0。
         PBYTE  pBufOut,缓冲区指针指向驱动程序传给应用程序使用的数据,本驱动中
                         用来向应用程序传递32位的ID号。
         DWORD  dwLenOut,要传给应用成熟使用数据的长度。
         PDWORD pdwActualOut,用于返回实际处理数据的长度。
****************************************************************************/
BOOL CAN_IOControl(DWORD  dwOpenData,
                   DWORD  dwCode,
                   PBYTE  pBufIn,
                   DWORD  dwLenIn,
                   PBYTE  pBufOut,
                   DWORD  dwLenOut,
                   PDWORD pdwActualOut)
{
    if(dwCode==0) {
        switch(dwLenIn) {           //
        case 0:
            in_buff[0] = 0;        //标志帧  
            in_buff[1] = 0;break;  //不是远程帧  
        case 1:
            in_buff[0] = 0;
            in_buff[1] = 1;break;
        case 2:
            in_buff[0] = 1;         //扩展帧
            in_buff[1] = 0;break;   //非远程帧
        case 3:
            in_buff[0] = 1;
            in_buff[1] = 1;break;
        default:
            break;
        }  
        in_buff[2] = pBufIn[0]; //传递ID,总共4个字节 31~24
        in_buff[3] = pBufIn[1]; //传递ID,总共4个字节 23~16
        in_buff[4] = pBufIn[2]; //传递ID,总共4个字节 15~8  
        in_buff[5] = pBufIn[3]; //传递ID,总共4个字节 7~0  
    }
    else {
        pBufOut[0] = out_buff[0];   //传递ID,总共4个字节 31~24
        pBufOut[1] = out_buff[1];   //传递ID,总共4个字节 23~16
        pBufOut[2] = out_buff[2];   //传递ID,总共4个字节 15~8
        pBufOut[3] = out_buff[3];   //传递ID,总共4个字节 7~0
    }
    return TRUE;
}
游客

返回顶部