CAN总线驱动 .

来源:互联网 发布:golang accept 编辑:程序博客网 时间:2024/05/21 07:05

AT91 linux开发板的驱动\CAN总线驱动

分类: Android linux 驱动 504人阅读 评论(0)收藏 举报
linuxbytebuttonstructdelaybuffer

编写心得;

can总线的芯片是mcp2515,利用spi进行数据的读写,spi是写在底层的驱动,对于mcp的数据读写操作放在应用层里面完成的

1:spi的底层驱动代码是

#include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/rtc.h> /* get the user-level API */
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/pci.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/pci.h>
#include <linux/input.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/kdev_t.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <asm/mach/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/leds.h>
#include <asm/mach-types.h>
#include <mach/at91_pio.h>
#include <mach/gpio.h>
#include <mach/hardware.h>
#include <linux/version.h>

//boy
/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
#define SPI_READ_MODE          _IOR('D', 1, long)
#define SPI_WRITE_MODE          _IOW('D', 1, long)
#define CS_SPI_H          _IOW('D', 2, int)
#define CS_SPI_L          _IOW('D', 3, int)
#define SPI_READ_DATA          _IOR('D', 4, long)
#define SPI_WRITE_DATA          _IOW('D', 4, long)
/*
     通过测试成功 AT91 的开发板 内核是2.6.27
*/
#define DEVICE_NAME     "spi"  /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */ 
#define SPI_MAJOR       231    /*  */
///
#define SPI_CLK_H      (at91_set_gpio_value(AT91_PIN_PA2, 1))
#define SPI_CLK_L      (at91_set_gpio_value(AT91_PIN_PA2, 0))
#define SPI_MOSI_H      (at91_set_gpio_value(AT91_PIN_PA1, 1))
#define SPI_MOSI_L      (at91_set_gpio_value(AT91_PIN_PA1, 0))
#define MCP2515_CS_H    (at91_set_gpio_value(AT91_PIN_PA3, 1))
#define MCP2515_CS_L    (at91_set_gpio_value(AT91_PIN_PA3, 0))
///PA3作为片选
struct button_irq_desc
 {   
  int irq;    /*中断号*/
  unsigned long flags;    /*中断标志,用来定义中断触发方式*/
  char *name;    /* 中断名称*/
 }; 
static struct button_irq_desc button_irqs [] = {   
 {AT91_PIN_PA26,AT91_AIC_SRCTYPE_RISING, "cancle"},    
 //{AT91_PIN_PA28,AT91_AIC_SRCTYPE_RISING, "right"},
 //{AT91_PIN_PA29,AT91_AIC_SRCTYPE_RISING, "enter"},
 };
