Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1252782
  • 博文数量: 160
  • 博客积分: 4132
  • 博客等级: 中校
  • 技术积分: 2086
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-06 21:56
文章分类

全部博文(160)

文章存档

2012年(25)

2011年(120)

2010年(15)

分类: 嵌入式

2010-11-11 10:54:20

摘自:

忙忙碌碌有一天,终于实现自己想要的结果了,虽说是个普通的流水灯,但是也让我收获不小啊,对着原理图看了很长时间才找到自己想要的管脚的名字,晚上没什么事就写出来了,如有错误希望留言指正

#include
#include

#include
#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

#define LED_MAJOR 242                 

//主设备号,先用cat /proc/devices看看自己的板子上那个主设备号没用。

#define LED_NAME "my2440_leds"        //设备名称,可以起自己喜爱的名字

 

#define STOP     0

#define START    1

 

static unsigned long led_table [] = { 

 S3C2410_GPF0,

 S3C2410_GPF2,

 S3C2410_GPF4,

 S3C2410_GPF6,

 S3C2410_GPG1,

 S3C2410_GPG5,

 S3C2410_GPG7,

 S3C2410_GPG10,

};

 

static unsigned int led_cfg_table [] = { 

 S3C2410_GPF0_OUTP,

 S3C2410_GPF2_OUTP,

 S3C2410_GPF4_OUTP,

 S3C2410_GPF6_OUTP,

 S3C2410_GPG1_OUTP,

 S3C2410_GPG5_OUTP,

 S3C2410_GPG7_OUTP,

 S3C2410_GPG10_OUTP,

};

//上面是将管脚设置成普通的输出管脚,在Micro型板子上都是用..._GPIO_OUTP

//打开设备

static int led_open(struct inode *inode, struct file *file)

{

    //

   int i;

 for (i = 0; i < 8; i++)

   {

   s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

   s3c2410_gpio_setpin(led_table[i], 0);             

    }

     return 0;   

}

//关闭设备

static int led_close(struct inode *inode, struct file *file)

{

    return 0;

}

//对设备进行控制

 static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

 int i;

 if(cmd==STOP)

  {
               printk("led stop\n"); 

   for (i = 0;i < 8;i++)

    {               

     s3c2410_gpio_setpin(led_table[i], !cmd);

    }

   }

 else if  (cmd==START)
          {  
              printk("leds start\n"); 

   for (i = 0;i < 8;i++)

    {
                  s3c2410_gpio_setpin(led_table[i], !cmd);

      msleep(500);

    }

   for (i = 0;i < 8;i++)

    {                

     s3c2410_gpio_setpin(led_table[7-i],cmd);

     msleep(500);

    }

  }

 else

     return -EINVAL;

}

 

static struct file_operations led_fops = {

 

 .owner =   THIS_MODULE,

 .open   =  led_open,

       .release = led_close,

 .ioctl   = led_ioctl,

 

};

 

static int __init led_init(void)

{  
    int ret;

    ret = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);

    if(ret < 0)

    {

        printk(LED_NAME " register falid!\n");

    }

}

static void __exit led_exit(void)

{

    //注销设备

    unregister_chrdev(LED_MAJOR, LED_NAME);
    printk(LED_NAME " rmmodule\n");

}

 

module_init(led_init);

