linux pwm驱动,动手写linux下PWM驱动--Apple的学习笔记

一,前言

linux舵机硬件环境搭建成功--Apple的学习笔记昨天已经把SG90舵机的硬件环境搭建成功,并且通过命令行驱动验证通过。今天还是动手写驱动。PWM驱动比I2C还要简单,可以理解为不用写,只要写应用就可以了,但是我想让应用的人使用起来更简单,所以呢,按这样的思路,PWM设备驱动还是要写的。那么就要抽象一下,做做分工,应用主要输入角度即可控制舵机转动位置,其它的都是驱动来实现。APP和驱动为文件夹12,上传到了我的gitee

二,SG90原理

昨天不是验证过有PWM,但是舵机转下就停了,原因是PWM占空比不变就是这样的现象,我今天查看了下SG90的原理。参考网址:https://blog.csdn.net/qq_24037197/article/details/53464176

无负载速度:0.12秒/60度(4.8V) 0.002s/度

都说50Hz的时候线性度好。所以设置为20ms周期,但是SG90舵机有运行速度,所以要delay一段时间。2000us/度。

在一个特定的频率下,特定的占空比使得舵机会转到一个角度,占空比不变,则角度不会不会变化,所以想要舵机动,就要在国定的频率下不断改变占空比。

三,测试通过

我做了3个调试,一个是在0和45度来回转。一个从0开始是慢慢转到180度,角度越大越慢,还有一个是0-180度间delay时间设置为固定的10ms的就可以看到从0快速转到180度。命令比较简单如下。

Welcome to Buildroot

buildroot login: root

# cd /usr/study/

# insmod applePWM.ko

[ 16.795320] applePWM: loading out-of-tree module taints kernel.

[ 16.802716] ApplePWM initilize ok

# ./pwm

^C

四,遇到的问题

一开始不清楚pwm设备如何注册。pwm的linux驱动框架应该如何写。

因为芯片厂商已经为soc写了pwm驱动,而我其实不需要再写了,那么app如何通过open,read,write使用pwm呢?pwm中是config,enable等pwm_ops结构体,不是file_ops,后来想到的办法是索性用misc框架来注册驱动进行pwm打包。然后调用底层的pwm.h中的函数。

一开始不清楚应用程序如何打开设备。

网上搜索了下按如下也可以用read,write操作。后来由于设计为了misc和platform其实类似,所以也可以用read,write,ioctrl了。

int pwm_enable()

{

fd = open("/sys/class/pwm/pwmchip0/pwm0/enable", O_WRONLY);

write(fd, "1", 0); // 为pwm0写值

return 0;

}

五,我的pwm驱动代码

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/**********************************************************************************

Copyright (C), by AppleCai

Project : Study Kernel

Description : BSP level for cdev

History :

CPU and Compiler : AM335x,ARM-LINIX-GCC

GenDate : 2020-11-16

OwnerBy : Apple Cai

**********************************************************************************/

#include

#include

struct pwm_device *pwm;

struct semaphore sem;

#define PMW_START 1

#define PMW_STOP 2

/*

* @description : 打开设备

* @param - inode : 传递给驱动的inode

* @param - filp : 设备文件,file结构体有个叫做private_data的成员变量

* 一般在open的时候将private_data指向设备结构体。

* @return : 0 成功;其他 失败

*/

static int ApplePWM_open(struct inode *inode, struct file *filp)

{

int ret = 0;

if (!down_trylock(&sem)) //是否获得信号量,是 down_trylock(&lock)=0,否则非 0

{

pwm = pwm_request(0, "mypwmdev");

if (NULL == pwm)

{

printk("no res\n");

up(&sem); //释放信号量 lock

return -ENODEV;

}

/*pwm_set_polarity(pwm, PWM_POLARITY_NORMAL);*/

return ret;

}

else

{

printk("busy\n");

return -EBUSY; //返回错误信息:请求的资源不可用

}

}

/*设备控制函数:*/

static long ApplePWM_ioctl(struct file *filp, unsigned int cmd,unsigned long arg)

{

switch (cmd) {

case PMW_START: //if cmd=1 即进入 case PWM_IOCTL_SET_FREQ

if (arg < 0) //如果设置的频率参数是 0

return -EINVAL; //返回错误信息,表示向参数传递了无效的参数

pwm_config(pwm, arg, 20000000);

pwm_enable(pwm);

break;

case PMW_STOP: // if cmd=2 即进入 case PWM_IOCTL_STOP

pwm_disable(pwm); //停止蜂鸣器

break;

}

return 0; //成功返回

}

/*

* @description : 关闭/释放设备

* @param - filp : 要关闭的设备文件(文件描述符)

* @return : 0 成功;其他 失败

*/

static int ApplePWM_release(struct inode *inode, struct file *filp)

{

pwm_disable(pwm);

pwm_free(pwm);

up(&sem); //释放信号量 lock

return 0;

}

/* AppleEEP操作函数 */

static const struct file_operations ApplePWM_ops = {

.owner = THIS_MODULE,

.open = ApplePWM_open,

.release = ApplePWM_release,

.unlocked_ioctl = ApplePWM_ioctl,

};

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = "ApplePWM",

.fops = &ApplePWM_ops,

};

static int __init ApplePWM_init(void)

{

int ret=0;

sema_init(&sem, 1);

ret = misc_register(&misc); //注册一个 misc 设备

printk ("ApplePWM initilize ok\n");

return ret;

}

static void __exit ApplePWM_exit(void)

{

misc_deregister(&misc); //注销设备

}

module_init(ApplePWM_init);

module_exit(ApplePWM_exit);

MODULE_AUTHOR("AppleCai");

MODULE_LICENSE("GPL");

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值