工作需要做了s3c2410下用spi接口驱动74H595移位寄存器来控制8个LED。linux下字符型驱动为比较简单的驱动类型,作为入门很合适。硬件连接s3c2410---74H595: GPB0--RCLK SPICLK0--SRCLK SPIMOSI0--SER VDD--/SRCLR GND--/OE
编程流程可以参考2410用户手册部分p482前两步,关键是选择SPI的工作方式这个要看你连的什么硬件。这里我们选择的是FormatA方式。
以下是源代码部分:
#includelinux/config.h>
#includelinux/module.h>
#includelinux/kernel.h>
#includelinux/init.h>
#includeasm/hardware.h>
#includeasm/delay.h>
#includeasm/uaccess.h>
//#undef DEBUG
#define DEBUG
#ifdef DBUGE
#define DPRINTK(x...) printk("s3c2410-spi:" ## x)
#else
#define DPRINTK(x...)
#endif
#ifdef CONFIG_SMP
#define __SMP__
#endif
/*
GPE3 nSS0
GPE11 SPIMOSI0
GPE12 SPIMISO0
GPE13 SPICLK0
*/
#define LED_SCLK GPIO_E13
#define LED_SDAT GPIO_E12
#define LED_RCLK GPIO_B0
#define DEVICE_NAME "s3c2410-spi"
#define SPI_MINOR 1
static int SPI_MAJOR = 0;
static char SpiData = 0;
static ssize_t s3c2410_spi_write(struct file* file,const char* buffer,size_t count,loff_t* ppos)
{
copy_from_user(&SpiData,buffer,sizeof(SpiData));
DPRINTK("write: SPI=0x%x,count = %d\n",SpiData,count);
if((SPSTA0 & 0x01) == 0x01) //data Tx/Rx ready
{
SPTDAT0 = SpiData;
}
clr_gpio_bit(GPIO_B0);
udelay(10);
set_gpio_bit(GPIO_B0);
return 0;
}
static int s3c2410_spi_open(struct inode* inode,struct file* filp)
{
DPRINTK(DEVICE_NAME "open \n");
MOD_INC_USE_COUNT;
set_gpio_ctrl(GPIO_MODE_nSS|GPIO_PULLUP_DIS|GPIO_E3); //nSS no-pullup
set_gpio_ctrl(GPIO_MODE_SPICLK|GPIO_PULLUP_DIS|GPIO_E13); // CLK0 no-pullup
set_gpio_ctrl(GPIO_MODE_SPIMOSI|GPIO_PULLUP_EN|GPIO_E12); //SPIMOSI pullup
set_gpio_ctrl(GPIO_MODE_SPIMISO|GPIO_PULLUP_EN|GPIO_E13); // SPIMISO pullup
SPPRE0 = 0x00; //set baud rate prescaler register; Baud rate = PCLK/2/(Prescaler value + 1)
SPCON0 = (06)|(05)|(14)|(13)|(12)|(01)|(00);
//polling,en_sck,master,low,format A,normal
SPPIN0 = (02)|(11)|(00);
//Multi Master error detect disable, reserved release
return 0;
}
static int s3c2410_spi_release(struct inode* inode,struct file* filp)
{
DPRINTK(DEVICE_NAME" release \n");
MOD_DEC_USE_COUNT;
return 0;
}
static struct file_operations s3c2410_spi_fops ={
owner: THIS_MODULE,
open: s3c2410_spi_open,
write: s3c2410_spi_write,
release: s3c2410_spi_release,
};
#ifdef CONFIG_DEVFS_FS
static devfs_handle_t devfs_spi_dir,devfs_spi_raw;
#endif
static int __init s3c2410_spi_init(void)
{
int ret;
ret = register_chrdev(SPI_MAJOR,DEVICE_NAME,&s3c2410_spi_fops);
if(ret 0)
{
printk(DEVICE_NAME "can't get major number\n");
return ret;
}
SPI_MAJOR = ret;
#ifdef CONFIG_DEVFS_FS
devfs_spi_dir = devfs_mk_dir(NULL,"spi",NULL);
devfs_spi_raw = devfs_register(devfs_spi_dir,"0",DEVFS_FL_DEFAULT,
SPI_MAJOR,SPI_MINOR,S_IFCHR|S_IRUSR|S_IWUSR,&s3c2410_spi_fops,NULL);
#endif
DPRINTK(DEVICE_NAME "initialized\n");
return 0;
}
static void __exit s3c2410_spi_exit(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_spi_raw);
devfs_unregister(devfs_spi_dir);
#endif
unregister_chrdev(SPI_MAJOR,DEVICE_NAME);
}
module_init(s3c2410_spi_init);
module_exit(s3c2410_spi_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("uniquepeng");
MODULE_DESCRIPTION("spi driver for s3c2410");
评论0