[番外篇]直流电机桥源码分析&LED驱动例程开发

  • 直流电机桥测试代码分析
  • 直流电机桥驱动代码分析
  • 仿写HBLED驱动程序
    • 利用芯片手册修改设备树
    • 利用原理图寻找引脚
    • 仿写代码
  • 仿写HBLED测试程序
  • 实际测试

直流电机桥测试代码分析

#define DCM_IOCTRL_SETPWM    (0x10)
#define DCM_IOCTRL_STATUS   (0x20)
#define DCM_IOCTRL_STOP     (0x30)
#define DCM_IOCTRL_START    (0x40)

定义了对设备的操作命令,类似于枚举类型。在驱动中也同样有所定义。

char *DCM_DEV="/dev/DCMotor";

声明了设备在系统中注册的名字,和驱动要一一对应,在系统中设备统一放在/dev/文件夹下面。

ioctl(dcm_fd, cmd, arg);

调用驱动中定义的函数,对设备进行操作,dcm_fd是设备的节点,cmd是之前定义过操作的类型,arg是对应的参数。

如果仔细阅读,还会发现在主函数中定义的status变量从来没有使用,可以删除。

直流电机桥驱动代码分析

module_init(uptech_dcm_init);
module_exit(uptech_dcm_exit);

在字符型驱动开发中,我们已经讲过,上面两个函数分别是加载驱动和卸载驱动所执行的函数。

#define DEVICE_NAME     "DCMotor"
#define DEV_MAJOR        0

驱动中同样定义了设备名称,DEV_MAJOR用于模块被加载时初始化函数调用的创建节点函数,为0表示自动获取设备号。

pwm_request(0, "my_pwm0");
pwm_config(pwm0, 10000000, 100000000);
pwm_disable(pwm0);
pwm_enable(pwm0);

pwm在linux中提供了很多api,pwm_request是申请pwm设备,第一个参数是i.MX6内置的pwmID号,从0到3一共4个,第二个参数是对此设备的简称。

pwm_config是配置pwm设备,第一个参数是pwm设备,第二个参数是一个周期内,高电平的时间,单位是纳秒,第三个参数是周期的长度,单位也是纳秒,在本例中,pwm0对应的引脚将以100000000纳秒为周期,其中前10000000纳秒为高电平,剩余时间都为低电平,对于电机来说,高电平转,低电平不转,但是由于惯性,电机仍有旋转趋势,控制占空比(高电平占周期的时间比)即可控制转速,占空比越大,转速越快。

pwm_disable是关闭pwm设备,停止pwm信号的作用,相反,pwm_enable是使能pwm设备,开始pwm信号,两个函数的参数都是pwm设备。

仿写HBLED驱动程序

为了不和直流电机桥已有的引脚冲突,我们选择pwmID为2的设备作为LED的Signal引脚。HBLED的性能如下。

  1. 需要5V或3.3V供电。
  2. 需要GND引脚接地。
  3. Signal引脚高电平时灯亮,低电平时灯灭。

利用芯片手册修改设备树

接下来我们打开i.MX6的芯片手册,位于/01 创新创客智能硬件平台光盘资料/创新创客智能硬件平台光盘V1.0/04_硬件/0401_数据手册/13_Cortex-A 系列核心板/IMX6/IMX6SDLRM.pdf,搜索pwm3(芯片手册中定义id为1到4,在linux中申请的id为0到3)。


可以看见SW_PAD_CTL_PAD_SD1_DAT1引脚可以用于PWM3_OUT功能。

接下来修改设备树,在虚拟机终端中输入sudo nano /home/uptech/fsl-6dl-source/kernel-3.14.28/arch/arm/boot/dts/imx6qdl-sabresd.dtsi

发现此引脚已经被复用为GPIO,将此引脚注释掉。


找到后面定义pwm引脚复用的地方,在后面添加以下代码。

pinctrl_pwm3: pwm3grp {fsl,pins = <MX6QDL_PAD_SD1_DAT1__PWM3_OUT           0x1b0b1>;
};


找到pwm定义的位置,在后面添加pwm3的定义。

&pwm3 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_pwm3>;status = "okay";
};


如果读者想深入了解0x1b0b1、MX6QDL_PAD_SD1_DAT1__PWM3_OUT等写法的原因,可以前往文件资料中/01 创新创客智能硬件平台光盘资料/创新创客智能硬件平台光盘V1.0/03_系统/0301_Linux/03_linux系统移植/01_doc/03_i.MX6-魔法师inux系统实验指导书V2.2.pdf的第四章继续学习。简单来说前者是引脚复用寄存器的配置,可以在芯片手册中查到,后者是引脚复用后的专用名称,可以在pinfunc.h中找到。

修改完设备树需要重新编译内核和设备树文件,然后重新烧录系统。

利用原理图寻找引脚

打开文件资料中/01 创新创客智能硬件平台光盘资料/创新创客智能硬件平台光盘V1.0/04_硬件/0402_原理图/12_Cortex-A 系列核心板与底板 文件夹内的i.MX6 核心板 V1.2.pdf和魔法师Cortex-A系列底板 V1.3.pdf。

