微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > ARM技术讨论 > TQ210 LED驱动+流水灯(转)

TQ210 LED驱动+流水灯(转)

时间:10-02 整理:3721RD 点击:

TQ210 LED驱动及测试

1.      编写led驱动

1.1 在系统中创建目录/home/share/led/

#mkdir –p /home/share/led

进入led目录

#cd /home/share/led

1.2创建源码文件led_driver.c

#vim led_driver.c

源码内容见附件一。

保存退出.

1.3创建并编辑Makefile

在该目录下创建Makefile文件,将驱动程序编译成模块。

#vim Makefile

内容如下:

oj-m +=led_driver.o

CURRENT_PATH := /home/share/led

LINUX_KERNEL ?= /home/share/learning/linux-2.6.35

#LINUX_KERNEL_PATH := $(LINUX_KERNEL)

default:

         $(MAKE) -C $(LINUX_KERNEL) m=$(CURRENT_PATH) modules

clean:

         $(MAKE) -C $(LINUX_KERNEL) M=$(CURRENT_PATH) clean

2.      编译

TQ210使用天嵌提供交叉编译器,路径:/home/share/tmp/opt/EmbedSky/4.4.6/bin

在该目录下直接make即可

#make

3. 测试led驱动

测试代码:见附件二

使用交叉编译工具编译程序:

# arm-linux-gcc -o led_test led_test.c

将生成的可执行程序led_test复制到nfs文件系统/home/share/nfsboot/rootfs中/mnt目录下;

在超级终端上控制开发板。

挂载好nfs文件系统:

#mount –t nfs 10.10.84.41:/home/share/nfsboot/rootfs –o nolock /mnt

进入挂载在/mnt 目录下的nfs文件系统内并且进入内部/mnt目录下:

#cd /mnt   //此目录是开发版的子目录

#cd /mnt   //此目录是挂载的宿主机上的nfs文件系统的子目录

执行可执行文件:

# ./led_test

出现段错误提示,原因参数不正确,还需要输入led的序号,以及开关指令。测试程序没有做好参数检查,所以会段错误在代码中对argc进行判断即可。

#./led_test   2       on     //打开第二个led

#./led_test      2       off       //关掉第二个led

开发板上两个LED灯均能正确控制,至此led驱动及测试代码试验完成。

附件一led驱动源码

/***********************************************************************************

* drivers/char/tq210_leds.c

* 功能简要:

*       该驱动注册一个字符设备“/dev/led”, 用于2个LED。

* 函数简介:

*       static void tq210_debug_leds(unsigned int cmd,unsigned long arg),用于内核驱动调试

* 提供的外部接口:

*       ioctol(struct inode *inode,struct file *file,unsigned int brightness);

*       用于LED的亮,灭。

* 调用实例:

*       提供控制台,命令式的测试程序。

*

*************************************************************************************/

#include <linux/miscdevice.h>

#include <linux/input.h>

#include <linux/clk.h>

#include <linux/delay.h>

#include <asm/io.h>

#include <asm/uaccess.h>

#include <mach/map.h>

#include <mach/gpio.h>

//#include <mach/gpio-bank.h>

#include <mach/regs-gpio.h>

#include <plat/gpio-core.h>

#include <plat/gpio-cfg.h>

#include <plat/gpio-cfg-helpers.h>

#define DEVICE_NAME "led"

/* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */

/*the second parameter that application program execute*/

#define IOCTL_GPIO_ON         1

#define IOCTL_GPIO_OFF        0

/* 用来指定LED所用的GPIO引脚 */

/*appoint the pin the LED will use*/

static unsigned long gpio_table [] =

{

         S5PV210_GPC0(3),

         S5PV210_GPC0(4),

};

/* 用来指定GPIO引脚的功能:输出 */

/*appoint the function of the pin:out put*/

static unsigned int gpio_cfg_table [] =

{

         S3C_GPIO_SFN(1),

         S3C_GPIO_SFN(1),

};

//static char gpio_name[][]={{"GPC0_3"},{"GPC0_4"}};

#ifdef CONFIG_TQ210_DEBUG_LEDS

static void tq210_debug_leds(unsigned int cmd,unsigned long arg)

{

         gpio_direction_output(gpio_table[arg], cmd);

         //s3c_gpio_setpin(gpio_table[arg], cmd);

}

static void toggle_led(unsigned int cmd,unsigned long arg)

{

         int loop=0;

         printk("%s : led %ld toggle now: \n",__func__,arg);

         for(;loop<11;loop++)

         {        cmd = loop%2;

                  printk("leds %d %s \n",arg+1,(cmd)?"on":"o   ff");

                   tq210_debug_leds(cmd,arg);

                   mdelay(1000);

         }

}

#endif

/**

*函数功能:打开/dev/led设备,设备名是:/dev/led

*fuction:open /dev/led device ,devce name: /dev/led

**/

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

