0 前言

代码链接:https://download.csdn.net/download/qq_55813245/85594338

资源 :imx6ull开发板

系统:正点原子出厂系统(Uboot 版本为 2016.03,内核版本为 4.1.15 ,根文件系统 rootfs为yocto。)

交叉编译:

应用程序:arm-linux-gnueabihf-gcc编译

驱动程序:对应的Makefile

QT应用程序:出厂系统的QT源码使用的arm-poky-linux-gnueabihf-gcc编译得到的,QT应用程序要用一样的编译器,在qt中设置对应的编译套件。

1 LED

1.2 LED驱动程序

基于新字符设备驱动,可以自动创建设备节点

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define LEDOFF 0
#define LEDON  1
#define LED_CNT 1 //设备号个数
#define LED_NAME "led" //名字
//寄存器物理地址
#define CCM_CCGR1_BASE           (0X020C406C)
#define SW_MUX_GPIO1_IO03_BASE   (0X020E0068)
#define SW_PAD_GPIO1_IO03_BASE   (0X020E02F4)#define GPIO1_DR_BASE           (0X0209C000)#define GPIO1_GDIR_BASE         (0X0209C004)//映射后的寄存器虚拟地址指针static void __iomem *IMX6U_CCM_CCGR1;static void __iomem *SW_MUX_GPIO1_IO03;static void __iomem *SW_PAD_GPIO1_IO03;static void __iomem *GPIO1_DR;static void __iomem *GPIO1_GDIR;// led设备结构体struct led_dev{dev_t devid; //设备号int major; //主设备号int minor;  //次设备号struct cdev cdev_led; //字符设备struct device *device;       //设备struct class *class;       //类         };struct led_dev led;       //led设备结构体static int led_open(struct inode *inode, struct file *filp){filp->private_data = &led;     //设置私有数据 return 0;}static ssize_t led_read(struct file *filp, char __user *buf,size_t cnt, loff_t *offt){return 0;}void delay_short(volatile unsigned int n){while(n--){while(0x7ff){}                 //在 396Mhz 的主频下延时时间大约为 1ms}}static ssize_t led_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt){     u32 val_set=0;int retvalue;unsigned char databuf[1];unsigned char ledstat;struct led_dev *dev = filp->private_data;retvalue = copy_from_user(databuf, buf, cnt);  //拷贝来自用户层的数据到databufif(retvalue < 0) {printk("kernel write failed!\r\n");return -EFAULT;}ledstat = databuf[0];   if(ledstat == LEDON) {val_set = readl(GPIO1_DR);val_set &= ~(1 << 3); writel(val_set, GPIO1_DR);                                //打开}    else if(ledstat == LEDOFF) {val_set = readl(GPIO1_DR);val_set |= (1 << 3); writel(val_set, GPIO1_DR);                               //关闭}return 0;                  }
static int led_release(struct inode *inode, struct file *filp){return 0;}
//设备操作函数
static struct file_operations led_fops = {.owner = THIS_MODULE,.open = led_open,.read = led_read,.write = led_write,.release = led_release,};
//设备的注册
static void __exit led_init(void){  //初始化ledu32 val=0;//1.获取映射后的寄存器地址IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4);GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);//2.使能时钟val=readl(IMX6U_CCM_CCGR1);val &=~(3<<26);  //清除以前的值val |= (3<<26);writel(val,IMX6U_CCM_CCGR1);//3. 设置复用功能和IO电气属性writel(5, SW_MUX_GPIO1_IO03);writel(0x10B0, SW_PAD_GPIO1_IO03);//4.设置 GPIO1_IO03 为输出功能val = readl(GPIO1_GDIR);val &=~(1<<3);  //清除以前的值val |= (1<<3);writel(val, GPIO1_GDIR);//5.默认关闭ledval = readl(GPIO1_DR);val |= (1 << 3);writel(val, GPIO1_DR);//led字符设备的注册//1.创建设备号led.major=0;  //设置为默认没有定义设备号,后面自动申请设备号alloc_chrdev_region(&led.devid,0,LED_CNT,LED_NAME);   //申请设备号led.major = MAJOR(led.devid); // 获取分配号的主设备号 led.minor = MINOR(led.devid); //获取分配号的次设备号 printk("led major=%d,minor=%d\r\n",led.major,led.minor);//2初始化 cdev_ledled.cdev_led.owner=THIS_MODULE;cdev_init(&led.cdev_led,&led_fops);//3.添加cedvcdev_add(&led.cdev_led,led.devid,LED_CNT);//4.自动创建设备节点-创建类led.class=class_create(THIS_MODULE,LED_NAME);if(IS_ERR(led.class)){return ;}else{}//创建设备led.device=device_create(led.class,NULL,led.devid,NULL,LED_NAME);if (IS_ERR(led.device)){return ; }else{printk("led驱动加载成功!\r\n");}return ;}//设备的注销
static void __exit led_exit(void)
{   //取消映射iounmap(IMX6U_CCM_CCGR1);iounmap(SW_MUX_GPIO1_IO03);iounmap(SW_PAD_GPIO1_IO03);iounmap(GPIO1_DR);iounmap(GPIO1_GDIR);cdev_del(&led.cdev_led);   //删除unregister_chrdev_region(led.devid,LED_CNT);  //注销device_destroy(led.class,led.devid);class_destroy(led.class);
}
// 驱动模块加载
module_init(led_init);
// 驱动模块卸载
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LED");

1.2 Makefile

KERNELDIR :=/home/zhw/linux/orign_code/linux-imx-4.1.15-2.1.0
CURRENT_PATH := $(shell pwd)
obj-m := led_mmu.o
build: kernel_modules
kernel_modules:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

利用tftp下载到开发板上,开发板,虚拟机,window三者在同一网段内

注意:

包含的头文件路径的内核源码目录版本一定与开发板使用的内核版本一样,且一定是用arm-linux-gnueabihf-交叉编译得到的内核源码。

1.3 C应用程序

if(argc != 3){printf("Error Usage!\r\n");return -1;}else{}filename = argv[1];//获取led设备对应的文件描述符fd = open(filename, O_RDWR);if(fd < 0){printf("file %s open failed!\r\n", argv[1]);return -1;}else{}//获取命令行的打开或者关闭databuf[0] = atoi(argv[2]);   //向/dev/led文件写入数据retvalue = write(fd, databuf, sizeof(databuf));if(retvalue < 0){printf("LED Control Failed!\r\n");close(fd);return -1;}else{}//关闭文件retvalue = close(fd); if(retvalue < 0){printf("file %s close failed!\r\n", argv[1]);return -1;}else{}return 0;}

利用arm-linux-gnueabihf-gcc ledApp.c -o ledApp 交叉编译器编译为可执行程序

实验:正点原子出厂系统红灯是Linux内核自带的 LED,挂在设备树上,默认打开的,首先要先将其关闭。

2 BEEP

Beep 基于设备树的pinctrl和gpio子系统

使用的出厂系统自带的设备树,所以pinctrl节点和gpio就不用自己添加了。

gpios属性是设置对应设备所使用的GPIO,如led就是gpio1的IO03,低电平有效。

蜂鸣器驱动程序是直接使用的正点原子的教程源码,基于设备树驱动的不同点在于,我们不用关心相应的寄存器使能驱动具体是怎么去实现的,这是非常底层的驱动,NXP已经帮我们写好了。只需要在设备树中配置好相应节点(pinctrl节点和gpio)就行了。后面还有更为分离的platform 设备驱动。

/* 设置BEEP所使用的GPIO *//* 1、获取设备节点:beep */beep.nd = of_find_node_by_path("/leds/beep");if(beep.nd == NULL) {printk("beep node not find!\r\n");return -EINVAL;} else {printk("beep node find!\r\n");}/* 2、 获取设备树中的gpio属性,得到BEEP所使用的BEEP编号 */beep.beep_gpio = of_get_named_gpio(beep.nd, "gpios", 0);if(beep.beep_gpio < 0) {printk("can't get beep-gpio");return -EINVAL;}printk("beeps-gpio num = %d\r\n", beep.beep_gpio);/* 3、设置GPIO5_IO01为输出,并且输出高电平,默认关闭BEEP */ret = gpio_direction_output(beep.beep_gpio, 1);printk("close beep\r\n");if(ret < 0) {printk("can't set gpio!\r\n");}

与led驱动不同之处在于,在注册字符设备前,这里是先获取beep在设备树中的设备节点,和beep使用的GPIO编号,最后再调用相应的gpio驱动函数使能相应寄存器。调用beep的应用程序说明加载的beep驱动是没有错误的。

3 QT程序

rcync远程部署调试,QT源码是来自于b站黑马QT视频的案例,与原本不同的是,这次的平台是基于ARM架构的linux系统,添加了led和beep控制程序。在开始游戏时,红灯亮;每一关卡胜利超时则蜂鸣器使能;回到其余界面蜂鸣器关闭。

3.1 LED控制程序

ledcontrol.h

#ifndef LEDCONTROL_H
#define LEDCONTROL_H
#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include<QObject>
class LedControl
{
public:LedControl();~LedControl();int fd;int ret;int  databuf[1];void open_file();void led_open();void led_off();
};
#endif // LEDCONTROL_H

ledcontrol.cpp

LedControl::LedControl()
{this->led_off();
}
void LedControl::led_open()
{this->open_file();this->databuf[0]=1;this->ret=write(fd,databuf,sizeof(databuf));if(this->ret<0){printf("LED Control Failed!\r\n");close(fd);return ;}close(fd);
}
void LedControl::led_off()
{this->open_file();this->databuf[0]=0;this->ret=write(fd,databuf,sizeof(databuf));if(this->ret<0){printf("LED Control Failed!\r\n");close(fd);return ;}close(fd);
}
void LedControl::open_file()
{this->fd=open("/dev/led", O_RDWR);if(fd<0){printf("can’t open!\n");return ;}
}LedControl::~LedControl()
{this->led_off();
}

3.2 beep控制程序

beep控制程序与led一样,打开文件路径不同。

3.3 led控制

 connect(startbtn,&MypushButton::clicked,this,[=](){//弹跳特效startbtn->zoom1(200,20);startbtn->zoom2(200,20);//延时进入开始场景QTimer::singleShot(500,this,[=](){led->led_open();this->hide();choose_scene->show();});});//监听选择关卡的返回connect(choose_scene,&ChooseLevelScene::chooseback,this,[=](){QTimer::singleShot(150,this,[=](){this->show();led->led_off();choose_scene->hide();});});
Mainscene::~Mainscene()
{delete this->led;led=NULL;delete ui;
}

在主界面点开始按钮后,红灯亮,进入选择关卡界面,返回到开始界面,红灯熄灭,且因为beep和led没有父对象,结束时要手动释放。

3.4 BEEP 控制

 //监听每个按钮的点击事件connect(menubtn,&MypushButton::clicked,this,[=](){//进入游戏场景PlayScene * play=new PlayScene(i+1);//play->setParent(this);不要依赖这个场景,场景消失,游戏界面也会this->hide();play->show();this->beep_flag=true;//蜂鸣器定时QTimer::singleShot(10000+(i+1)*(i+1)*5000,this,[=](){if(this->beep_flag){beep->beep_open();}});//胜利时,蜂鸣器定时无效connect(play,&PlayScene::winsignal,this,[=](){this->beep_flag=false;} );//监听游戏关卡的返回connect(play,&PlayScene::returnsignal,this,[=]()      {QTimer::singleShot(150,this,[=](){this->show();this->beep_flag=false;delete play;beep->beep_off();});});});

用一个状态表示选择页面的打开和关闭,打开时,蜂鸣器定时无效;在游戏程序中添加一个信号函数,在一定内时间胜利,告诉蜂鸣器定时无效;进入游戏界面,蜂鸣器开始定时,返回到选择界面,蜂鸣器关闭。

4 .程序界面效果

5 总结

利用远程调试可以正常运行,通过tftp下载到开发板上运行就会发生段错误,现在也还没找到问题;可以通过QFile直接对文件进行读写,后期可以lcd、触摸屏等驱动加载到自己移植的系统上,再进行可视化编程,可以在windows上编写一个服务端,接受来自开发板的信息等。

QT、linux驱动以及应用基础学习总结-基于IMX6ULL的翻金币游戏点灯以及蜂鸣器报警相关推荐

  1. 详细介绍Linux shell脚本系列基础学习(列表)

    本系列适合Linux初学者,属于Linux入门级教程,主要介绍了Shell的分类.语法格式以及脚本的使用和编写格式等. 不断更新中,是Shell学习的必读经典教程.现主要包含以下文章: Linux S ...

  2. 电子书 鸟哥的Linux私房菜 (基础学习篇 第三版).pdf

    <鸟哥的Linux私房菜 (基础学习篇 第三版)>是颇具知名度的Linux入门书<鸟哥的Linux私房菜:基础学习篇>的全新版,全面而详细地介绍了Linux操作系统. 全书分为 ...

  3. FPGA零基础学习:基于FPGA的多路选择器设计(附代码)

    FPGA零基础学习:基于FPGA的多路选择器设计(附代码) 大侠好,欢迎来到FPGA技术江湖.本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的& ...

  4. FPGA零基础学习:基于FPGA的二进制转BCD设计(附代码)

    FPGA零基础学习:基于FPGA的二进制转BCD设计(附代码) 本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的"傻瓜式"讲 ...

  5. C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(二)

    C#上位机基础学习_基于SOCKET实现与PLC服务器的TCP通信(二) 测试软件: TIA PORTAL V15.1 S7-PLCSIM ADVANCED V3.0 Visual Studio 20 ...

  6. linux系统怎样写单片机程序,单片机知识是Linux驱动开发的基础之一以及如何学单片机...

    这是arm裸机1期加强版第1课第2.3节课程的wiki文字版. 为什么没前途也要学习单片机? 因为它是个很好的入口. 学习单片机可以让我们抛开复杂的软件结构,先掌握硬件操作,如:看原理图.芯片手册.写 ...

  7. 鸟哥的Linux私房菜(基础学习,服务器架设)

    纪念下吧:2014年大连的第一场雪,12月1号,早上出门就看见漫天飘着雪花,其实,还是很漂亮的! 自学过Linux的同学应该对<鸟哥的Linux私房菜>不会陌生,鸟哥分成两个部分来写,第一 ...

  8. Linux驱动设计——硬件基础

    Linux 驱动设计之硬件基础 0.开篇说明 本片内容主要来源于宋宝华老师<Linux设备驱动开发> 1.处理器 目前主流的通用处理器(GPP)多采用SoC(片上系统)的芯片设计方法,集成 ...

  9. qt实战-翻金币游戏

    项目介绍 界面演示 规则说明 翻金币是一个简单的游戏,在翻金币场景中点击界面中的币可以进行翻转,翻转规则是币加其上下左右的币同时进行翻转(动画做了一些小延迟),胜利的条件是界面中全是金币. 实现步骤分 ...

最新文章

  1. 在CentOS 6.3 64bit上安装FTP服务器vsftpd 2.2.2
  2. 曲线学习PyQt5方案一
  3. python压缩包怎么安装-python – 如果安装的模块在zip文件的顶层添...
  4. 分数化小数(模拟除法操作)
  5. Python爬虫入门(1):综述
  6. C++中的类所占内存空间总结
  7. trados怎么导出html,【转】Trados 基本知识、使用技巧与经验
  8. idea conf文件_JavaWe商品项目保姆级解析IDEA版(配置篇)
  9. vue路由权限(结合服务端koa2)
  10. 赋值给集合_ArrayList集合源码
  11. DateFormat PHP Class (php 处理日期)
  12. isecure center 综合安防管理平台_企业综合安全管理平台
  13. Linux常用命令小结(一)
  14. android获取电池是否充电,Android 判断电池是否为充电状态的方法
  15. Java面试常见各种概念区别比较
  16. 计算机专业中专自我鉴定范文,计算机专业中专生自我鉴定范文
  17. 【优化预测】基于matlab差分进化算法优化BP神经网络预测【含Matlab源码 1315期】
  18. IOS平台车牌识别技术简介
  19. 红外遥控学习,万能遥控解决方案
  20. 创业公司系统安全的搭建

热门文章

  1. canvas制作图片选区的效果(Vue)
  2. 搜狗测试年终总结和测试总监luke春节寄语
  3. mysql创建外键语句
  4. 三角函数与缓入缓出动画及C#实现(图文讲解)
  5. hive与pig比较
  6. Android 报错:Unregister alarmreceiver to MqttServiceXXXX
  7. 某某程序员对加班的看法
  8. [训练7]输出连续的英文字母
  9. 摄像头分辨率怎么调整_监控摄像头怎么选购
  10. 找不到文件或程序集名称“xxx”,或找不到它的一个依赖项