当前位置: 首页 > news >正文

【IMX6ULL驱动开发学习】21.Linux驱动之PWM子系统(以SG90舵机为例)

1.设备树部分

首先在 imx6ull.dtsi 文件中已经帮我们定义好了一些pwm的设备树节点,这里以pwm2为例

pwm2: pwm@02084000 {compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";reg = <0x02084000 0x4000>;interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_DUMMY>,<&clks IMX6UL_CLK_DUMMY>;clock-names = "ipg", "per";#pwm-cells = <2>;
};

我们要在设备树(.dts)文件中引用和使能该节点,同时指定好pwm映射到的GPIO引脚(即pinctrl子系统,我这里映射到了GPIO1_9上)

&iomuxc {pinctrl-names = "default";pinctrl-0 = <&pinctrl_hog_1>;imx6ul-evk {............/* SG90 PWM2 GPIO1_IO09 */pinctrl_pwm2: pwm2grp {fsl,pins = <MX6UL_PAD_GPIO1_IO09__PWM2_OUT   0x110b0>;};............
}......
......&pwm2 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_pwm2>;clocks = <&clks IMX6UL_CLK_PWM2>,<&clks IMX6UL_CLK_PWM2>;status = "okay";
};

使用pwm 只需要在设备树节点中添加两条属性信息,如下所示

pwms = <&PWMn id period_ns>;
pwm-names = "name";
  • pwms :属性是必须的,它共有三个属性值

  • &PWMn 指定使用哪个pwm,在imx6ull.dtsi文件中定义,总共有8个可选;

  • id :pwm的id通常设置为0。

  • period_ns :用于设置周期。单位是ns。

  • pwm-names :定义pwm设备名字。(可以不设置)

最后在根节点下添加自己定义的节点

hc_sg90 {compatible    =  "hc-sg90";pwms = <&pwm2 0 20000000>;    /* 使用pwm1  id为0   周期为20000000ns = 20ms */status 		  =  "okay";
};

2.驱动代码部分

老一套的字符设备驱动框架:

  • 驱动入口出口
  • 驱动入口定义注册字符设备、创建字符设备节点、注册platform设备;
  • 驱动出口反注册platfrom设备、删除字符设备节点、反注册字符设备
  • 构建file_operations结构体
  • 构建platform_device结构体,编写probe函数

如下代码所示:

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
#include <linux/timekeeping.h>
#include <linux/wait.h>
#include <linux/irqflags.h>
#include <linux/pwm.h>static int major;
static struct class *class;static struct pwm_device *pwm_test;static int sg90_probe(struct platform_device *pdev)
{struct device_node *node = pdev->dev.of_node;printk("sg90 match success \n");if (node){/* 从子节点中获取PWM设备 */pwm_test = devm_of_pwm_get(&pdev->dev, node, NULL);  if (IS_ERR(pwm_test)){printk(KERN_ERR" pwm_test,get pwm  error!!\n");return -1;}}else{printk(KERN_ERR" pwm_test of_get_next_child  error!!\n");return -1;}pwm_config(pwm_test, 1500000, 20000000);   /* 配置PWM:1.5ms,90度,周期:20000000ns = 20ms */pwm_set_polarity(pwm_test, PWM_POLARITY_NORMAL); /* 设置输出极性:占空比为高电平 */pwm_enable(pwm_test);    /* 使能PWM输出 */return 0;
}static int sg90_remove(struct platform_device *dev)
{pwm_config(pwm_test, 500000, 20000000);  /* 配置PWM:0.5ms,0度 */pwm_free(pwm_test);return 0;
}static const struct of_device_id sg90_of_match[] = {{ .compatible = "hc-sg90" },{ }
};static struct platform_driver sg90_platform_driver = {.driver = {.name		= "my_sg90",.of_match_table	= sg90_of_match,},.probe			= sg90_probe,.remove			= sg90_remove,
};static int sg90_open (struct inode *node, struct file *filp)
{return 0;
}static ssize_t sg90_write (struct file *filp, const char __user *buf, size_t size, loff_t *offset)
{int res;unsigned char data[1];if(size != 1)return 1;res = copy_from_user(data, buf, size);/* 配置PWM:旋转任意角度(单位1度) */pwm_config(pwm_test, 500000 + data[0] * 100000 / 9, 20000000);   return 1;
}static int sg90_release (struct inode *node, struct file *filp)
{return 0;
}static struct file_operations sg90_ops = {.owner		=	THIS_MODULE,.open 		= 	sg90_open,.write 		= 	sg90_write,.release 	=	sg90_release,
};static int sg90_init(void)
{major = register_chrdev(0 , "sg90", &sg90_ops);class = class_create(THIS_MODULE, "sg90_class");device_create(class, NULL, MKDEV(major, 0), NULL, "sg90");platform_driver_register(&sg90_platform_driver);return 0;
}static void sg90_exit(void)
{platform_driver_unregister(&sg90_platform_driver);device_destroy(class, MKDEV(major, 0));class_destroy(class);unregister_chrdev(major, "sg90");
}module_init(sg90_init);
module_exit(sg90_exit);
MODULE_LICENSE("GPL");
  • 首先 struct device_node *node = pdev->dev.of_node; 获取子节点,在设备树插件中,我们把PWM相关信息保存在 hc_sg90 的子节点中, 所以这里首先获取子节点。

  • 在子节点获取成功后我们使用 devm_of_pwm_get 函数获取pwm, 由于节点内只有一个PWM 这里将最后一个参数直接设置为NULL,这样它将获取第一个PWM。

  • 依次调用 pwm_config、pwm_set_polarity、pwm_enable 函数配置**PWM、设置输出极性、 使能PWM输出,**需要注意的是这里设置的极性为正常极性, 这样pwm_config函数第二个参数设置的就是pwm波的一个周期内的高电平事件。

