【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的设备树节点,这里以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绑定的值是无法检测到用户自己输入的。 解决思路: el-cascader 没有提供…...

大数据技术之Clickhouse---入门篇---SQL操作、副本
星光下的赶路人star的个人主页 积一勺以成江河,累微尘以崇峻极 文章目录 1、SQL操作1.1 Insert1.2 Update 和 Delete1.3 查询操作1.4 alter操作1.5 导出数据 2、副本2.1 副本写入流程2.2 配置步骤 1、SQL操作 基本上来说传统关系型数据库(以 MySQL 为例…...
【Rust 基础篇】Rust Sized Trait:理解Sized Trait与动态大小类型
导言 Rust是一门以安全性和性能著称的系统级编程语言。在Rust中,类型大小的确定在编译期是非常重要的。然而,有些类型的大小在编译期是无法确定的,这就涉及到了Rust中的动态大小类型(DST)。为了保证在编译期可以确定类…...
前端框架学习-Vue(三)
目录 初识VueVue模板语法数据绑定el和data的两种写法事件的基本使用$emit在子组件中定义方法,执行父组件的方法 Vue中的事件修饰符:键盘事件计算属性监视属性条件渲染列表渲染表单数据收集过滤器 笔记内容来自:尚硅谷Vue2.0Vue3.0全套教程丨v…...
HTML <rt> 标签
实例 一个 ruby 注释: <ruby> 漢 <rt> ㄏㄢˋ </rt> </ruby>浏览器支持 元素ChromeIEFirefoxSafariOpera<rt>5.05.538.05.015.0 Internet Explorer 9, Firefox, Opera, Chrome 以及 Safari 支持 <rt> 标签。 注释…...

VMware Linux Centos 配置网络并设置为静态ip
在root用户下进行以下操作 1. 查看子网ip和网关 (1)进入虚拟网络编辑器 (2)进入NAT设置 (3)记录子网IP和子网掩码 2. 修改网络配置文件 (1)cd到网络配置文件路径下 [rootlo…...
【Leetcode 30天Pandas挑战】学习记录
这个系列难度比较低,一题写一篇其实没必要,就全部放到一篇吧 题目列表: 595. Big Countries1757. Recyclable and Low Fat Products 595. Big Countries 原题链接:595. Big Countries Table: World ---------------------- | C…...

微信小程序使用 canvas 2d 实现签字板组件
本文是在微信小程序中使用 canvas 2d 来实现签字板功能; 效果图: 代码: 1、wxml <view><canvas id"canvas"type"2d"bindtouchstart"start"bindtouchmove"move"bindtouchend"end&qu…...
区块链赋能新时代司法体系,中移链打造可信存证服务
近期,某百万级粉丝网红的法律维权之路引发社会关注。其在面对网络造谣行为时积极搜集证据,使用区块链技术将相关信息上链保全,然后将造谣者全部起诉,一系列操作被广大网友喻为是教科书式网络维权。 科技在发展,时代在…...

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

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

JVM | 基于类加载的一次完全实践
引言 我在上篇文章:JVM | 类加载是怎么工作的 中为你介绍了Java的类加载器及其工作原理。我们简单回顾下:我用一个易于理解的类比带你逐步理解了类加载的流程和主要角色:引导类加载器,扩展类加载器和应用类加载器。并带你深入了解…...
Termux实现电脑端远程操作【开启SSH的完整教程】
文章目录 前言一、安装软件1、安装2、启动服务3、特别说明4、添加key二、电脑端连接1、查看ip2、电脑端连接总结前言 上篇文章【安卓手机变身Linux服务器】讲了如何将你的上古安卓手机变废为宝,这节着重为大家解决一个痛点:“手机上操作实在是不方便”。 一、安装软件 1、安…...

java(Collection类)
文章目录 Collection接口继承树Collection接口及方法判断删除其它 Iterator(迭代器)接口迭代器的执行原理 foreach循环Collection子接口1:ListList接口特点List接口方法List接口主要实现类:ArrayListList的实现类之二:LinkedListList的实现类…...
VS2019编译安装OpenMesh8.0
文章目录 一、简介二、相关准备三、编译安装四、举个栗子参考资料一、简介 多边形网格一直以来就是交互式3D图形应用程序中最合适的几何表示,它们足够灵活,可以近似任意形状,并且可以通过当前的图形硬件有效地处理,即使在今天的低成本电脑上也是如此。OpenMesh便是其中一种…...

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

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

Linux - PostgreSQL 适用于9.x 以上的 tar.gz 源码安装与理解 - 报错集锦
这里写目录标题 序言主要内容bash 配置文件个人理解关于初始化 PostgreSQL 数据库的理解 启动方法检查服务器是否在PostgreSQL中运行关闭 postgresql 数据库方法参考链接 序言 PostgreSQL 9.x 以下版本笔者没用过,具体操作看参考链接,笔者就不记录重复操…...

Django使用用户列表的展示和添加
接着上一篇:https://blog.csdn.net/javascript_good/article/details/132027702 来实现用户表的查询和添加 1、创建数据库表 在models.py 中,增加UserInfo类,包括字段姓名、密码、年龄、账号余额、入职时间、所属部门、性别 verbose_name 就…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...