在核心板的原理图中搜索SD1_DAT1,可以看到SD1_DAT1对应的是CSI0 RST B。

打开底板原理图,搜索CSI0 RST B,可以看到对应了J5端口的20号引脚,说明我们LED的signal需要插在此引脚上。

仿写代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/pwm.h>
#include <linux/fs.h>#define DEVICE_NAME     "HBLED"
#define DEV_MAJOR        0#define DRIVER_AUTHOR "sertonry@obcube.cn"
#define DRIVER_DESCRIPTION "Unknown_HighBrightnessLED"#define HBLED_IOCTRL_SETPWM (0x10)
#define HBLED_IOCTRL_OFF    (0x20)
#define HBLED_IOCTRL_ON     (0x30)static struct cdev hbLEDcDev;
struct class* hbLEDclass;
dev_t devNo;struct pwm_device* pwm;
static int defaultPWMRate = 50;static long HBLED_ioctl(struct file* filp, unsigned int cmd, unsigned long arg)
{switch (cmd) {case HBLED_IOCTRL_SETPWM:if (arg > 100 || arg < 0){printk("HBLED_IOCTRL_SETPWM arg can't is %ld!\n", arg);break;}pwm_enable(pwm);pwm_config(pwm, 20000 * arg, 2000000);break;case HBLED_IOCTRL_OFF:pwm_config(pwm, 20000 * 0, 2000000);pwm_disable(pwm);break;case HBLED_IOCTRL_ON:pwm_enable(pwm);break;}return 0;
}static struct file_operations HBLED_gpio_fops = {.owner = THIS_MODULE,.unlocked_ioctl = HBLED_ioctl,
};static int create_dev_node(void)
{int ret;if (DEV_MAJOR){devNo = MKDEV(DEV_MAJOR, 0);ret = register_chrdev_region(devNo, 1, DEVICE_NAME);}else {ret = alloc_chrdev_region(&devNo, 0, 1, DEVICE_NAME);}if (0 < ret) {return ret;}cdev_init(&hbLEDcDev, &HBLED_gpio_fops);ret = cdev_add(&hbLEDcDev, devNo, 1);if (ret) {printk("cdev_add(); failed! ret_num=%d\n", ret);}hbLEDclass = class_create(THIS_MODULE, DEVICE_NAME);if (IS_ERR(hbLEDclass)) {printk("Err: failed in creating class.\n");return -1;}device_create(hbLEDclass, NULL, devNo, NULL, DEVICE_NAME);return 0;
}int __init HBLED_init(void)
{int ret;pwm = pwm_request(2, "hbLEDpwm");       if (IS_ERR(pwm)) {printk("ERROR is %ld\n", PTR_ERR(pwm));return -1;}pwm_config(pwm, 20000 * defaultPWMRate, 2000000);ret = create_dev_node();if (ret)return ret;return 0;
}void __exit HBLED_exit(void)
{pwm_disable(pwm);               pwm_free(pwm);                  cdev_del(&hbLEDcDev);device_destroy(hbLEDclass, devNo);class_destroy(hbLEDclass);unregister_chrdev_region(devNo, 1);
}
module_init(HBLED_init);
module_exit(HBLED_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);

对应的Makefile文件如下

obj-m    :=HighBrightnessLED_driver.oKERNELDIR := /home/uptech/fsl-6dl-source/kernel-3.14.28/
PWD := $(shell pwd)all:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:$(MAKE) -C $(KERNELDIR) M=$(PWD) clean

仿写HBLED测试程序

#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>#define HBLED_IOCTRL_SETPWM (0x10)
#define HBLED_IOCTRL_OFF    (0x20)
#define HBLED_IOCTRL_ON     (0x30)char* HBLED_DEV = "/dev/HBLED";
int cmd_group[] = { HBLED_IOCTRL_SETPWM, HBLED_IOCTRL_ON, HBLED_IOCTRL_OFF };void print_menu()
{printf("-----HBLED_TEST-----\n");printf("|   1.SETPWM      |\n");printf("|   2.ON          |\n");printf("|   3.OFF         |\n");printf("|   4.EXIT        |\n");printf("-------------------\n");
}int main(void)
{int hbled_fd, menu_num, cmd, arg;hbled_fd = open(HBLED_DEV, O_WRONLY);            if (hbled_fd < 0) {printf("Error opening %s device\n", HBLED_DEV);return 1;}while (1){print_menu();scanf("%d", &menu_num);if (menu_num == 4)break;if (menu_num == 1){printf("Input brightness value(0~100)\n");scanf("%d", &arg);if (arg > 100 || arg < 0){printf("Brightness can't be %ld!\n", arg);continue;}}cmd = cmd_group[menu_num - 1];ioctl(hbled_fd, cmd, arg);}close(hbled_fd);                      return 0;
}

对应的Makefile文件如下

CC = arm-poky-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/opt/poky/1.7/sysroots/cortexa9hf-vfp-neon-poky-linux-gnueabi
TARGET = HighBrightnessLED_test
all:$(CC) -o $(TARGET) $(TARGET).c
clean:rm $(TARGET)