module_exit(led_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("gaofeng");

MODULE_DESCRIPTION("my2440 led driver");

驱动就这么多了,接下来就是编译了,还是用老方法吧,编译成模块吧,先将驱动程序移到内核的驱动代码

/mini2440/linux2.6.29/drivers/char下,编译Makefile,添加如下

obj-m += 8leds.o//我的驱动代码保存的文件名实8led.c的

然后退到linux2.6.29目录下,输入命令make modules

没有错误的话就会生成8leds.ko,将该目标代码下载到开发板上。接下来就是创建设备如口和加载模块了

“这里说点别的,可能有的人在编译成模块文件时碰到过这样的问题,就是mknod...和insmod...都没有错误,但是执行rmmod时却提示说模块文件不存在,并且执行lsmod时明明看到自己加载的模块处于live状态,我刚开始就是这样,刚开始还以为是自己的系统有问题了,偶然在一个论坛中看到是因为自己缺少一个文件夹执行mkdir /mkdir/modules/2.6.29.4.FriendlyARM将编译好的模块文件放到该文件夹里就不会有这种问题了”

下面是测试程序:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define STOP     0
#define START    1

static int tmp;
static int fd;

static void set_leds(void)
{
 ioctl(fd, tmp); 
}

int main(int argc, char **argv)
{
    //打开led设备
    fd = open("/dev/8ledtest", O_RDWR);
    if(fd < 0)
    {
        printf("Open LED Device Faild!\n");
        exit(1);
    }
    //提示用户输入一个参数来对led进行控制,0表示停止工作,1表示开始
    printf("please enter the cmd (0|1 is stop|Start):\n");
    scanf("%d", &tmp);
    while(1)
    {      
     fd_set rdfds;
     struct timeval tv;
     int ret;
     FD_ZERO(&rdfds);
     FD_SET(0, &rdfds);//0是标准输入的句柄(1是标准输出的句柄、2是错误的句柄)
     tv.tv_sec = 1;//设置timeout的值为1秒
     tv.tv_usec = 0;
     ret = select(1, &rdfds, NULL, NULL, &tv);
     if(ret < 0) perror("select");
     else if(ret == 0)
      {
      set_leds();
      }
     else
       {
      scanf("%d", &tmp);
      printf("cmd = %d\n", tmp);
       }
     if(tmp < 0)
        {
            break;
        }
    }
    //关闭设备
    close(fd);
    return 0;

}

因为想在程序运行起来之后还能从控制台输入控制信息,想了好长时间也没有想出一个好的方法,只好加了一个文件检测的select()函数,使测试程序写的有点长了。编译好后将测试程序下到板子上或是用mount命令都OK。

接下来需要自己焊个流水灯了,在流水灯负极最好焊个电阻,防止二极管被烧坏吗!焊好插到自己的板子上运行,就会看到流水的现象了。

下面是用QT编写的一个简单的图形界面

1.编写图形界面

打开QT 2.0,在里面进行编辑如下

将名字该为LEDBaseForm,因为在后面的程序中要把它当做是一个父类来继续的,所以此处的名字要和后面的.h文件中保持一致,保存成8led_base.ui格式的文件,因为下面的.h中要用。

2.编写.h文件
#ifndef MYHELLOFORM_H
#define MYHELLOFORM_H
#include "8led_base.h"//就是上面保存的.ui文件
#include

class MyLEDForm : public LEDBaseForm//要和前面的推行界面的名字保持一致
{
 Q_OBJECT
 
 public:
     MyLEDForm( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );//带默认参数的构造函数
     virtual ~MyLEDForm();
 private slots:
 void Onled();
 void Offled();
};

#endif // MYHELLOFORM_H

保存成8led.h后面的程序要用

3.编写mian.cpp文件

#include "8led.h"
#include

QTOPIA_ADD_APPLICATION("8ledtest",MyLEDForm)
QTOPIA_MAIN

4.编写8led.cpp

#include "8led.h"

#include

#include
#include

#include
#include
#include
#include
#include
#include
#include
#include

#include

#define LED_START   1
#define LED_STOP            0
int fd;


MyLEDForm::MyLEDForm( QWidget* parent, const char* name, WFlags fl)

     :LEDBaseForm(parent, name, fl)//要和前面建立的图形界面的名字保持一致

{    
   

    connect(PushButton1,SIGNAL(clicked()),this,SLOT(Onled()));

    connect(PushButton2,SIGNAL(clicked()),this,SLOT(Offled()));
 

}

 

MyLEDForm::~MyLEDForm(){}

 


void MyLEDForm::Onled()

{

    fd = ::open("/dev/8ledtest", 0);
    ::ioctl(fd, 1);

}
void MyLEDForm::Offled()

{

    fd = ::open("/dev/8ledtest", 0);
    ::ioctl(fd, 0);
    ::close(fd); // 关闭设备

}

5.接下来时.pro文件

CONFIG  += qtopiaapp
CONFIG  -= buildQuicklaunch

HEADERS = 8led.h
SOURCES = 8led.cpp

SOURCES+=main.cpp

INTERFACES = 8led_base.ui

desktop.files = 8led.desktop
desktop.path = /apps/gaof
INSTALLS += desktop

pics.files=pics/*
pics.path=/pics/gaof/qpelogo
PICS_INSTALLS+=pics

TARGET  = 8ledtest//生成的可执行程序

6.编写build文件

#!/bin/bash

source /opt/FriendlyARM/mini2440/arm-qtopia/qtopia-2.2.0-FriendlyARM/setQpeEnv
qmake -spec /opt/FriendlyARM/mini2440/arm-qtopia/qtopia-2.2.0-FriendlyARM/qtopia/mkspecs/qws/linux-arm-g++ -o Makefile *.pro

make clean
make

7.编写8leds.desktop

[Desktop Entry]
Comment=An Example Program
Exec=8ledtest
Icon=gaof/qpelogo

//需要先在opt/Qtopia/pics下建立一个自己的文件夹,我的当然就是gaof了将想要显示的图标放到里面
Type=gaof

//gaof是我自己建的最上层的图标,类似于友善的Games图标,具体的建立方法可以参考
Name=8led

9.上面的都做好后就可以运行./build生成可执行文件了。编译后将8led.desktop下载到开发办的/opt/Qtopia/apps/gaof目录里

将生成的可执行程序下载到/opt/Qtopia/bin里,这时通过图形界面上的ledstart和ledstop按钮就可以控制自己焊的流水灯的亮和灭了。

!!终于写完了,时间也差不多了,实验室要锁门了,写的有点仓促,如有错误,望指正!!

阅读(1569) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~