s3c2410+linux通过SPI驱动双数码管参考代码
来源:互联网 发布:废铁战士 的淘宝店 编辑:程序博客网 时间:2024/06/08 05:53
学习了一段时间的嵌入式系统了,感觉它的复杂就体现在要和硬件打交道并且还要在操作系统中控制硬件。开发板上有一个实例,我把它改了一下便于理解,以作为以后学习的参考。
本人描述能力差,还是直接上图和代码吧。
硬件原理图:
驱动代码:
/**************magic_leds.c******************** s3c2410+linux 2.6.24.4通过SPI控制双数码管显示的驱动程序参考代码*/#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/fs.h>#include <asm/uaccess.h>#include <linux/slab.h>#include <linux/types.h>#include <linux/kdev_t.h>#include <linux/cdev.h>#include <linux/delay.h>#include <linux/device.h>#include <asm/io.h>#include <asm/unistd.h>#include <asm/plat-s3c24xx/regs-spi.h>#include <asm-arm/arch-s3c2410/regs-gpio.h>#define SPI_MAJORE 25#define DEVICE_NAME "S3C2410_SPI0"struct class *leds_class;struct cdev dev;#define rSPCON0 ((volatile unsigned long *)r_SPCON0) #define rSPSTA0 ((volatile unsigned long *)r_SPSTA0) #define rSPPIN0 ((volatile unsigned long *)r_SPPIN0) #define rSPPRE0 ((volatile unsigned long *)r_SPPRE0) #define rSPTDAT0 ((volatile unsigned long *)r_SPTDAT0) #define rSPRDAT0 ((volatile unsigned long *)r_SPRDAT0) #define rCLKCON ((volatile unsigned long *)r_CLKCON)unsigned long *r_SPCON0,*r_SPSTA0,*r_SPPIN0,*r_SPPRE0,*r_SPTDAT0,*r_SPRDAT0,*r_CLKCON;int address_map(void){ //将一个IO地址空间映射到内核的虚拟地址空间上去,便于访问; r_CLKCON = ioremap(0x4C00000c,4); //从s3c2410芯片手册中知道,这映射的是“时钟产生控制寄存器”的地址 r_SPCON0 = ioremap(0x59000000,4); //映射的是“SPI channel 0 control register”,串行外部接口通道0控制寄存器 r_SPSTA0 = ioremap(0x59000004,4); //映射的是“SPI channel 0 status register”,串行外部接口通道0状态寄存器 r_SPPRE0 = ioremap(0x5900000c,4); //映射的是“SPI cannel 0 baud rate prescaler register”,串行外部接口通道0波特率分频寄存器 r_SPTDAT0 = ioremap(0x59000010,4); //映射的是“SPI channel 0 Tx data register”,串行外部接口通道0传送数据寄存器 r_SPRDAT0 = ioremap(0x59000014,4); //映射的是“SPI channel 0 Rx data register”,串行外部接口通道0接收数据寄存器 return 0;}static ssize_t spi_open(struct inode *inode, struct file *file){ unsigned long temp; s3c2410_gpio_cfgpin(S3C2410_GPH0,S3C2410_GPH0_OUTP); s3c2410_gpio_pullup(S3C2410_GPH0, 0); temp = __raw_readl(rCLKCON); temp |= 0x40000; //根据s3c2410芯片手册可以知道,这是设置“Control PCLK into SPI block.” __raw_writel(temp,rCLKCON); __raw_writel(0x0d,rSPPRE0); //根据s3c2410芯片手册可以知道,这是设置Prescaler Value,“Determine SPI clock rate as above equation. Baud rate = PCLK / 2 / (Prescaler value + 1)” __raw_writel(0x19,rSPCON0); //查看芯片手册可知,这是在设置I2C的时钟可用,设置USB为master端 return 0;}static ssize_t spi_release(struct inode *inode, struct file *file){ printk("it has been released!\n"); return 0;}static ssize_t spi_read(struct file *file, char __user *buffer, long count, loff_t *ppos){ printk("it is reading from pin!\n"); return 1;}static ssize_t spi_write(struct file *file, const char __user *buffer, long count, loff_t *ppos){ int i; unsigned char ptr[count]; printk("start writing!\n"); if (copy_from_user(ptr, buffer, count))return -EFAULT; s3c2410_gpio_setpin(S3C2410_GPH0,0); for(i=0;i<count;i++) { while(((__raw_readl(rSPSTA0)) & 0x01) == 0x00); { __raw_writel(ptr[i],rSPTDAT0); //向传送寄存器中写入数据,芯片手册上有“SPI channel 0 Tx data register” printk("writing ptr[%d]=%X \n",i,ptr[i]); udelay(10); } } s3c2410_gpio_setpin(S3C2410_GPH0,1); return count;}static ssize_t spi_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ printk("it is the ioctl model!\n"); return 0;}static struct file_operations s3c2410_spi0_fops={.owner = THIS_MODULE,.open = spi_open,.write = spi_write,.read = spi_read, .ioctl = spi_ioctl, .release = spi_release,};static void spi_setup_cdev(void){int err,devno = MKDEV(SPI_MAJORE,0);cdev_init(&dev,&s3c2410_spi0_fops);dev.owner = THIS_MODULE;dev.ops = &s3c2410_spi0_fops;err = cdev_add(&dev,devno,1);if(err)printk(KERN_NOTICE"Error cdev_add!!!");}static int __init s3c2410_spi0_init(void){int ret;dev_t devno = MKDEV(SPI_MAJORE,0);address_map();ret = register_chrdev_region(devno, 1, DEVICE_NAME);printk(DEVICE_NAME "initializing\n");if (ret<0){printk(DEVICE_NAME "cann't register major numer\n");return ret;}printk(DEVICE_NAME "initialized\n");spi_setup_cdev();leds_class=class_create(THIS_MODULE,"led_class"); if(IS_ERR(leds_class)) {printk("err:failed in creating class.\n"); return -1; } class_device_create(leds_class,NULL,MKDEV(SPI_MAJORE,0),NULL,"S3C2410_SPI%d",0);return 0;}static void __exit s3c2410_spi0_exit(void){class_device_destroy(leds_class,MKDEV(SPI_MAJORE,0)); class_destroy(leds_class);cdev_del(&dev);unregister_chrdev_region(MKDEV(SPI_MAJORE,0), 1);}module_init(s3c2410_spi0_init);module_exit(s3c2410_spi0_exit);MODULE_AUTHOR("xw_tech@126.com"); MODULE_DESCRIPTION("led driver for UP_Magic");MODULE_LICENSE("GPL");
测试代码:
/*************magicleds_test.c*******************双数码管显示的测试代码*/#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>//#include <sys/ioctl.h>int MAX_LEN=255;int main(){int fd;int i;char c,sc;unsigned char buf1[32]={0xc0,0xc0,0xf9,0xf9,0xa4,0xa4,0xb0,0xb0, 0x99,0x99,0x92,0x92,0x82,0x82,0xf8,0xf8, 0x80,0x80,0x90,0x90,0x88,0x88,0x83,0x83, 0xc6,0xc6,0xa1,0xa1,0x86,0x86,0x8e,0x8e, };unsigned char buf[2]={0xff,0xff};fd=open("/dev/S3C2410_SPI0",O_RDWR);if(fd < 0){printf("####spi device open fail####\n");return (-1);} write(fd,&buf,2); //将buf中的两个字节写入到fd对应的文件中 while(1)for(i=0;i<32;){ write(fd,buf1+i,2); sleep(1); write(fd,buf,2); i=i+2; }close(fd);return 0;}
运行过程控制台截图:
由于本人菜鸟一个,错误之处在所难免,欢迎指正。
(---------------------完----------------------)
- s3c2410+linux通过SPI驱动双数码管参考代码
- S3c2410-SPI驱动设计
- S3c2410 Linux 驱动
- SPI FLASH_W25Q64驱动 代码
- Linux s3c2410 DMA驱动开发
- Linux s3c2410 DMA驱动开发
- linux s3c2410触摸屏驱动讲解
- linux spi驱动
- linux spi驱动分析
- linux spi驱动分析
- linux spi驱动分析
- linux spi驱动分析
- Linux SPI驱动
- LINUX SPI驱动笔记
- Linux SPI驱动
- linux spi驱动分析
- linux SPI总线驱动
- linux SPI 设备驱动
- Android--关于Android面试
- iOS 预览功能的实现
- VS2010 操作Word(五)图片操作
- 为学论坛“每日一题”系列---最长连续子数组
- VS2010 操作Word(六)属性设置
- s3c2410+linux通过SPI驱动双数码管参考代码
- 使用select和shutdown
- uploadify+Struts2实现多文件上传
- listview低分辨率下divider滑动时变粗
- 我对android理解之jni .
- DMA基本概念及linux2440下DMA驱动程序编写与测试
- 双控和三控 接线图
- 我对linux理解之tty一
- u-boot for tiny210(core:samsung s5pv210) 更新汇总