本文主要讲述了基于SPI总线的RC522驱动程序的设计。描述了主控如何与从设备通过SPI总线进行数据的读写。
一 在SPI驱动中,有两个重要的结构:spi_device&spi_driver。
1 spi_device的构建与注册:
Spi_device板信息用spi_board_info结构体来描述,它描述了SPI外设(RC522模块)使用的主机控制器序号,片选信号,数据比特率,传输方式等。故要先填充struct spi_board_info这个结构体。--4412平台在mach-smdk4x12.c里,三星给的BSP包里面已经配置好了这些,我们要做的只是打开CONFIG_S3C64XX_DEV_SPI这个宏。
spi_register_board_info(spi2_board_info, ARRAY_SIZE(spi2_board_info));
具体实现见下面代码。
点击(此处)折叠或打开
-
static struct spi_board_info spi2_board_info[] __initdata = {
-
-
{
-
-
.modalias = "rfid_rc522",
-
-
.platform_data = NULL,
-
-
.max_speed_hz = 10*1000*1000,
-
-
.bus_num = 2,
-
-
.chip_select = 0,
-
-
.mode = SPI_MODE_0,
-
-
.controller_data = &spi2_csi[0],
-
-
}
-
-
};
-
-
-
static struct s3c64xx_spi_csinfo spi2_csi[] = {
-
-
[0] = {
-
-
.line = EXYNOS4_GPC1(2),
-
-
.set_level = gpio_set_value,
-
-
.fb_delay = 0x2,
-
-
},
-
- }
2 spi_driver的构建与注册:
点击(此处)折叠或打开
-
spi_register_driver(&rc522_driver);
-
-
-
static struct spi_driver rc522_driver = {
-
-
.probe = rc522_probe,
-
-
.remove = rc522_remove,
-
-
.driver = {
-
-
.name = "rfid_rc522",
-
-
},
-
-
};
-
-
-
static int rc522_probe(struct spi_device *spi)
-
-
{
-
-
//默认读第一块(可选0 ~ 63)
-
-
KuaiN = 1;
-
-
printk("%s\n", __func__);
-
-
rc522_spi = spi;
-
-
return 0;
-
- };
二 注册好了SPI设备与驱动,就可以通过SPI总线实现数据读写了。
这里注册了一个混合设备:misc_register(&rc522_misc_device);
点击(此处)折叠或打开
-
static struct miscdevice rc522_misc_device = {
-
-
.minor = MISC_DYNAMIC_MINOR,
-
-
.name = "rfid_rc522_dev",
-
-
.fops = &rc522_fops,
-
-
};
-
-
-
static struct file_operations rc522_fops = {
-
-
.owner = THIS_MODULE,
-
-
.open = rc522_open,
-
-
.release = rc522_release,
-
-
.read = rc522_read,
-
-
.write = rc522_write,
-
-
.poll = rc522_poll,
-
-
.unlocked_ioctl = rc522_ioctl,
-
-
-
};
-
-
//省略号这里省略了fops里各个操作的具体函数。
-
- ……
在read, write操作里都会调用到WriteRawRC(unsigned char Address, unsigned char value)函数,在这个函数里才真正实现了通过SPI来对RC522寄存器的读写操作:
点击(此处)折叠或打开
-
//////////////////////////////////////////////////////////////////
-
-
//功 能:写RC522寄存器
-
-
//参数说明:Address[IN]:寄存器地址
-
-
// value[IN]:写入的值
-
-
/////////////////////////////////////////////////////////////////////
-
-
void WriteRawRC(unsigned char Address, unsigned char value)
-
-
{
-
-
unsigned char ucAddr;
-
-
struct spi_transfer st[2];
-
-
struct spi_message msg;
-
-
-
CLR_SPI_CS;
-
-
ucAddr = ((Address<<1)&0x7E);
-
-
spi_message_init( &msg );
-
-
memset( st, 0, sizeof(st) );
-
-
-
st[ 0 ].tx_buf = &ucAddr;
-
-
st[ 0 ].len = 1;
-
-
spi_message_add_tail( &st[0], &msg );
-
-
-
st[ 1 ].tx_buf = &value;
-
-
st[ 1 ].len = 1;
-
-
spi_message_add_tail( &st[1], &msg );
-
-
spi_sync( rc522_spi, &msg );
-
-
-
SET_SPI_CS;
-
- };
三 添加定时器
为了节省CPU资源,需要添加一个定时器,每隔一定的时间才读卡一次。代码略。
到此为止,驱动的关键部分已经完工,只需把spi_register_driver(&rc522_driver)和misc_register(&rc522_misc_device)放进rfid_rc522_init()函数即可进行编译调试。