wait_queue_head_t button_waitq; /**/  
static void __iomem *pio_base;
static volatile int ev_press = 0;/* 中断事件标志, 中断服务程序将它置1,buttons_read将它清0 */
//////
/***************************************************
*函数名:static irqreturn_t buttons_interrupt(int irq, void *dev_id)
*描述:中断服务函数
*输入参数:
*返回:
***************************************************/
static irqreturn_t buttons_interrupt(
    int irq,
    void *dev_id)
{    
 ev_press = 1;                   // 表示中断发生了 
 wake_up_interruptible(&button_waitq);    // 唤醒休眠的进程    
 printk(KERN_DEBUG"SPI_CAN_INTERRUPTER\n");
 return IRQ_RETVAL(IRQ_HANDLED);
}
////////delay()
void spi_delay(int num)
{
  int i;
  while(num--)
  {
     for(i = 0;i<100;i++);
  }
}
int SpiWrite(unsigned char data)
{
 int i;
 unsigned char datat;
 datat = data;
 unsigned char mask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
        for(i=7; i >= 0; i--)
 {
  SPI_CLK_L;                  //把clock线拉低,模拟一个时钟
  if((data & mask[i]) >> i)   //把数据送上DATA线
   SPI_MOSI_H; 
  else
   SPI_MOSI_L;
  ////////测试把MOSI于MISO连接在一起可以进行测试,要注意因为写的东西没有保存所以读和写要在一个函数里面就可以了//
  //if((readl(pio_base + PIO_PDSR) & mask[i]) >> i)//把数据送上DATA线 ?读寄存器是不行的,不知道原因
  /*
  if(at91_get_gpio_value(AT91_PIN_PA0)==1)
  {
    printk(DEVICE_NAME " PA0=1\n");
  }
  else
  {
    printk(DEVICE_NAME " PA0=0\n");
                }
                */ 
                 ////////测试读数据////////////////////////////////////////////////////////////////////////////
  spi_delay(10);              //等待适当的时间,以等待数据稳定
  SPI_CLK_H;                  //拉高clock线,让设备端接收数据
  spi_delay(10);
 }
 return 1;
}
int SpiRead(unsigned char *data)
{

 int i;
 unsigned char dataa=0x29;
 unsigned char mask[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
        for(i=7; i >= 0; i--)
 {
  SPI_CLK_L;               //把clock线拉低,模拟一个时钟
  if(at91_get_gpio_value(AT91_PIN_PA0)==1)//读I/O就可以了 真他妈的搞不懂
  {
   *data |= 0x1<<i;
  }
  else
  {
   *data &= ~(0x1<<i);
                }
  spi_delay(10);                     //等待适当的时间,以等待数据稳定
  SPI_CLK_H;                          //拉高clock线,让设备端接收数据
  spi_delay(10);
  
 }
 //printk(DEVICE_NAME " spiread\n");
 return 1;
}
static int spi_open(struct inode *inode, struct file *file)
{
        int i;
        int err;
        printk(DEVICE_NAME"::SPI_OPEN \n");
        at91_set_A_periph(AT91_PIN_PA0, 1); /* SPI0_MISO */
     at91_set_A_periph(AT91_PIN_PA1, 1); /* SPI0_MOSI */
     at91_set_A_periph(AT91_PIN_PA2, 1); /* SPI1_SPCK */
 
        at91_set_gpio_output(AT91_PIN_PA2, 1);    /* I/O 口设置*/
        at91_set_deglitch(AT91_PIN_PA2, 1);
       
        at91_set_gpio_output(AT91_PIN_PA1, 1);    /* I/O 口设置*/
        at91_set_deglitch(AT91_PIN_PA1, 1);
       
        at91_set_gpio_input(AT91_PIN_PA0, 1);    /* I/O 口设置*/
        at91_set_deglitch(AT91_PIN_PA0, 1);
       
        at91_set_gpio_output(AT91_PIN_PA3, 1);    /* I/O 口设置*/
        at91_set_deglitch(AT91_PIN_PA3, 1);
        /////按键测试
        at91_set_gpio_input(AT91_PIN_PA26, 1);    /* I/O 口设置*/
 at91_set_deglitch(AT91_PIN_PA26, 1);
        pio_base = ioremap(0xFFFFF400,512);  //PIOA开始的地址 以及空间512字节 
        //注册中断
      
        for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++){
 err = request_irq(button_irqs[i].irq, buttons_interrupt, button_irqs[i].flags,                          
        button_irqs[i].name, NULL);
        /*注册中断*/
  
  if (err){     /*如果出错,则退出*/
   printk(KERN_ERR"request_irq_err\n");
   break;
  }  
 }
 
 if (err){             /*如果出错,则把已经注册的中断释放*/     
  i--;       
  for (; i >= 0; i--){          
   free_irq(button_irqs[i].irq, NULL);
  }      
  return -EBUSY;   
 }           
        printk(DEVICE_NAME"::SPI_OPEN_END\n");
        return 0;
 } 
 /***************************************************
*函数名:static int buttons_close(struct inode *inode, struct file *file)
*描述:应用程序对设备文件/dev/buttons执行close(...)时,就会调用buttons_close函数
*输入参数:
*返回:
***************************************************/
static int spi_close(
    struct inode *inode,
    struct file *file)
{   
 int i;       
 for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
 {       
  free_irq(button_irqs[i].irq, NULL);  //释放中断 
 }   
 return 0;
}
 
static int spi_write(struct file *file, const char __user *buf, size_t count)
{
       int i;
       unsigned char  missing;
       unsigned char  *buffer;
       ssize_t       status = 0;
       buffer = kmalloc(count*sizeof(char), GFP_KERNEL); 
       missing=copy_from_user(buffer,buf, count);
       if(missing != 0)
       {
          kfree(buffer);
          status = -EFAULT;
        }
       printk(KERN_INFO "count =%d\n",count);
       for(i=0;i<count;i++)
       {
    SpiWrite(*buffer++);
 }
 return status;
}