其中write函数中关于SG90的占空比计算就不多说了,根据如下图来计算吧

在这里插入图片描述
不难得出高电平时间每多出1ms(1000000ns) 对应角度多出9度的结论
则旋转到角度 1 度时,对应的高电平时间为 (500000 + 1000000)/9 ns(因为0度对应的高电平时间为0.5ms = 500000ns)
则旋转到角度 n 度时,高电平时间为 (500000 + n * 1000000)/9 ns


3.应用程序部分

运行示例: ./sg90_test 90 , 即转到90度的位置

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>int main(int argc, char *argv[])
{int fd;int res;unsigned char buf[1];fd = open("/dev/sg90", O_WRONLY);if(fd < 0){printf("sg90 open failed\n");return 0;}buf[0] = atoi(argv[1]);write(fd, buf, 1);close(fd);return 0;
}

相关文章:

【IMX6ULL驱动开发学习】21.Linux驱动之PWM子系统(以SG90舵机为例)

1.设备树部分 首先在 imx6ull.dtsi 文件中已经帮我们定义好了一些pwm的设备树节点&#xff0c;这里以pwm2为例 pwm2: pwm02084000 {compatible "fsl,imx6ul-pwm", "fsl,imx27-pwm";reg <0x02084000 0x4000>;interrupts <GIC_SPI 84 IRQ_TYP…...

el-cascader级联选择器加载远程数据、默认开始加载固定条、可以根据搜索加载远程数据。

加载用户列表分页请求、默认请求20条数据。想添加远程搜索用户功能。原有的方法filter-method不能监听到输入清空数据的时候。这样搜索完无法返回默认的20条数据。直接监听级联选择的v-model绑定的值是无法检测到用户自己输入的。 解决思路&#xff1a; el-cascader 没有提供…...

大数据技术之Clickhouse---入门篇---SQL操作、副本

星光下的赶路人star的个人主页 积一勺以成江河&#xff0c;累微尘以崇峻极 文章目录 1、SQL操作1.1 Insert1.2 Update 和 Delete1.3 查询操作1.4 alter操作1.5 导出数据 2、副本2.1 副本写入流程2.2 配置步骤 1、SQL操作 基本上来说传统关系型数据库&#xff08;以 MySQL 为例…...

【Rust 基础篇】Rust Sized Trait:理解Sized Trait与动态大小类型

导言 Rust是一门以安全性和性能著称的系统级编程语言。在Rust中&#xff0c;类型大小的确定在编译期是非常重要的。然而&#xff0c;有些类型的大小在编译期是无法确定的&#xff0c;这就涉及到了Rust中的动态大小类型&#xff08;DST&#xff09;。为了保证在编译期可以确定类…...

前端框架学习-Vue(三)

目录 初识VueVue模板语法数据绑定el和data的两种写法事件的基本使用$emit在子组件中定义方法&#xff0c;执行父组件的方法 Vue中的事件修饰符&#xff1a;键盘事件计算属性监视属性条件渲染列表渲染表单数据收集过滤器 笔记内容来自&#xff1a;尚硅谷Vue2.0Vue3.0全套教程丨v…...

HTML <rt> 标签