{

         int i;

         int err;

         err = gpio_request(gpio_table[0], "GPC0_3");

         if(err)

         {

                   printk(KERN_ERR "failed to request GPC0_3 for LVDS PWDN pin\n");

        return err;

         }

         err = gpio_request(gpio_table[1], "GPC0_4");

         if(err)

         {

                   printk(KERN_ERR "failed to request GPC0_4 for LVDS PWDN pin\n");

        return err;

         }

         printk(KERN_INFO " leds opened\n");

         for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)

         {

                   s3c_gpio_cfgpin(gpio_table, gpio_cfg_table);

                   gpio_direction_output(gpio_table, 0);

                   //s3c_gpio_setpin(gpio_table, 0);

         }

#ifdef CONFIG_TQ210_DEBUG_LEDS

         for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)

         {

                   toggle_led(1,i);

         }

#endif

         return 0;

}

/**

*函数功能:用于控制led的亮灭

*fuction:control the led /turn on & turn off

*控制字为cmd,arg为控制哪个灯的亮灭取值范围为0-1:cmd为IOCTL_GPIO_ON时亮,cmd为IOCTL_GPIO_OFF为灭

*control byte is cmd; arg appointed which led wile be turn on or off,it can be 0 and 1;IOCTL_GPIO_ON:turn on,IOCTL_GPIO_OFF:turn off.

**/

static long tq210_gpio_ioctl(

         struct inode *inode,

         struct file *file,

         unsigned int cmd,

         unsigned long arg)

{

         arg -= 1;

         if (arg > sizeof(gpio_table)/sizeof(unsigned long))

         {

                   return -EINVAL;

         }

         switch(cmd)

         {

                   case IOCTL_GPIO_ON:

                            // 设置指定引脚的输出电平为1

                            gpio_direction_output(gpio_table[arg], 1);

                            //s3c_gpio_setpin(gpio_table[arg], 1);

                            return 0;

                   case IOCTL_GPIO_OFF:

                            // 设置指定引脚的输出电平为0

                            gpio_direction_output(gpio_table[arg], 0);

                            //s3c_gpio_setpin(gpio_table[arg], 0);

                            return 0;

                   default:

                            return -EINVAL;

         }

}

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

{

         gpio_free(gpio_table[0]);

         gpio_free(gpio_table[1]);

         printk(KERN_INFO "TQ210 LEDs driver successfully close\n");

         return 0;

}

/*驱动接口设置*/

/*setting the interface of the driver*/

static struct file_operations dev_fops = {

         .owner     =       THIS_MODULE,

         .ioctl         =       tq210_gpio_ioctl,

         .open =   tq210_gpio_open,

         .release =        tq210_gpio_close,

};

/*设备结构的设置*/

/*setting the architecture of the device*/

static struct miscdevice misc = {

         .minor = MISC_DYNAMIC_MINOR,

         .name = DEVICE_NAME,

         .fops = &dev_fops,

};

/*初始化设备,配置对应的IO,以及注册设备*/

/*init the device, config the right IO and register the device*/

static int __init dev_init(void)

{

         int ret;

         int i;

         int err;

         #ifdef CONFIG_TQ210_DEBUG_LEDS

         err = gpio_request(gpio_table[0], "GPC0_3");

         if(err)

         {

                   printk(KERN_ERR "failed to request GPC0_3 for LVDS PWDN pin\n");

        return err;

         }

         err = gpio_request(gpio_table[1], "GPC0_4");

         if(err)

         {

                   printk(KERN_ERR "failed to request GPC0_4 for LVDS PWDN pin\n");

        return err;

         }

         for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)

         {

                   //gpio_request(gpio_table[0],gpio_name);

                   s3c_gpio_cfgpin(gpio_table, gpio_cfg_table);//配置管脚为输出config the pin to out put

                   gpio_direction_output(gpio_table, 0);

                   //s3c_gpio_setpin(gpio_table, 0);//设置管脚为低电平config the pin to low level

                   s3c_gpio_setpull(gpio_table, S3C_GPIO_PULL_NONE);

         }

         #endif

         ret = misc_register(&misc);

         printk(KERN_INFO "TQ210 LEDs driver successfully probed\n");

         #ifdef CONFIG_TQ210_DEBUG_LEDS

         for (i = 0; i < sizeof(gpio_table)/sizeof(unsigned long); i++)

         {

                   toggle_led(1,i);

         }

         #endif

         return ret;

}

/*注销设备*/

/*log out the device*/

static void __exit dev_exit(void)

{

         misc_deregister(&misc);

         gpio_free(gpio_table[0]);

         gpio_free(gpio_table[1]);

         printk(KERN_INFO "TQ210 LEDs driver successfully exit\n");

}

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("www.embedsky.com");

MODULE_DESCRIPTION("LEDS' Driver");

附件二 led测试源码

