[经验] [记录]ARM,linux开发控制硬件之还是那个LED

ywlzh   2016-7-23 23:43 楼主
搭载好了一个空的字符设备驱动程序,接下来就是填充对硬件的控制程序,查看自己板子的LED驱动程序例子,用的misc,混杂设备,现在不用那么深入(慢慢积累),提出其中对硬件控制的程序 #define LED_GPIO MXS_PIN_TO_GPIO(PINID_LCD_D23) //硬件引脚 gpio_request //这个函数是对GPIO口做初始化的函数,就像单片机引脚初始化一样 gpio_direction_output //这个函数是对GPIO输出高低电平做改变的函数 然后是添加进自己的字符设备驱动程序里,只做了write操作
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/types.h>
  4. #include <linux/sched.h>
  5. #include <linux/init.h>
  6. #include <linux/fs.h>
  7. #include <linux/ioctl.h>
  8. #include <linux/delay.h>
  9. #include <linux/bcd.h>
  10. #include <linux/capability.h>
  11. #include <linux/rtc.h>
  12. #include <linux/cdev.h>
  13. #include <linux/miscdevice.h>
  14. #include <linux/gpio.h>
  15. #include <../arch/arm/mach-mx28/mx28_pins.h>
  16. #define DEVICE_NAME "led" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */
  17. #define LED_GPIO MXS_PIN_TO_GPIO(PINID_LCD_D23) //硬件引脚
  18. static struct class *led_class;
  19. static struct class_device *led_class_devs;
  20. static int led_open(struct inode *inode, struct file *file)
  21. {
  22. printk("led open ok\n");
  23. gpio_request(LED_GPIO, "led");
  24. return 0;
  25. }
  26. static int led_release(struct inode *inode, struct file *filp)
  27. {
  28. gpio_free(LED_GPIO);
  29. return 0;
  30. }
  31. ssize_t led_write(struct file *filp, const char __user *buf, size_t count,
  32. loff_t *f_pos)
  33. {
  34. char data[2];
  35. copy_from_user(data, buf, count);
  36. gpio_direction_output(LED_GPIO, data[0]);
  37. printk("write data:%d \n",data[0]);
  38. return count;
  39. }
  40. static struct file_operations led_fops = {
  41. .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
  42. .open = led_open,
  43. .write = led_write,
  44. .release = led_release,
  45. };
  46. int major;
  47. static int __init led_init(void)
  48. {
  49. major = register_chrdev(0, DEVICE_NAME, &led_fops); //主设备号为0 就自动分配
  50. if (major < 0) {
  51. printk(" can't register major number\n");
  52. return major;
  53. }
  54. printk("register sucess /dev/led OK!\n");
  55. led_class = class_create(THIS_MODULE, DEVICE_NAME);
  56. if (IS_ERR(led_class))
  57. return PTR_ERR(led_class);
  58. led_class_devs = device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
  59. if (unlikely(IS_ERR(led_class_devs)))
  60. return PTR_ERR(led_class_devs);
  61. printk(DEVICE_NAME " initialized\n");
  62. return 0;
  63. }
  64. static void __exit led_exit(void)
  65. {
  66. unregister_chrdev(major, DEVICE_NAME);
  67. device_unregister(led_class_devs);
  68. class_destroy(led_class);
  69. printk(" led rmmod OK!\n");
  70. }
  71. module_init(led_init);
  72. module_exit(led_exit);
  73. MODULE_LICENSE("GPL");
内核写好了,是不是该写测试文件了,看着LCD屏还是触摸的,不来点交互怎么能行呢? 那就用QT来测试吧: 对内核写进 1 就是点亮灯 对内核写进 0 就是熄灭灯 我选择用QCommandLinkButton,个人感觉这个控件比QPushbutton要好看一些,就选择它了,按下一个点亮灯,按下另一个熄灭灯 具体程序如下:
  1. #include "mainwindow.h"
  2. MainWindow::MainWindow(QWidget *parent)
  3. : QMainWindow(parent)
  4. {
  5. fd = open("/dev/led", O_RDWR);
  6. ON = new QCommandLinkButton("open LED","",this);
  7. OFF = new QCommandLinkButton("close LED","",this);
  8. ON->setGeometry(10,10,100,30);
  9. OFF->setGeometry(10,40,100,30);
  10. connect(ON,SIGNAL(clicked()),this,SLOT(open_led()));
  11. connect(OFF,SIGNAL(clicked()),this,SLOT(close_led()));
  12. }
  13. MainWindow::~MainWindow()
  14. {
  15. }
  16. void MainWindow::open_led()
  17. {
  18. val = 0;
  19. write(fd, &val, 1);
  20. }
  21. void MainWindow::close_led()
  22. {
  23. val = 1;
  24. write(fd, &val, 1);
  25. }
然后是.h文件要包含对应的头文件
  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QtGui/QMainWindow>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <fcntl.h>
  10. #include <termios.h>
  11. #include <errno.h>
  12. #include <limits.h>
  13. #include <asm/ioctls.h>
  14. #include <time.h>
  15. #include <pthread.h>
  16. #include <QCommandLinkButton>
  17. class MainWindow : public QMainWindow
  18. {
  19. Q_OBJECT
  20. public:
  21. MainWindow(QWidget *parent = 0);
  22. ~MainWindow();
  23. QCommandLinkButton *ON;
  24. QCommandLinkButton *OFF;
  25. private:
  26. int fd;
  27. char val;
  28. private slots:
  29. void open_led();
  30. void close_led();
  31. };
  32. #endif // MAINWINDOW_H
经过编译 进入nfs目录 加载内核驱动文件,运行QT QQ图片20160723233333.png QQ图片20160723234123.jpg 点击"open LED",会发现左边的灯变亮 QQ图片20160723234117.jpg 点击“close LED” 会发现左边的灯会熄灭 QQ图片20160723234120.jpg 同时,终端也会打印出数据 QQ图片20160723234046.png 本帖最后由 ywlzh 于 2016-7-23 23:54 编辑
天地庄周马;江湖范蠡船。 个性签名还是放QQ号吧,2060347305,添加说明EEworld好友

回复评论 (2)

床底下的周公板还在吃灰……
点赞  2016-7-24 15:29
不错啊,我的ZLG 283也在吃灰,不知从何学起
点赞  2016-7-24 17:34
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复