PWM的定义为:可调节脉冲调节器,换句话来说就是一个总周期不变,占空比可调节的方波。
方波:在信号领域一般分为数字信号和模拟信号,数字信号就两种状态:0和1,相互交替成为方波。
总周期:从1状态到1状态。也就是总周期为:从一个电平再回到这个电平。
占空比:有效电平占据占总周期的比例
有效电平:器件生效的电平
我所使用的开发板为RK3588S支持15路的PWM,经过裁剪之后配置三个PWM,分别为PWM7、PWM11、PWM12。
设备树编写:
&pwm7{
pinctrl-0 = <&pwm7m0_pins>;//pwm作用的引脚
status = "okay";
}
引脚配置:
pwm7m0_pins->GPIO0_RKPD0
pwm7m1_pins->GPIO4_RKPD4
pwm7m2_pins->GPIO1_RKPC3
额外说明:
pwm开启后会按照从0的 ID号依次生成内核设备!
PWM7 PWM11 PW12
0 1 2
头文件:
#include "linux/pwm.h"
函数功能:向内核申请一个pwm设备,通过ID申请
函数原型:
struct pwm_device *pwm_request( int pwm_id, const char *label );
函数参数:
pwm_id:
申请PWM的ID号,一般从0开始
label:
申请PWM使用的标签名
函数返回值:
内核抽象出来的PWM设备结构体
后续操作PWM都依靠这个结构体
函数功能:设置一个PWM 、总周期、占空比
函数原型:
int pwm_config( struct pwm_device *pwm, int duty_ns, int period_ns )
函数参数:
pwm:
刚才申请得到的PWM的设备结构体
duty_ns:
占空周期的时间
period_ns:
总周期时间
函数返回值:
成功返回0;失败返回非0
其他接口函数:
pwm_free();//释放函数
pwm_enable();//使能
pwm_disable();//失能
PWM设备分别对PWM7 PWM11 PWM12
在sys系统中:
export注册接口文件
unexport取消注册
echo 0 > export 注册 PWM7 的通道 0
echo 0 > unexport 取消注册 PWM7 的通道 0
如果注册成功就会生成 pwm0 这个文件夹
生成pwm0就是sys下的控制接口文件
duty_cycle:占空比
enble:使能 0代表失能 1代表使能
period:总周期
polarity:极性反转;inverse 翻转的 normal正常
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/of.h"
#include "linux/cdev.h"
#include "linux/fs.h"
#include "linux/gpio.h"
#include "linux/of_gpio.h"
#include "linux/device.h"
#include "linux/platform_device.h"
#include "linux/miscdevice.h"
#include "asm/uaccess.h"
#include "linux/input.h"
#include "linux/irq.h"
#include "linux/interrupt.h"
#include "linux/pwm.h"
#define MAX_PWM_VALUE 100000
struct miscdevice misc;
struct file_operations *fop;
struct pwm_device * pwm_dev;//pwm核心结构体
//打开函数
int pwm_open (struct inode *ino, struct file *f)
{
//pwm初始化函数
pwm_config(pwm_dev, 0,MAX_PWM_VALUE);
//使能PWM
pwm_enable(pwm_dev);
return 0;
}
//出口函数
int pwm_close (struct inode *i, struct file *f)
{
pwm_config(pwm_dev, 0,0);//清零
pwm_disable(pwm_dev );
return 0;
}
ssize_t pwm_write (struct file *f, const char __user *buf, size_t size, loff_t *lof)
{
int ret = 0;
uint32 value =0;
ret = copy_from_user(&value,buf,size);
if(value > MAX_PWM_VALUE)
{
return -EIO;
}
ret =ret;
pwm_enable(pwm_dev);
pwm_config(pwm_dev,value,MAX_PWM_VALUE)
return 0;
}
//加载函数
static int __init pwm_init(void)
{
pwm_dev = pwm_request(0,"pwm_led");
if(pwm_dev == NULL)
{
printk("PWM Reuqest Failed\r\n");
return -EINVAL;
}
fop.open = pwm_open;
fop.owner = THIS_MODULE;
fop.release = pwm_close;
fop.write = pwm_write;
misc.minor = 255;
misc.name = "pwm_led";
misc.fops =&fop ;
return misc_register(&misc);
}
//卸载函数
static void __exit pwm_exit(void)
{
misc_deregister(&misc);
pwm_free(pwm_dev);
}
module_init(pwm_init);
module_exit(pwm_exit);
MODULE_LICENSE("GPL");
终端控制法:
#include "stdio.h"
#include
#include
#include
#include "unistd.h"#include "stdint.h"
#include "linux/input.h"
#include
#include
struct input_event myreadvalue;
#define MAX_VALUE 10000
int main()
{
int readvalue = 0;
char buf[128]={0};
system("echo 0 > /sys/class/pwm/pwmchip0/export");
usleep(1000);
system("echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable");
usleep(1000);
system("echo normal > /sys/class/pwm/pwmchip0/pwm0/polarity");
usleep(1000);
system("echo 10000 > /sys/class/pwm/pwmchip0/pwm0/period");
usleep(1000);
while(1)
{
printf("请输入一个占空比的值! :\r\n\t");
scanf("%d",&readvalue);
sprintf(buf,"echo %d > /sys/class/pwm/pwmchip0/pwm0/duty_cycle",readvalue);
system(buf);
memset(buf,0,128);
}
return 0;
}