实际测试


亮度为0

亮度为5%

亮度为50%

亮度为100%

番外篇——直流电机桥源码分析LED驱动例程开发相关推荐

  1. 【梅哥的Ring0湿润插入教程】【番外篇四】抓取盛大GPK驱动保护文件及简略逆向...

    [梅哥的Ring0湿润插入教程] Email:mlkui@163.com 转载请注明出处,谢绝喷子记者等,如引起各类不适请自觉滚J8蛋! 番外篇四:抓取盛大GPK驱动保护文件及简略逆向 [湿润前言] ...

  2. SRS流媒体服务器架构设计及源码分析丨音视频开发丨C/C++音视频丨Android开发丨嵌入式开发

    SRS流媒体服务器架构设计及源码分析 1.SRS流媒体服务器架构设计 2.协程-连接之间的关系 3.推流-转发-拉流之间的关系 4.如何手把手调试SRS源码 视频讲解如下,点击观看: SRS流媒体服务 ...

  3. Java集合篇:LinkedList源码分析

    (注:本文内容基于JDK1.6) 一.概述: LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口 ...

  4. Binder源码分析之驱动层(原)

    前言 在< Binder源码分析之ServiceManager >一文中我们介绍了利用Binder进行通讯的流程,即ServiceManager把自己注册为"管理员"之 ...

  5. spring boot实战(第九篇)Application创建源码分析

    前言 通过前面的文章了解到在spring boot的启动时,利用的是编写的Application类,使用了注解@SpringBootApplication,本篇将阐述该Bean的加载过程. [html ...

  6. React Native 启动速度优化——Native 篇(内含源码分析)

    Web 开发有一个经典问题:「浏览器中从输入 URL 到页面渲染的这个过程中都发生了什么?」 据我考据这个问题起码有十年历史了.在日新月异学不动的前端圈子里,这个问题能一直被问,就是因为因为它是个非常 ...

  7. 源码篇:ReentrantLock 源码分析上篇

    文章目录 引言 整体结构 公平锁和非公平锁的差异 非公平锁 NonfairSync acquire,锁获取流程 tryAcquire(1) addWaiter 入队流程 acquireQueued 排 ...

  8. pixhawk 源码分析-SPI驱动-MS5611

    最近学习了一下SPI的驱动软件,在此将其进行总结. 本文使用的代码为pixhawk 1.5.5版本的源码 源码下载地址 第一步函数入口: 老规矩,所有px4的代码的函数入口都是在启动脚本中,启动脚本地 ...

  9. Android源码分析 - Framework层的Binder(客户端篇)

    开篇 本篇以aosp分支android-11.0.0_r25作为基础解析 我们在之前的文章中,从驱动层面分析了Binder是怎样工作的,但Binder驱动只涉及传输部分,待传输对象是怎么产生的呢,这就 ...

最新文章

  1. php显示页面查询次数和耗时,wordpress显示页面查询次数、页面执行时间
  2. 【抠图中的注意力机制】HAttMatting---让抠图变得如此简单!
  3. Linux笔记(更改权限chmod,更改所有组chown,umask,隐藏权限chattr)
  4. TensorFlow深度学习实战---循环神经网络
  5. mini2440使用jlink烧写superboot到norflash
  6. FM,FFM及其实现
  7. python偶数列表_使用条件偶数列表创建带有地图的元组 - python
  8. PaddleOCR-release-2.3\deploy\cpp_infer\src识别中文时出现乱码
  9. Safari、IE8、iPhone和BlackBerry在Pwn2Own竞赛中被挑落
  10. QML Text 文字元素
  11. 防DDoS攻击,你知道自己和其他大型运营商的区别在哪里吗?
  12. 程序员在技术之外,还要掌握一个技能——自我营销能力
  13. 刷题-洛谷-P1179 数字统计
  14. 如何应对大数据分析工程师面试Spark考察,看这一篇就够了
  15. Windows10安装Internet Information Services(IIS)管理器
  16. 如何解决SQL Server 2008 无法连接到(local)(服务器名称)
  17. SQL Server链接服务器的使用
  18. Kubernetes 部署策略
  19. Mac常备必用的软件-mac软件推荐
  20. java ui界面美观,JavaFX实现UI美观效果代码实例

热门文章

  1. 位运算:找出唯一成对的数、找出落单的数
  2. 一文足矣——动态规划经典之Floyd(弗洛伊德)算法
  3. 通达OA 谈谈我们公司应用通达OA工作流
  4. linux 开发板相关命令
  5. android 嘶嘶 录音 电流音_教你如何轻松解决拾音器的“电流声”
  6. 西邮linux小组面试题总结(2016-5-30)
  7. 三星android9更快么,三星S9将会成为最快Android手机 有6大要点你必须知道
  8. XML——XML解析之DOM
  9. notion函数_高效工作必备,手把手教你玩转 Notion 模板(附下载)
  10. Tomcat #无法启动8005端口