/*FILENAME:led_test.c

*AUTHOR:Michael Li

*DATE:2013-06-03

*DESCRIPTION:the test of the led driver

* */

#include<stdio.h>

#include<fcntl.h>

#define DEVICENAME "/dev/led"

#define IOCTL_LED_ON 1

#define IOCTL_LED_OFF 0

int main(int argc, char **argv)

{

    FILE *fd;

    int led_no = 0;

    fd = (FILE *)open(DEVICENAME,0);

         if(argc < 3)

         {

                   printf("The arguments you input are wrong\n");

                   printf("USE:\n");

                   printf("\t\t./program\tled-number\ton/off\n");

                   return -1;

         }

    //led_no = strtoul(argv[1],0,0) -1;//its wrong to set like this

         led_no = strtoul(argv[1],0,0);//operate the led_1 by input 1 and led_2 by input 2

    printf("111111\n");

    if(!strcmp(argv[2],"on"))//turn on the led

    {

        ioctl(fd,IOCTL_LED_ON,led_no);

                   printf("you want the %d on\n",led_no);

    }

    else if(!strcmp(argv[2],"off"))//turn off the led

    {

        ioctl(fd,IOCTL_LED_OFF,led_no);   

    }

    else printf("error!\n");

    return 0;

}

附件三:流水灯

/*FILENAME:led_test.c

*AUTHOR:Michael Li

*DATE:2013-06-03

*DESCRIPTION:the test of the led driver,please refer to the label "usage:" below.

* */

#include<stdio.h>

#include<fcntl.h>

#include <signal.h>

//#include <time.h>

#include <sys/time.h>

#define DEVICENAME "/dev/led"

#define IOCTL_LED_ON 1

#define IOCTL_LED_OFF 0

void sigoutime();

void timer_init();

void delay(int time);

int time_1= 0;

int main(int argc, char **argv)

{

    FILE *fd;

    int led_no = 0;

         int i = 0;

    fd = (FILE *)open(DEVICENAME,0);

    int delay_grade = 0;

         timer_init();

usage:     

         if(argc < 3)

         {

                   printf("The arguments you input are wrong\n");

                   printf("USE:\n");

                   printf("\t./program\t<right/left/both>\t<1/2/3>\n");

                   printf("\t3:slow;2:faster;1:fastest\n");

                   printf("\teg: ./led_flow\tleft\t1\n\tlet the led light start from left and the speed is the fastest\n");

                   return -1;

         }

        

         if(!strcmp(argv[2],"1"))

         delay_grade = 1;//20ms

         else if (!(argv[2],"2"))

         delay_grade = 15;//300ms

         else if(!(argv[2],"3"))

         delay_grade = 50;//1s

         else

                   delay_grade = 30;//600ms

                  

    if(!strcmp(argv[1],"left"))//turn on the led

    {

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

                   {

                            if((i%2)!=0)

                            {

                                     led_no = 1;

                            }

                            else

                                     led_no = 2;

                            ioctl(fd,IOCTL_LED_ON,led_no);

                            printf("you want the %d on\n",led_no);

                            delay(delay_grade);

                            ioctl(fd,IOCTL_LED_OFF,led_no);

                   }

    }

    else if(!strcmp(argv[1],"right"))//turn off the led

    {

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

                   {

                            if((i%2)==0)

                            {

                                     led_no = 1;

                            }

                            else

                                     led_no = 2;

                            ioctl(fd,IOCTL_LED_ON,led_no);

                            delay(delay_grade);

                            ioctl(fd,IOCTL_LED_OFF,led_no);

                   }

         }

         else if(!strcmp(argv[1]),"both")

         {

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

                   {

                            ioctl(fd,IOCTL_LED_ON,1);

                            ioctl(fd,IOCTL_LED_ON,2);

                            delay(delay_grade);//delay 0.8s

                            ioctl(fd,IOCTL_LED_OFF,1);

                            ioctl(fd,IOCTL_LED_OFF,2);

                            delay(delay_grade);//delay 0.8s

                   }

         }

    else printf("error!\n");

         close(fd);

    return 0;

}

void delay(int time)

{

         while(time_1<time);

         time_1 = 0; //you must clean the time_1 every time you sign a time

         return;

}

void timer_init() //内核定时器初始化函数

{

         struct itimerval value; //(1)定义类型为itimerval的结构体变量

         signal(SIGALRM, sigoutime);//注册信号的处理函数            

         value.it_value.tv_sec = 0;//秒——设置第一次运行sigroutine函数时间

         value.it_value.tv_usec = 100000;//微妙——设置为0

         value.it_interval.tv_sec = 0;//秒——设置间隔运行sigroutine函数的时间(实际定时)

         value.it_interval.tv_usec = 20000;//微妙———设置为20ms

         setitimer(ITIMER_REAL, &value, NULL); //(2)设置 “真实计时器“参数

}

void sigoutime()

{  

         time_1++;

         return;

}


不错,应该赞一个

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top