实例 一个 ruby 注释&#xff1a; <ruby> 漢 <rt> ㄏㄢˋ </rt> </ruby>浏览器支持 元素ChromeIEFirefoxSafariOpera<rt>5.05.538.05.015.0 Internet Explorer 9, Firefox, Opera, Chrome 以及 Safari 支持 <rt> 标签。 注释&#xf…...

VMware Linux Centos 配置网络并设置为静态ip

在root用户下进行以下操作 1. 查看子网ip和网关 &#xff08;1&#xff09;进入虚拟网络编辑器 &#xff08;2&#xff09;进入NAT设置 &#xff08;3&#xff09;记录子网IP和子网掩码 2. 修改网络配置文件 &#xff08;1&#xff09;cd到网络配置文件路径下 [rootlo…...

【Leetcode 30天Pandas挑战】学习记录

这个系列难度比较低&#xff0c;一题写一篇其实没必要&#xff0c;就全部放到一篇吧 题目列表&#xff1a; 595. Big Countries1757. Recyclable and Low Fat Products 595. Big Countries 原题链接&#xff1a;595. Big Countries Table: World ---------------------- | C…...

微信小程序使用 canvas 2d 实现签字板组件

本文是在微信小程序中使用 canvas 2d 来实现签字板功能&#xff1b; 效果图&#xff1a; 代码&#xff1a; 1、wxml <view><canvas id"canvas"type"2d"bindtouchstart"start"bindtouchmove"move"bindtouchend"end&qu…...

区块链赋能新时代司法体系,中移链打造可信存证服务

近期&#xff0c;某百万级粉丝网红的法律维权之路引发社会关注。其在面对网络造谣行为时积极搜集证据&#xff0c;使用区块链技术将相关信息上链保全&#xff0c;然后将造谣者全部起诉&#xff0c;一系列操作被广大网友喻为是教科书式网络维权。 科技在发展&#xff0c;时代在…...

ELK报错no handler found for uri and method [PUT] 原因

执行后提示no handler found for uri and method post&#xff0c;最新版8.2的问题&#xff1f; 原因&#xff1a; index.mapping.single_type: true在索引上 设置将启用按索引的单一类型行为&#xff0c;该行为将在6.0后强制执行。 原 {type} 要改为 _doc&#xff0c;格式如…...

Sublime操作技巧笔记

同时选中2个文件&#xff1a;自动切换成左右2个界面 格式化代码ctrlshifth&#xff1a; 使用快捷键ctrl shift p调出控制台&#xff0c;输入install package&#xff0c;然后输入html-css-js prettify&#xff0c;进行下载。具体的快捷键在preference > package setting &g…...

JVM | 基于类加载的一次完全实践

引言 我在上篇文章&#xff1a;JVM | 类加载是怎么工作的 中为你介绍了Java的类加载器及其工作原理。我们简单回顾下&#xff1a;我用一个易于理解的类比带你逐步理解了类加载的流程和主要角色&#xff1a;引导类加载器&#xff0c;扩展类加载器和应用类加载器。并带你深入了解…...

Termux实现电脑端远程操作【开启SSH的完整教程】

文章目录 前言一、安装软件1、安装2、启动服务3、特别说明4、添加key二、电脑端连接1、查看ip2、电脑端连接总结前言 上篇文章【安卓手机变身Linux服务器】讲了如何将你的上古安卓手机变废为宝,这节着重为大家解决一个痛点:“手机上操作实在是不方便”。 一、安装软件 1、安…...

java(Collection类)

文章目录 Collection接口继承树Collection接口及方法判断删除其它 Iterator(迭代器)接口迭代器的执行原理 foreach循环Collection子接口1&#xff1a;ListList接口特点List接口方法List接口主要实现类&#xff1a;ArrayListList的实现类之二&#xff1a;LinkedListList的实现类…...

VS2019编译安装OpenMesh8.0

文章目录 一、简介二、相关准备三、编译安装四、举个栗子参考资料一、简介 多边形网格一直以来就是交互式3D图形应用程序中最合适的几何表示,它们足够灵活,可以近似任意形状,并且可以通过当前的图形硬件有效地处理,即使在今天的低成本电脑上也是如此。OpenMesh便是其中一种…...

Python爬虫遇到URL错误解决办法大全

在进行Python爬虫任务时&#xff0c;遇到URL错误是常见的问题之一。一个错误的URL链接可能导致爬虫无法访问所需的网页或资源。为了帮助您解决这个问题&#xff0c;本文将提供一些实用的解决方法&#xff0c;并给出相关代码示例&#xff0c;希望对您的爬虫任务有所帮助。 一、…...

基于Vue+ElementUI+Echarts+G2Plot的大屏设计器,代码完全开源

