编写心得;
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;