static int spi_read(struct file *file, const char __user *buf, size_t count)
{
        int i;
        unsigned char  missing;
        unsigned char  *buffer;
        ssize_t       status = 0;
        ev_press = 0;
        printk(KERN_INFO "Spi_read_start\n");  
        wait_event_interruptible(button_waitq, ev_press); /* 如果ev_press等于0,休眠 */  
        printk(KERN_INFO "Spi_read_dormancy\n");
        buffer = kmalloc(count*sizeof(char), GFP_KERNEL);
 for(i=0;i<count;i++)
 {
    SpiRead(buffer++);
  }
 missing=copy_to_user(buf,buffer, count);//boy
        if(missing != 0)
        {
           kfree(buffer);
           status = -EFAULT;
        }
 ev_press = 0; 
 return status;
}                                   
//应用程序对设备文件/dev/leds执行ioclt(...)时,就会调用s3c2410_leds_ioctl函数
static int spi_ioctl(
    struct inode *inode,
 struct file *file,
 unsigned int cmd,
 unsigned char *arg
        )
{
     unsigned char TxBuff[1]={0};
     unsigned char RxBuff[1]={0};
     int           missing = 0;
     ssize_t    status = 0;
    switch(cmd) { 
        case SPI_WRITE_DATA:
             missing=copy_from_user(TxBuff,arg,sizeof(arg));
             if(missing != 0) return -EFAULT;
             SpiWrite(TxBuff[0]);
             return 0;
        break; 
        case SPI_READ_DATA:
             SpiRead(RxBuff);
             missing=copy_to_user(arg,RxBuff, sizeof(RxBuff)/sizeof(RxBuff[0]));
             if(missing != 0) return -EFAULT;
             return 0;
        break; 
        case CS_SPI_H:      
             MCP2515_CS_H;
             return 0;
        break; 
        case CS_SPI_L:
             MCP2515_CS_L;
             return 0;
        break;
        case SPI_READ_MODE:
              SPI_MOSI_H;
              return 0;
        break;
        case SPI_WRITE_MODE:
             SPI_MOSI_L;
             return 0;
        break;
    default:
         printk(DEVICE_NAME" leds_ioctl_default\n");
        return -EINVAL;
     
        return 0;
    }
}
static struct file_operations S5PC100_leds_fops = {
    .owner  =   THIS_MODULE,
    .open   =   spi_open,
    .ioctl  =   spi_ioctl,
    .read   =   spi_read,
    .write  =   spi_write,
    .release   = spi_close,
};
static int  spi_init(void)
{   
     int ret;
     ret = register_chrdev(SPI_MAJOR, DEVICE_NAME, &S5PC100_leds_fops);
     init_waitqueue_head(&button_waitq);
    return ret;          
}
static void  spi_exit(void)
{
        unregister_chrdev(SPI_MAJOR, DEVICE_NAME);
        printk(DEVICE_NAME "s5pc100_leds_exit\n");
}
module_init(spi_init);
module_exit(spi_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("luckyboy");
//表示在make menuconfig 里面可以选着////
/*****Kconfig****************************
      config ATSAM9G20_SPI
      tristate "spi"
      default m
******************************************/

/****Makeflie*****************************
obj-$(CONFIG_ATSAM9G20_SPI)   +=spi.o
******************************************/
////该驱动没有动态加载功能
//所以要执行 mknod /dev/spi c 231 0
//表示编译为模块////
 2:mcp2515.h文件是

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
//MCP2515 Define the command constant
#define SPI_READ_MODE          _IOR('D', 1, long)
#define SPI_WRITE_MODE          _IOW('D', 1, long)
#define CS_SPI_H          _IOW('D', 2, int)
#define CS_SPI_L          _IOW('D', 3, int)
#define SPI_READ_DATA          _IOR('D', 4, long)
#define SPI_WRITE_DATA          _IOW('D', 4, long)
////
int fd;
//unsigned char buffer[8]={ 0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
/////
//MCP2515 波特率配置  16M晶振     SJW  段数(1+PRSEG+PRSEG1+PRSEG2)  
#define CNF1_5K      0xff        //4   25(1+8+8+8)
#define CNF2_5K      0xff
#define CNF3_5K      0x47

#define CNF1_10K     0xe9        //4   19(1+3+8+7)
#define CNF2_10K     0xfa
#define CNF3_10K     0x46
 
#define CNF1_15K     0xdb        //4   19(1+3+8+7)
#define CNF2_15K     0xfa
#define CNF3_15K     0x46

#define CNF1_20K     0xd3        //4   20(1+4+8+7)
#define CNF2_20K     0xfb
#define CNF3_20K     0x46

#define CNF1_25K     0xcb        //4   20(1+4+8+7)
#define CNF2_25K     0xfb
#define CNF3_25K     0x46

#define CNF1_40K     0xc9        //4   20(1+4+8+7)
#define CNF2_40K     0xfb
#define CNF3_40K     0x46

#define CNF1_50K     0xc7        //4   20(1+4+8+7)
#define CNF2_50K     0xfb
#define CNF3_50K     0x46

#define CNF1_80K     0xc4        //4   20(1+4+8+7)
#define CNF2_80K     0xfb
#define CNF3_80K     0x46

#define CNF1_100K    0x84        //3   16(1+1+8+6)
#define CNF2_100K    0xf8
#define CNF3_100K    0x45

#define CNF1_125K    0x83        //3   16(1+1+8+6)
#define CNF2_125K    0xf8
#define CNF3_125K    0x45

#define CNF1_200K    0xc1        //4   20(1+4+8+7)
#define CNF2_200K    0xfb
#define CNF3_200K    0x46

#define CNF1_250K    0x81        //3   16(1+1+8+6)
#define CNF2_250K    0xf8
#define CNF3_250K    0x45

#define CNF1_400K    0xc0        //4   20(1+4+8+7)
#define CNF2_400K    0xfb
#define CNF3_400K    0x46

#define CNF1_500K    0x80        //3   16(1+1+8+6)
#define CNF2_500K    0xf8
#define CNF3_500K    0x45

#define CNF1_667K    0x80        //3   12(1+1+5+5)
#define CNF2_667K    0xa0
#define CNF3_667K    0x44

#define CNF1_800K    0x80        //3   10(1+1+4+4)
#define CNF2_800K    0x98
#define CNF3_800K    0x43

#define CNF1_1M      0x40        //2   08(1+1+3+3)
#define CNF2_1M      0x90
#define CNF3_1M      0x42

 3:mcp2515.c文件是

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "mcp2515.h"
unsigned char  RXBnSIDL,RXBnDLC;
unsigned char  byte_IR;
unsigned char Cmmd[]={0xc0,0x05,0x03,0x02,0x36,0x81,0x61};
//                   复位指令 位修改指令 读指令 写指令 发送缓存的地址  0的发送请求 接收缓冲器0标准标识符的高位
unsigned char *pointer=Cmmd;
//功能:复位指令可以重新初始化MCP2515 的内部寄存器,并设置配置模式  片选::PA3管脚
void delay(int num)
{
  int i;
  while(num--)
  {
     for(i = 0;i<100;i++);
  }
}
void Reset_2515()
{
        ioctl(fd,CS_SPI_L,NULL);       //CS_SPI=0;
        ioctl(fd,SPI_WRITE_DATA,pointer);//复位指令0xc0
        ioctl(fd,CS_SPI_H,NULL);       //CS_SPI=1;
}
//功能:只修改寄存器中的某些位
//入口参数:Addr:寄丰器地址  MASK:屏蔽字  dat:数据字节
void MODIFY_2515(unsigned char addr,unsigned char mask,unsigned char dat)
{
     ioctl(fd,CS_SPI_L,NULL);       //CS_SPI=0;
     ioctl(fd,SPI_WRITE_DATA,(pointer+1));//位修改指令0x05
     ioctl(fd,SPI_WRITE_DATA,&addr);
     ioctl(fd,SPI_WRITE_DATA,&mask); 
     ioctl(fd,SPI_WRITE_DATA,&dat); 
     ioctl(fd,CS_SPI_H,NULL);       //CS_SPI=1;
}
//功能:从指定地址起始的寄存器读取数据。读寄存器的值
unsigned char Read_BYTE_2515(unsigned char addr)
{
    unsigned char ret;
    unsigned char RxBuff[1]={0};
    ioctl(fd,CS_SPI_L,NULL);        //CS_SPI=0;
    ioctl(fd,SPI_WRITE_DATA,(pointer+2)); //读指令 0x03
    ioctl(fd,SPI_WRITE_DATA,&addr);
    ioctl(fd,SPI_READ_DATA,RxBuff);
    ret = RxBuff[0];
    ioctl(fd,CS_SPI_H,NULL);       //CS_SPI=0;
    return(ret);
}
//功能:读出数据。接受传过来的报文
 unsigned char Read_SPI( )
 {
    unsigned char ret;
    unsigned char rx_bufer[1]={0};
   /* if(read(fd,rx_bufer,sizeof(rx_bufer)/sizeof(rx_bufer[0]))<0) //注意fd?
    {
           perror("read wrong::");
           exit(1);
    }
    */
    ioctl(fd,SPI_READ_DATA,rx_bufer);
    ret = rx_bufer[0];
    return(ret);
  }
 //功能:读出数据。接受传过来的报文
 unsigned char Read_Inter( )
 {
    unsigned char ret;
    unsigned char rx_bufer[1]={0};
    if(read(fd,rx_bufer,sizeof(rx_bufer)/sizeof(rx_bufer[0]))<0) //注意fd?
    {
           perror("read wrong::");
           exit(1);
    }
    ret = rx_bufer[0];
    return(ret);
  }
//功能:将数据写入指定地址起始的寄存器。
void Write_BYTE_2515(unsigned char addr, unsigned char dat)
{
    ioctl(fd,CS_SPI_L,NULL);       //CS_SPI=0;
    ioctl(fd,SPI_WRITE_DATA,(pointer+3));//写指令0x02
    ioctl(fd,SPI_WRITE_DATA,&addr);
    ioctl(fd,SPI_WRITE_DATA,&dat);
    ioctl(fd,CS_SPI_H,NULL);       //CS_SPI=1;
}
void  Init_can(void)
{
    Reset_2515();                    //复位       
    Write_BYTE_2515(0x0f, 0x80);     //CANCTRL寄存器--进入配置模式 中文DATASHEET 58页
    //可以设置的波特率 5K 10K 15K 20K 25K 40K 50K 80K 100K 125K 200K 400K 500K 667K 800K 1M
    Write_BYTE_2515(0x2A, CNF1_50K); //CNF1位定时配置寄器   中文DATASHEET 41-42页
    Write_BYTE_2515(0x29, CNF2_50K); //CNF2位定时配置寄器   中文DATASHEET 41-42页
    Write_BYTE_2515(0x28, CNF3_50K); //CNF3位定时配置寄器   中文DATASHEET 41-43页
    Write_BYTE_2515(0x2B, 0x1f);     //CANINTE中断使能寄存器  中文DATASHEET 50 页
    Write_BYTE_2515(0x60, 0x60);     //RXB0CTRL接收缓冲器0 控制寄存器 中文DATASHEET 27 页 关闭滤波功能
    MODIFY_2515(0x0C, 0x0f, 0x0f);   //BFPCTRL_RXnBF 引脚控制寄存器和状态寄存器 中文DATASHEET 29 页
    Write_BYTE_2515(0x0f, 0x00);     //CAN控制寄存器--工作模式
}
void Can_send(unsigned char ID[],unsigned char tx_buff[],unsigned char Fream)
{
    unsigned char i,ret;
    unsigned char data=0;
    unsigned char *point=tx_buff;
    do
    {
        delay(100);
        ret = Read_BYTE_2515(0x30);
    } while (ret&0x10);               //如果报文发送有误就循环  死在这里?????
    if (Fream==1)                     //标准数据帧
    {
        Write_BYTE_2515(0x31, ID[0]); //发送缓冲器0标准标识符高位
 ID[1]=ID[1]&0xe0;
        Write_BYTE_2515(0x32, ID[1]); //发送缓冲器0标准标识符低位
        Write_BYTE_2515(0x35, 0x08);  //发送缓冲器0数据长度码 8个字节
        printf("Fream == 1\n");
    }
    else if (Fream==2) //扩展数据帧
    {       
        ID[1]=(ID[1]&0xe3)|0x08;
        Write_BYTE_2515(0x31, ID[0]); //发送缓冲器0标准标识符高位       
        Write_BYTE_2515(0x32, ID[1]); //发送缓冲器0标准标识符低位
        Write_BYTE_2515(0x33, ID[2]); //发送缓冲器0扩展标识符高位
        Write_BYTE_2515(0x34, ID[3]); //发送缓冲器0扩展标识符低位
        Write_BYTE_2515(0x35, 0x08);  //发送缓冲器0数据长度码 8个字节
        printf("Fream == 2\n");
    }
    ioctl(fd,CS_SPI_L,NULL);          //CS_SPI=0;
    ioctl(fd,SPI_WRITE_DATA,(pointer+3)); //写指令
    ioctl(fd,SPI_WRITE_DATA,(pointer+4)); //发送缓冲器地址 0x36-0x3Dh
    for(i = 0; i < 8; i++) ioctl(fd,SPI_WRITE_DATA,(point+i));//发送缓冲器 Write_SPI(tx_buff[i]);
    ioctl(fd,CS_SPI_H,NULL);       //CS_SPI=1;
    ioctl(fd,CS_SPI_L,NULL);       //CS_SPI=0;
    ioctl(fd,SPI_WRITE_DATA,(pointer+5));//TXBO请求发送0x81
    ioctl(fd,CS_SPI_H,NULL);             //CS_SPI=1;
}
unsigned char Can_receive(unsigned char ID[],unsigned char rx_buff[])
{
    unsigned char i;
    unsigned char interrupter;
    interrupter = Read_Inter();
    byte_IR = Read_BYTE_2515(0x2c);    //读取中断标志寄存器的值 CANINTF  51页
    printf("byte_IR =::0x%02X\n",byte_IR);
    if (byte_IR == 0xff) return(3);    //错误
    if (byte_IR == 0xe0) return(0);    //无数据
    if (byte_IR & 0x01)                //CANINTF的第0位=1  bit_RI=接收缓冲器0满中断标志位
    {
        printf("byte_IR_in =::0x%02X\n",byte_IR);
        ioctl(fd,CS_SPI_L,NULL);       //片选 CS_SPI = 0;
        ioctl(fd,SPI_WRITE_DATA,(pointer+2));//读指令
        ioctl(fd,SPI_WRITE_DATA,(pointer+6));//接收缓冲器0标准标识符的高位0x61
        printf("Read_spi\n");
        for(i = 0; i < 4; i++) ID[i] = Read_SPI();
        printf("Read_spi2\n");
 RXBnSIDL = ID[1];           //读取0x62的值
 RXBnDLC = Read_SPI();       //读取0x65的值
        for(i = 0; i < 8; i++) rx_buff[i] = Read_SPI();//读取0x66-0xDh的值
        ioctl(fd,CS_SPI_H,NULL);       //CS_SPI=1;
        MODIFY_2515(0x2c,0x01,0x00);
  if((!(RXBnSIDL & 0x08)) && (!(RXBnSIDL & 0x10))) return (1);//接收标准数据帧
  if((RXBnSIDL & 0x08) && (!(RXBnDLC & 0x40)))     return (2);//接收扩展数据帧
    }
    if (byte_IR & 0x04) //bit_TI=发送缓冲器0空中断标志位
    {
 MODIFY_2515(0x2c, 0x04, 0x00);
 return(3);
    }
    Write_BYTE_2515(0x2c, 0x00);//清零CANINTF
    return(0);
}

 4:main.c的住测试文件是

/*
 * mcp2515 test(using spidev driver)
 *
 * Copyright (c) 2011 3 1 wangyulu
 * Copyright (c) 2011 3 1 wangyulu<wangyuluyulu@126.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 */
//#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include<sys/stat.h> 
#include<fcntl.h> 
#include "mcp2515.h"
unsigned char TxBuff[8]={0x91,0x88,0x77,0x66,0x33,0x55,0x99,0xe0};
unsigned char RxBuff[8]={0};
unsigned char ID[4];
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
void delay_ms(unsigned short ms)
{
    unsigned short i;
    unsigned char j;
    for(i=0;i<ms;i++)
    {
        for(j=0;j<200;j++);
        for(j=0;j<102;j++);
    }
}
int main(int argc, char **argv)
{     
     unsigned char ret;
     unsigned char i;
     unsigned char counter=0;
     fd =  open("/dev/spi",O_RDWR);
     if(fd <0 )
     {
         perror("open device spi::");
         //exit(1);
     }
     else
     {
         printf("open device sucess::\n");
         delay_ms(100);
     }
     Init_can();//初始化MCP2515
     for(i=0;i<4;i++)
     {
        ID[i]=0;
     }
     Can_send(ID,TxBuff,1); //发送标准帧
     delay_ms(100);    
     while(1)
     {
         
           ret = Can_receive(ID,RxBuff); //接收CAN总线数据
           if(ret == 1)
           {
              delay_ms(100); 
              for(i=0;i<8;i++) printf("Can_receive_RxBuff:: %d\n", (RxBuff[i]-48));
           }
           if(ret == 0)  printf("ret::%d\n",ret);
           if(ret == 1)  printf("ret::%d\n",ret);
           if(ret == 2)  printf("ret::%d\n",ret);
           if(ret == 3)  printf("ret::%d\n",ret);
          // counter ++;
     }
     close(fd);
     return 0;     
}

 

以上是我写的can总线的测试文件,希望对大家有帮助,如有疑问可以讨论,欢迎大家留言,谢谢!