简介 &#x1f525;DataRoom是一款基于SpringBoot、MyBatisPlus、ElementUI、G2Plot、Echarts等技术栈的大屏设计器&#xff0c;具备大屏设计、预览、资源管理、组件管理等能力&#xff0c;支持JSON、MySQL、Oracle、PostgreSQL、HTTP、JavaScript、Groovy等数据集接入&#x…...

Linux - PostgreSQL 适用于9.x 以上的 tar.gz 源码安装与理解 - 报错集锦

这里写目录标题 序言主要内容bash 配置文件个人理解关于初始化 PostgreSQL 数据库的理解 启动方法检查服务器是否在PostgreSQL中运行关闭 postgresql 数据库方法参考链接 序言 PostgreSQL 9.x 以下版本笔者没用过&#xff0c;具体操作看参考链接&#xff0c;笔者就不记录重复操…...

Django使用用户列表的展示和添加

接着上一篇&#xff1a;https://blog.csdn.net/javascript_good/article/details/132027702 来实现用户表的查询和添加 1、创建数据库表 在models.py 中&#xff0c;增加UserInfo类&#xff0c;包括字段姓名、密码、年龄、账号余额、入职时间、所属部门、性别 verbose_name 就…...

kubernetes错误汇总

title: “kubernetes错误汇总” categories: - “技术” tags: - “Kubernetes” - “错误汇总” toc: false original: true draft: false 1、增加 master etcd 报错 1.1、错误描述 由于创建的k8s集群&#xff0c;其中有一个master节点初始化失败&#xff0c;先删除了这个节…...

[openCV]基于拟合中线的智能车巡线方案V4

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表"""newDir d…...

【网络云盘客户端】——上传文件的功能的实现

目录 上传文件功能的实现 uploadtask的设计 设置上传的槽函数 uploadFileAction接口 uploadFile接口 定时上传文件 进度条的设计 上传文件功能的实现 上传文件功能实现 1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文…...

WebView2对比CefSharp的超强优势

第一次使用了CefSharp组件&#xff0c;集成开发结束后&#xff0c;测试及使用过程中遇到了一些无法处理的bug及严重的性能问题。然后又测试对比了其他多种组件&#xff0c;具体情况可以阅读我的博客​ ​《.NET桌面程序集成Web网页开发的十种解决方案》​​。最终选用了微软新出…...

前端需要知道的计算机网络知识

1 Web 机制 无论通过有线方式 (通常是网线) 还是无线方式&#xff08;比如 wifi 或蓝牙)&#xff0c;通信需要进行连接&#xff0c;网络上的每台计算机需要链接到路由器&#xff08;router&#xff09;。 路由器确保从一台计算机上发出的一条信息可以到达正确的计算机。计算机…...

[2023杭电多校5 1005] Snake (生成函数)

题意 有 n n n 个标号为 1 , 2 , ⋯ , n 1,2,\cdots,n 1,2,⋯,n 的球&#xff0c;放到 m m m 个无标号盒子 (盒内顺序有标号)&#xff0c;且每个盒子球数不超过 k k k&#xff0c;求方案数对 998 244 353 998\,244\,353 998244353 取模。 1 ≤ m , k ≤ n ≤ 1 0 6 1 \le…...

【MyBtis】各种查询功能

目录 【MyBtis】配置和映射 11.1 示例:实现表数据的增、删、改、查 1.创建工程mybatis_DML demo 2.创建数据库操作的工具类&#xff1a;DBOperatorMgr.java 3.创建映射接口 4.创建XML映射文件 5.测试 【MyBtis】配置和映射 MyBatis 的真正强大之外在于它的映射语句&#xf…...

H5打包封装小程序系统开发

H5打包封装小程序系统开发 H5打包封装小程序系统开发是指将H5页面打包封装成小程序的开发过程。下面是一个简单的步骤&#xff1a; 准备工作&#xff1a;首先&#xff0c;需要准备好H5页面的代码和资源文件。确保H5页面在浏览器中正常运行&#xff0c;并且没有依赖于浏览器特…...

SpringBoot集成jasypt,加密yml配置文件

SpringBoot集成jasypt&#xff0c;加密yml配置文件 一、pom配置二、生成密文代码三、配置3.1、yml加密配置3.2、密文配置3.3、启动配置3.4、部署配置 四、遇到的一些坑 最新项目安全检测&#xff0c;发现配置文件中数据库密码&#xff0c;redis密码仍处理明文状态 一、pom配置…...

【C++】模板(初阶)

1、泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 2、函数模板 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定类型版本…...