使用linux内核hrtimer高精度定时器实现GPIO口模拟PWM,【原创】

本文介绍了如何使用Linux内核的高精度定时器(hrtimer)在S5P4418平台上模拟GPIO口产生PWM信号来控制无源蜂鸣器。普通定时器因精度限制可能导致蜂鸣器杂音,而hrtimer能极大提升性能。程序中应用了信号量和等待队列以确保定时任务完成后再关闭设备。尽管如此,由于定时器可能被打断,仍可能产生PWM输出不连续的问题。文章提供了驱动程序代码、APP控制示例及编译说明。
摘要由CSDN通过智能技术生成

关键词:Android  linux hrtimer 蜂鸣器  等待队列 信号量 字符设备

平台信息:
内核:linux3.4.39 
系统:android/android5.1
平台:S5P4418 

作者:庄泽彬(欢迎转载,请注明作者)

邮箱:2760715357@qq.com

程序描述:本文控制的设备是无源蜂鸣器,由于无源蜂鸣器是需要产生一定的频率的PWM才能够控制蜂鸣器,不像有源蜂鸣器,只需要提供高低电平就可以控制蜂鸣器。linux内核普通的定时器,由于具有一定的局限性,不能达到纳秒级别的定时,使用普通的定时器模拟GPIO口产生PWM会导致蜂鸣器出现杂音,因此要使用hrtimer高精度定时器模拟GPIO口产生PWM可以极大的改善性能。使用信号量sem只是为了避免多个应用程序打开设备,使用等待队列是为了让程序可以按照指定的方式去运行,如果不加等待队列,在启动hrtimer定时器之后就会不会等待定时器完成之后在关闭设备,因此需要加入等待队列,等待定时器定时的工作完成之后再唤醒等待队列。虽然程序可以使用GPIO模拟PWM产生一定频率的信号去控制无源蜂鸣器,但是还是存在一定的局限性,因为定时器也是加入内核进行调度,所以有可能杂定时的时候会导致输出的PWM被打断,导致杂音的出现。因此严格来说不能完整的输出一段不被打断模拟PWM信号。如果有什么好方法可以实现的话,可以共同探讨。好吧不说了上代码吧。

无源蜂鸣器的驱动程序(代码写的一般般如有不对,欢迎指点)

buzzer_driver.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/fs.h>
  4 #include <linux/device.h>
  5 #include <linux/slab.h>
  6 #include <linux/cdev.h>
  7 #include <linux/interrupt.h>
  8 #include <linux/gpio.h>
  9 #include <linux/input.h>
 10 #include <linux/sched.h>
 11 #include <linux/wait.h>
 12 #include <linux/delay.h>
 13 #include <linux/semaphore.h>
 14 
 15 #include <asm/uaccess.h>
 16 #include <asm/io.h>
 17 
 18 #include <mach/platform.h>
 19 
 20 #define BUZZER_DEVICE_NAME   "mybuzzer"     
 21 #define BUZZER_CLASS_NAME   "mybuzzer"    //sys/class/mybuzzer
 22 #define BUZZER_DEVICE_NUM     1         //设备节点的编号最终生成节点的名字为/dev/buzzer-1
 23 
 24 
 25 #define BUZZER_GPIO_SWITCH  1    //是否设置buzzer的gpio的初始化,另一个驱动已经初始化GPIO
 26 #define BUZZER_DELAY_TIME_HIGHT (190000) //2.7KHZ
 27 #define BUZZER_DELAY_TIME_LOW (190000) //2.7KHZ
 28 #define DE_BUG 1
 29 
 30 #if DE_BUG 
 31 #define prdebug(fmt,arg...)      printk("zbzhuang"KERN_ERR fmt"\n",##arg)
 32 #else
 33 #define prdebug(fmt,arg...)      do{}while(0);
 34 #endif
 35 
 36 
 37 
 38 typedef enum {
 39     BUZZER_DISABLE = 0,
 40     BUZZER_ENABLE,
 41 }BUZZER_STATUS_t;
 42 
 43 //buzzer的设备对象
 44 struct buzzer_chip{
 45    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
GPIO模拟PWM(脉冲宽度调制)是一种通过在GPIO引脚上快速切换电平来模拟PWM信号的方法。在某些单片机或嵌入式系统中,可能没有硬件支持的PWM功能,但可以使用GPIO实现类似的效果。 要在GPIO模拟PWM,你可以按照以下步骤进行操作: 1. 选择一个合适的GPIO引脚作为输出引脚。 2. 使用编程语言(如Python或C)来控制GPIO引脚的电平。 3. 通过控制GPIO引脚的电平持续时间来模拟PWM信号的占空比。 4. 使用一个循环或定时器来控制PWM信号的频率。 下面是一个使用Python进行GPIO模拟PWM的示例代码: ```python import time import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) pwm = GPIO.PWM(18, 100) # 设置频率为100Hz pwm.start(50) # 设置初始占空比为50% try: while True: # 改变占空比 for duty_cycle in range(0, 101, 5): pwm.ChangeDutyCycle(duty_cycle) time.sleep(0.1) for duty_cycle in range(100, -1, -5): pwm.ChangeDutyCycle(duty_cycle) time.sleep(0.1) except KeyboardInterrupt: pass pwm.stop() GPIO.cleanup() ``` 以上代码使用RPi.GPIO库来控制树莓派的GPIO引脚。通过改变`ChangeDutyCycle()`函数的参数,可以改变PWM信号的占空比。循环部分可以让PWM信号在0%到100%之间循环变化。 请注意,GPIO模拟PWM的精度可能不如硬件PWM,并且频率也会受到系统性能的限制。因此,对于需要高精度和稳定性的应用,建议使用支持硬件PWM的设备或模块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式小庄老师

要是觉得不错,就给我点支持吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值