RK3588开发板(armsom-w3)之PWM实操 世界即时
PWM介绍
专栏总目录PWM是脉宽调制(Pulse Width Modulation)的缩写。它是一种用于控制电子设备的技术,通过改变电信号的脉冲宽度来实现对设备的控制。PWM基本概念
PWM信号由一个固定频率的周期性脉冲序列组成,每个脉冲的宽度(持续时间)可以根据需要进行调节。调节脉冲宽度的比例可以改变平均电压或电流的大小,从而实现对设备的控制。
(资料图)
当谈论PWM时,以下三个关键术语经常被提及:
频率(Frequency):PWM信号的频率是指每秒钟内脉冲的数量。
周期(Period):PWM信号的周期是指一个完整脉冲序列所花费的时间。它是频率的倒数,以秒为单位表示。周期可以通过将频率的倒数计算得到,例如,一个10kHz的PWM信号的周期为0.1毫秒(100微秒)。
占空比(Duty Cycle):占空比是指PWM信号中脉冲宽度与周期之间的比例关系。它表示了脉冲在一个周期中所占据的时间比例,通常以百分比表示。占空比为0%意味着脉冲不存在(完全低电平),而占空比为100%表示脉冲持续时间占据了整个周期(完全高电平)。在实际应用中,占空比可以在0%到100%之间任意调整,以实现所需的控制效果。
PWM驱动
pwm驱动是一个通用的驱动,SOC厂家都会在SDK里面默认打开
驱动文件
驱动文件所在位置:
drivers/pwm/pwm-rockchip.c
默认SDK已经加载好了PWM的驱动,下文我们主要注意PWM怎么使用
DTS 节点配置
DTS 配置参考文档
Documentation/devicetree/bindings/pwm/pwm.txt
以下为一个例子的示例
Node name { compatible = "Driver matching character"; pwms = < &pwmX 0 25000 0 >; }; &pwmX { status = "okay"; pinctrl-names = "active"; pinctrl-0 = < &pwmX_pin_pull_down >; };
pwms的几个参数说明如下:
参数 1,表示 index (per-chip index of the PWM to request),一般是 0,因为我们 Rockchip PWM 每个chip 只有一个。
参数 2,表示 PWM 输出波形的时间周期,单位是 ns;例如下面配置的 25000 就是表示想要得到的
PWM 输出周期是 40K 赫兹。
参数 3,表示极性,为可选参数;下面例子中的配置为负极性。
PWM使用
PWM 提供了用户层的接口,在 /sys/class/pwm/ 节点下面,PWM 驱动加载成功后,会在/sys/class/pwm/ 目录下产生 pwmchip0 目录;向 export 文件写入 0,就是打开 pwm 定时器0,会产生一个 pwm0 目录,相反的往 unexport 写入 0 就会关闭 pwm 定时器了,同时 pwm0 目录会
被删除,该目录下有以下几个文件:
enable:写入 1 使能 pwm,写入 0 关闭 pwm;
polarity:有 normal 或 inversed两个参数选择,表示输出引脚电平翻转;
duty_cycle:在 normal 模式下,表示一个周期内高电平持续的时间(单位:纳秒),在
reversed 模式下,表示一个周期中低电平持续的时间(单位:纳秒);
period:表示 pwm 波的周期(单位:纳秒);
以下是 pwmchip0 的例子,设置 pwm0 输出频率 100K,占空比 50%, 极性为正极性:
cd /sys/class/pwm/pwmchip0/echo 0 > exportcd pwm0echo 10000 > periodecho 5000 > duty_cycleecho normal > polarityecho 1 > enable
PWM应用实例
通常电子设备中应用pwm是比较常见的,比如风扇电机控制,电视背光控制, LED 照明调光、电动工具马达控制、汽车加热器等领域。
这里简单介绍一下pwm控制LED灯实现呼吸灯效果。
呼吸灯需要灯的驱动与PWM的驱动结合,两个驱动之间传递数据,我们可以在驱动中调用其他的驱动。
led是我需要的设备,这个设备用到了pwm,而pwm是用默认的驱动。
硬件上我们在开发板找到具有pwm功能的引脚
设备树的修改如下:
/{breathing_light {compatible = "lhd,breathing_light_test";backlight {pwms = < &pwm8 0 25000 0 >;pwm-names = "breathing_light"; };};};&pwm8 {status = "okay";};
写一个驱动。内部在使用PWM子系统。形成了包含驱动的驱动。
示例代码
驱动程序
#include < linux/init.h >#include < linux/module.h >#include < linux/fs.h >#include < linux/cdev.h >#include < linux/uaccess.h >#include < linux/types.h >#include < linux/kernel.h >#include < linux/delay.h >#include < linux/ide.h >#include < linux/errno.h >#include < linux/gpio.h >//#include < asm/mach/map.h >#include < linux/of.h >#include < linux/of_address.h >#include < linux/of_gpio.h >#include < asm/io.h >#include < linux/device.h >#include < linux/platform_device.h >#include < linux/pwm.h >#define RED_LED_DTS_COMPATIBLE "lhd,breathing_light_test" /* 设备树节点匹配属性 */#define LED_PWM_CMD_SET_DUTY 0x01#define LED_PWM_CMD_SET_PERIOD 0x02#define LED_PWM_CMD_SET_BOTH 0x03#define LED_PWM_CMD_ENABLE 0x04#define LED_PWM_CMD_DISABLE 0x05struct led_pwm_param{ int duty_ns; int period_ns;};struct red_led_dev { dev_t dev_no; struct cdev chrdev; struct class *led_class; struct device_node *dev_node; struct pwm_device *red_led_pwm;};static struct led_pwm_param led_pwm;static struct red_led_dev led_dev;static int red_led_drv_open (struct inode *node, struct file *file){ int ret = 0; //pwm_set_periodnnn(led_dev.red_led_pwm, PWM_POLARITY_INVERSED);//设置PWM信号的极性pwm_enable(led_dev.red_led_pwm);//启用指定PWM设备,使其开始输出PWM信号。 printk("red_led_pwm open"); return ret;}static ssize_t red_led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset){ int err; if (size != sizeof(led_pwm)) return -EINVAL;err = copy_from_user(&led_pwm, buf, size); if (err > 0) return -EFAULT;pwm_config(led_dev.red_led_pwm, led_pwm.duty_ns, led_pwm.period_ns);//配置PWM设备的基本参数,如频率、占空比等。 printk("red_led_pwm write");return 1;}static long drv_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ int ret = 0; void __user *my_user_space = (void __user *)arg; switch (cmd) { case LED_PWM_CMD_SET_DUTY: ret = copy_from_user(&led_pwm.duty_ns, my_user_space, sizeof(led_pwm.duty_ns)); if (ret > 0) return -EFAULT; pwm_config(led_dev.red_led_pwm, led_pwm.duty_ns, led_pwm.period_ns); break; case LED_PWM_CMD_SET_PERIOD: ret = copy_from_user(&led_pwm.period_ns, my_user_space, sizeof(led_pwm.period_ns)); if (ret > 0) return -EFAULT; pwm_config(led_dev.red_led_pwm, led_pwm.duty_ns, led_pwm.period_ns); break; case LED_PWM_CMD_SET_BOTH: ret = copy_from_user(&led_pwm, my_user_space, sizeof(led_pwm)); if (ret > 0) return -EFAULT; pwm_config(led_dev.red_led_pwm, led_pwm.duty_ns, led_pwm.period_ns); break; case LED_PWM_CMD_ENABLE: pwm_enable(led_dev.red_led_pwm); break; case LED_PWM_CMD_DISABLE: pwm_disable(led_dev.red_led_pwm); break; } return 0;}static int red_led_drv_release(struct inode *node, struct file *filp){ int ret = 0; pwm_config(led_dev.red_led_pwm, 0, 5000);//配置PWM设备的基本参数,如频率、占空比等。 printk("led pwm dev close");// pwm_disable(led_dev.red_led_pwm); return ret;}static struct file_operations red_led_drv = {.owner = THIS_MODULE,.open = red_led_drv_open,.write = red_led_drv_write, .unlocked_ioctl = drv_ioctl, .release = red_led_drv_release,};/*设备树的匹配列表 */static struct of_device_id dts_match_table[] = { {.compatible = RED_LED_DTS_COMPATIBLE, }, {}, };static int led_red_driver_probe(struct platform_device *pdev){ int err; int ret; struct device *tdev; struct device_node *child; tdev = &pdev- >dev; child = of_get_next_child(tdev- >of_node, NULL); /* 获取设备树子节点 */if (!child) { return -EINVAL; } led_dev.red_led_pwm = devm_of_pwm_get(tdev, child, NULL); /* 从子节点中获取PWM设备,设备树获取这个设备就可以了 */ if (IS_ERR(led_dev.red_led_pwm)) { printk(KERN_ERR"can"t get breathing_light!!"); return -EFAULT; } ret = alloc_chrdev_region(&led_dev.dev_no, 0, 1, "breathing_light");//动态分配字符设备的主设备号if (ret < 0) {pr_err("Error: failed to register mbochs_dev, err: %d", ret);return ret;}cdev_init(&led_dev.chrdev, &red_led_drv);//初始化字符设备结构体cdevcdev_add(&led_dev.chrdev, led_dev.dev_no, 1);//将已经初始化的字符设备结构体cdev添加到系统中 led_dev.led_class = class_create(THIS_MODULE, "breathing_light");//创建一个设备类(device class)并注册到内核中err = PTR_ERR(led_dev.led_class);if (IS_ERR(led_dev.led_class)) { goto failed1;} tdev = device_create(led_dev.led_class , NULL, led_dev.dev_no, NULL, "breathing_light"); //创建一个设备实例并注册到设备类中 if (IS_ERR(tdev)) { ret = -EINVAL;goto failed2;} printk(KERN_INFO"%s %s line %d", __FILE__, __FUNCTION__, __LINE__); return 0;failed2: device_destroy(led_dev.led_class, led_dev.dev_no); class_destroy(led_dev.led_class);failed1: cdev_del(&led_dev.chrdev);unregister_chrdev_region(led_dev.dev_no, 1); return ret;}int led_red_driver_remove(struct platform_device *dev){ // pwm_disable(led_dev.red_led_pwm); // pwm_free(led_dev.red_led_pwm); printk(KERN_INFO"driver remove %s %s line %d", __FILE__, __FUNCTION__, __LINE__); device_destroy(led_dev.led_class, led_dev.dev_no);class_destroy(led_dev.led_class);unregister_chrdev_region(led_dev.dev_no, 1); cdev_del(&led_dev.chrdev); return 0;}static struct platform_driver red_led_platform_driver = { .probe = led_red_driver_probe, .remove = led_red_driver_remove, .driver = { .name = "lhd,breathing_light_test", .owner = THIS_MODULE, .of_match_table = dts_match_table, //通过设备树匹配 },};module_platform_driver(red_led_platform_driver);MODULE_AUTHOR("LHD");MODULE_LICENSE("GPL");
将上述驱动编译为ko文件然后push进3588开发板里面
应用层程序
#include "stdio.h"#include < sys/types.h >#include < sys/stat.h >#include < fcntl.h >#include < unistd.h >#include < stdio.h >#include < string.h >#include < sys/ioctl.h >#include < poll.h >#include < stdint.h >#define DEV_NAME "/dev/breathing_light"#define LED_PWM_CMD_SET_DUTY 0x01#define LED_PWM_CMD_SET_PERIOD 0x02#define LED_PWM_CMD_SET_BOTH 0x03#define LED_PWM_CMD_ENABLE 0x04#define LED_PWM_CMD_DISABLE 0x05struct led_pwm_param { int duty_ns; int period_ns;};void sleep_ms(unsigned int ms){ struct timeval delay;delay.tv_sec = 0;delay.tv_usec = ms * 1000; select(0, NULL, NULL, NULL, &delay);}int main(int argc, char **argv){ int fd; int ret; /* 2. 打开文件 */fd = open(DEV_NAME, O_RDWR | O_NONBLOCK); // | O_NONBLOCKif (fd < 0){printf("can not open file %s, %d", DEV_NAME, fd);return -1;} int buf = 3;struct led_pwm_param led_pwm;led_pwm.duty_ns = 500;led_pwm.period_ns = 5000; write(fd, &led_pwm, sizeof(led_pwm)); sleep_ms(3000);while(1){if(led_pwm.duty_ns<=500){while(led_pwm.duty_ns< led_pwm.period_ns){ioctl(fd, LED_PWM_CMD_SET_DUTY, &led_pwm.duty_ns);sleep_ms(50);led_pwm.duty_ns += 300;}}else{while(led_pwm.duty_ns > 500){ioctl(fd, LED_PWM_CMD_SET_DUTY, &led_pwm.duty_ns);sleep_ms(50);led_pwm.duty_ns -= 300;}}}close(fd); return 0;}
使用3588自带的编译器将用户程序编译进开发板
prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc apptest_breathing_light_.c -o testpwm
adb push path/testpwm /userdata
chmod 777 testpwm
./testpwm
最后可以看到灯明灭交替的效果
审核编辑:汤梓红
标签:
推荐文章
- RK3588开发板(armsom-w3)之PWM实操 世界即时
- 鸡蛋的保质期是几个月(鸡蛋的保质期)
- 耀华中学红桥学校7月招生 计划招收140人_世界时快讯
- 居理买房暴雷!前员工称“欠薪千万元,丈母娘顶替法人”
- 精彩看点:上海市浦东新区发布大风黄色预警
- 环球新动态:二十碳五烯酸需求量(二十碳五烯酸)
- 焦点快看:2023首届装备制造产业大会暨“中国钻机之乡”张家口宣化高质量发展大会准备就绪!
- 爱旭股份:拟出资24亿元设立山东爱旭
- 今日热搜:国安达:变电站火灾和锂电池储能柜火灾的特征不同,因此我们采用的灭火技术及解决方案也不同
- 每日快播:《欢迎来到王之国》公开正式预告,李俊昊&润娥根本就是演艺圈的资优生
- 每日头条!中信建投陈果:港股迎来年内最佳机会
- 国家防总启动防汛四级应急响应 派工作组赴广西福建指导救灾|头条
- 当前报道:男篮18人名再度反转,杜锋杨鸣的4爱徒出局,姚明助力周琦回归CBA
- 严正化不敢看《车贞淑医生》首播,被夸后中断录影爆哭半小时 新消息
- 每日报道:吃美食、看电影、赏舞剧!非遗文化在新时代有多潮?
- 每日消息!中方驳斥:无中生有、信口雌黄、恶意诋毁!
- 环球观天下!220件文物讲述汉字源远流长 成博新展带你走进“汉字中国”丨文化和自然遗产日
- 环球观天下!阅后即焚电影(阅后即焚)
- 12306网站试行在线选铺服务!卧铺铺位要哪个?自己决定
- 生育津贴必须三个月内领取么
- 智商极高,心思缜密,最难被算计的3星座,精明无比,公认的人精_观热点
- 今年雪糕价格如何?3至5元仍是主流
- 镇赉县气象局发布冰雹黄色预警【III级/较重】【2023-06-10】
- 月经期可以吃什么(来例假时吃什么比较好)
- 曼联两引援目标愿加盟,都是第二人选!预算不足滕哈格欲启用青木_全球最资讯
- 牵手胡继勇的董思槿相貌前后相差这么大的秘密
- 《天空之城》:用纯真对抗贪婪
- 航行警告!渤海海峡黄海北部执行军事任务
- 约基奇23+12戈登27分 掘金力克热火3-1夺冠军点
- 甲烷燃烧后火焰是什么颜色的 甲烷燃烧产生的火焰 最资讯
- 中国驻英使馆:苏纳克涉华言论纯属无中生有、信口雌黄、恶意诋毁|天天即时
- 天天实时:第二十五届上海国际电影节开幕
- abc视频文件转换mp4_abc文件转换成mp4 每日速递
- 益方生物单日跌幅达19.92% 创新药“盲盒式”渡劫轮番上场
- 快播:联特科技:公司向客户交付产品情况属于商业秘密不便披露,请谅解
- 我国西南三大铁路干线襄渝、达成、成昆铁路大修完工
- 全球实时:科华数能、国轩高科、海博思创、国能日新等7家企业分羹!1.54GWh直流侧+1.57GW PCS+40套EMS集采!
- 帝蒂卡图腾(帝蒂卡) 今亮点
- 白塔国际机场暑运模式即将开启 观速讯
- 卩是什么偏旁怎么念(卩) 环球微动态
- 高考预录取什么时候知道(高考预录取)
- 世界热门:宙斯浏览器好在哪里_宙斯浏览器有什么猫腻
- 山东省泗水县水利实业有限责任公司(山东省泗水县)-世界观察
- 补肾壮阳药哪种效果好(补肾壮阳药哪种最好)_热闻
- moto(razr v8)
- 快资讯丨一天内三名高管辞任,汾酒还能“三分天下”吗?
- 世界新资讯:俄高官:乌克兰曾迫于美国压力放弃与俄签署和平协议
- get out of什么意思(get out是什么意思) 环球精选
- 视焦点讯!三亚机场今年旅客吞吐量破千万 达历史同期最高水平
- 高盛:2027年创作者经济规模可接近5000亿美元
- 观热点:400首古诗有哪些 四百字左右的古文或诗词有哪些?
- 长青科技:田相龄女士辞去公司第三届监事会监事职务|全球观焦点
- Niko Partners:预计到2027年中国游戏市场总收入将超过570亿美元 环球快讯
- DXOMARK 发布小米 13Ultra 影像测试,不如小米 11Ultra? 全球消息
X 关闭
最新资讯
- 一汽奔腾NAT续航达成率97.85%,青岛网约车司机都在夸-焦点滚动
- 时讯:引援计划曝光!皇马将投4亿欧元,欲签5人,小梅西凯恩阿芳上榜
- 每日速看!长城久润混合基金A份额限购
- 新疆持续优化营商环境 紧贴民生推动高质量发展_全球新消息
- 环球百事通!无锡外地户籍怎么打印儿童预防接种情况评价表?
- 进入技术性衰退!欧元区一季度GDP环比下降0.1%,不及预期
- 【全球时快讯】航班增加 机票价格回落 国内民航市场加快复苏进程
- 全球热门:北京市2023年6月8日19时00分解除大风蓝色预警信号
- 鸿铭股份:关于股票所属概念题材,各个炒股软件有其自身划分标准,公司始终专注于包装设备的研发生产和销售
- 消息称三星、谷歌和高通正联合开发新MR产品,最早今年内推出_全球今日讯
- 当前讯息:2026年全球电动汽车交付量有望翻番 但2050年难实现零排目标
- 斯巴鲁傲虎怎么样及Subaru Outback现在报价多少钱 天天热点
- DDoS攻击来袭 游戏厂商如何防御? 世界即时
- 【大敦煌·绝色】敦煌鸣沙山下,沙漠露营太好玩了! 全球滚动
- 环球要闻:新华全媒+|夜色中,一座港口向世界展现新活力
- 焦点关注:格兰陵鲨鱼_格兰陵
- 微软 Azure OpenAI 政府客户将获得安全的生成式 AI API 访问权限|热门看点
- 各大平台暑期游产品销售火爆 旅游市场有望延续五一行情|天天要闻
- 无限期待中的限是什么意思_无限期待的意思 全球热门
- 港交所:未来内地投资者或可经“港股通”买卖人民币柜台证券_最新快讯
- 天天实时:民勤:高考第一天 考场外温暖的目送
- 当前动态:饿了么关联公司法定代表人变更 方永新接替王星
- 浙江衢州怎么念_忂衢州读音
- “小分子”撬动健康产业大发展 济南发力培育透明质酸产业集群 每日速读 当前速递
- 控股股东成“老赖”!加加食品:对公司生产经营暂无实质影响|环球讯息
- 广东省发布《关于进一步完善和落实积极生育支持措施的实施意见》
- 幼儿师范专科学校毕业的文凭 幼儿师范学校毕业及以上学历是什么意思
- 你过桥他爬桥、买个馒头排大队……网红打卡怎样才能不招人烦?|当前热讯
- 赵丽颖谢娜,黄景瑜,热巴,华晨宇,范丞丞
- 华铭智能:公司产品主要使用于新能源汽车等设备,但未来可以扩大和开发市场领域 每日资讯
- 6月7日美棉M1-1/8到港价涨67元/吨 报16518元/吨-焦点消息
- 重庆两江新区中医院:爱眼日健康宣教进校园 守护孩子明眸“视界”|天天播资讯
- 新巨丰拟收购纷美包装股权,深交所下发重组问询函 世界看点
- 最早江苏方言茉莉花原唱?
- 【收评】沪锌日内上涨1.24% 机构称沪锌短线维持低位震荡看待 上方压力位在20日均线_世界要闻
- 华铭智能:公司的自动检票机上很早就开发了AI功能的集成 包括指纹 掌静脉 虹膜和人脸等功能
- 客观唯心主义和主观唯心主义的区别是什么意思_客观唯心主义和主观唯心主义的区别是什么|播资讯
- 今天(2023年6月7日)黄金价格走势分析 每日热讯
- 广东自贸试验区累计办理FT账户资金业务超2万亿元 每日快看
- 极目锐评|要平息“指鼠为鸭”质疑,何不公布调查细节?
- 南方人好还是北方人好_河南人属于南方人还是北方人
- 五款大模型谁最强?讯飞星火实测高考作文全国卷:掌控时间,做自己的主人 世界快播报
- 龙舟赛期间南昌免费发放1万张景区门票
- 被删除的Sam Altman谈话纪要,讲了什么?_全球快报
- 时政现场说丨久久为功 守护“塞外明珠”
- 盈康生命旗下医院引入山西省首台纳米刀(IRE)肿瘤消融系统 天天关注
- 吾尝终日不食终夜不寝以思无益不如学也翻译句子的意思_吾尝终日不食终夜不寝以思无益不如学也翻译
- 全球报道:黑色蓝眼睛的猫是什么品种_蓝眼睛的猫是什么品种
- 天天微头条丨6月7日新天钢管坯出厂价下跌
- 首开股份(600376)6月7日主力资金净买入81.28万元 要闻速递
X 关闭