`
qvb3d
  • 浏览: 171574 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Linux Kernel 内核驱动 gpio 数码管

 
阅读更多


下面具体说一段代码 (原创禁止转载) 
驱动源码 
//********************************************************************************

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/fs.h> 
#include <linux/errno.h> 
#include <linux/types.h> 
#include <linux/cdev.h> 
#include <linux/wait.h> 
#include <mach/regs-gpio.h> //gpio 寄存器的内核初始宏定义
#include <mach/regs-gpioj.h> //gpio 寄存器的内核扩展宏定义 
#include <asm/uaccess.h> 
#include <asm/io.h> // __raw_writel __raw_readl 函数,用来操作地址数据 
//懂得硬件的老大们,这里应该知道是要用些linux内核内部函数了 
//很多老大们省略了这些.h,不知道是为了节省,还是就不想让人知道在哪里找到函数原型 
//至少很多老大们的书,为了节省纸去掉了

#define LED_CFG __raw_writel((__raw_readl(S3C2440_GPJCON)

|(0xffff))&(0x5555),S3C2440_GPJCON)
//这个是2440的gpio的一个初始配置,具体的原理图上有 
//为了配置所有gpio口为输出 
//先取回16bits配置地址数据,再或(1111111111111111)与(101010101010101) 
//再写回16bits配置地址数据 
//gpio 16bits地址数据为输出数据 

#define WRITE_H(abc) __raw_writel(abc,S3C2440_GPJDAT) 

//给gpio 输出16bits数据 
MODULE_LICENSE("GPL"); //你自己的license GPL 的尊守 
#define major 235 //code 的节点号
static unsigned int code[]={0x11,0xd7,0x23,0x83,0xc5,0x89,

                                         0x09,0xd3,0x01,0x81};
//以下是 
//0x11 =0001 0001 这个是数码管显示0 第0 bits 4 bits 是高电屏led是灭的,

                             其它的都是底电屏亮 
//0xd7 =1101 0111 这个是数码管显示1 
//0x23 =0010 0011 这个是数码管显示2 
//0x83 =1000 0011 这个是数码管显示3 
//0xc5 =1100 0101 这个是数码管显示4 
//0x89 =1000 1001 这个是数码管显示5 
//0x09 =0000 1001 这个是数码管显示6 
//0xd3 =1101 0011 这个是数码管显示7 
//0x01 =0000 0001 这个是数码管显示8 
//0x81 =1000 0001 这个是数码管显示9
 




 


unsigned int olddat//用来保存原来的dat
int led_open(struct inode *inode,struct file *filp
      { 
            //一个空结构 
          return 0
      } 
int led_ioctl(struct inode *inode,struct file *filp,

                   unsigned int cmd,unsigned long arg
      { 
            //cmd 为在数码管要显示的数0-9 
        if((cmd>=0)&&(cmd<=9)) 
            { 
           WRITE_H(__raw_readl(S3C2440_GPJDAT)|0xFF);

                //关闭所有数码管显示 
                   //0xFF 1111 1111 
          WRITE_H(__raw_readl(S3C2440_GPJDAT)&code[cmd]); 
                      //将数码管数据写回,点亮数码管 
              return 0
            } 
        if(cmd==10
            { 
                    //如果cmd 为10 就将数码管关闭 
              WRITE_H(__raw_readl(S3C2440_GPJDAT)|0xFF);

                    //关闭所有数码管显示 
                    //0xFF 1111 1111 
              return 0
            } 
        if(cmd==11
            { 
                //cmd=11 是为了测试. 
             WRITE_H(__raw_readl(S3C2440_GPJDAT)|0xFF); 
             WRITE_H(__raw_readl(S3C2440_GPJDAT)&0xFE);
                //0xFE 1111 1110 
              return 0
             } 
        printk("ioctl error\nCommand 0-9"); 
        return -EFAULT
      } 

struct file_operations led_fops={ 
                    .owner = 
THIS_MODULE
                    .ioctl=
led_ioctl//生明ioctl起动led_ioctl函数 
                    .open=
led_open//生明ioctl起动led_open函数 
                                              }; 

struct led_dev_g 
      { 
        struct cdev devno
      } 
led_dev; //全局的节点结构体 
void led_cleanup_module(void
      { 
        dev_t devno=MKDEV(major,0); //创建节点号与内核关联 
        WRITE_H(__raw_readl(S3C2440_GPJDAT)|0xFF);

         //关闭所有数码管显示 
        WRITE_H(olddat); //还原写回老的数据 
        unregister_chrdev_region(devno,1); //撤销注册节点 
        printk("Stop Led ...\n"); 
       } 
int led_init_module(void
      { 
        int result
        dev_t dev=0
        printk("Start Led Mem......\n"); 
        olddat=__raw_readl(S3C2440_GPJDAT); //保存原始数据 
        LED_CFG//设置为GPIO输出格式 
        WRITE_H(__raw_readl(S3C2440_GPJDAT)|0xFF);

        //关闭所有数码管显示 
        dev=MKDEV(major,0); //创建节点号与内核关联 
        result=register_chrdev_region(dev,1,"qvb_led"); 

          //内核声明节点号 
        if(result<0
              { 
                  printk("can't major\n");
                  return result
              } 
        cdev_init(&led_dev.devno,&led_fops); //节点的初始化 
        led_dev.devno.owner=THIS_MODULE
        led_dev.devno.ops=&led_fops//节点文件指向 led_fops 
        result=cdev_add(&led_dev.devno,dev,1); //led_fops 联系 dev
        if(result
              { 
                  printk("Error not add"); 
                  led_cleanup_module(); 
                  return result
              } 
        return 0
      } 

module_init(led_init_module); 
module_exit(led_cleanup_module); 
//************************************************************************* 
应用程序使用该驱动 
使用命令 
insmod dataled.ko 
mknod /dev/qvbled c 235 0 
以下是应用程序 
//************************************************************************* 

#include <stdio.h> 
#include <fcntl.h> //文件描述控制函数库
int main(int argc,char *argv[]
    { 
        int fd
        int retval
        int cmd
        fd=open("/dev/qvbled",O_RDWR);
        if(fd==-1
              { 
                  perror("/dev/qvbled error"); 
                  exit(-1); 
              } 
        if(argc<2
              { 
                  printf("\nPlease: cmd 0-9 \n"); 
                  printf(" Led on\n"); 
                  printf("\nPlease: cmd off \n"); 
                  printf(" Led off\n"); 
                  exit(-1); 
              } 
        cmd=atoi(argv[1]); 
        if(cmd==11
              { 
                  retval=ioctl(fd,cmd,0); 
              } 
        if((cmd>=0)&&(cmd<=9)) 
              { 
                  retval=ioctl(fd,cmd,0); 
              } 
        if(!strcmp(argv[1],"off")) 
              { 
                  retval=ioctl(fd,10,0); 
              } 
        close(fd); 
        return 0
      } 
//***************************************************************************

  • 大小: 113.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics