PWM介紹
- 專(zhuān)欄總目錄
- PWM是脈寬調(diào)制(Pulse Width Modulation)的縮寫(xiě)。它是一種用于控制電子設(shè)備的技術(shù),通過(guò)改變電信號(hào)的脈沖寬度來(lái)實(shí)現(xiàn)對(duì)設(shè)備的控制。
PWM基本概念
PWM信號(hào)由一個(gè)固定頻率的周期性脈沖序列組成,每個(gè)脈沖的寬度(持續(xù)時(shí)間)可以根據(jù)需要進(jìn)行調(diào)節(jié)。調(diào)節(jié)脈沖寬度的比例可以改變平均電壓或電流的大小,從而實(shí)現(xiàn)對(duì)設(shè)備的控制。
當(dāng)談?wù)揚(yáng)WM時(shí),以下三個(gè)關(guān)鍵術(shù)語(yǔ)經(jīng)常被提及:
頻率(Frequency):PWM信號(hào)的頻率是指每秒鐘內(nèi)脈沖的數(shù)量。
周期(Period):PWM信號(hào)的周期是指一個(gè)完整脈沖序列所花費(fèi)的時(shí)間。它是頻率的倒數(shù),以秒為單位表示。周期可以通過(guò)將頻率的倒數(shù)計(jì)算得到,例如,一個(gè)10kHz的PWM信號(hào)的周期為0.1毫秒(100微秒)。
占空比(Duty Cycle):占空比是指PWM信號(hào)中脈沖寬度與周期之間的比例關(guān)系。它表示了脈沖在一個(gè)周期中所占據(jù)的時(shí)間比例,通常以百分比表示。占空比為0%意味著脈沖不存在(完全低電平),而占空比為100%表示脈沖持續(xù)時(shí)間占據(jù)了整個(gè)周期(完全高電平)。在實(shí)際應(yīng)用中,占空比可以在0%到100%之間任意調(diào)整,以實(shí)現(xiàn)所需的控制效果。
PWM驅(qū)動(dòng)
pwm驅(qū)動(dòng)是一個(gè)通用的驅(qū)動(dòng),SOC廠家都會(huì)在SDK里面默認(rèn)打開(kāi)
驅(qū)動(dòng)文件
驅(qū)動(dòng)文件所在位置:
drivers/pwm/pwm-rockchip.c
默認(rèn)SDK已經(jīng)加載好了PWM的驅(qū)動(dòng),下文我們主要注意PWM怎么使用
DTS 節(jié)點(diǎn)配置
DTS 配置參考文檔
Documentation/devicetree/bindings/pwm/pwm.txt
以下為一個(gè)例子的示例
Node name {
compatible = "Driver matching character";
pwms = < &pwmX 0 25000 0 >;
};
&pwmX {
status = "okay";
pinctrl-names = "active";
pinctrl-0 = < &pwmX_pin_pull_down >;
};
pwms的幾個(gè)參數(shù)說(shuō)明如下:
參數(shù) 1,表示 index (per-chip index of the PWM to request),一般是 0,因?yàn)槲覀?Rockchip PWM 每個(gè)chip 只有一個(gè)。
參數(shù) 2,表示 PWM 輸出波形的時(shí)間周期,單位是 ns;例如下面配置的 25000 就是表示想要得到的
PWM 輸出周期是 40K 赫茲。
參數(shù) 3,表示極性,為可選參數(shù);下面例子中的配置為負(fù)極性。
PWM使用
PWM 提供了用戶層的接口,在 /sys/class/pwm/ 節(jié)點(diǎn)下面,PWM 驅(qū)動(dòng)加載成功后,會(huì)在/sys/class/pwm/ 目錄下產(chǎn)生 pwmchip0 目錄;向 export 文件寫(xiě)入 0,就是打開(kāi) pwm 定時(shí)器 0,會(huì)產(chǎn)生一個(gè) pwm0 目錄,相反的往 unexport 寫(xiě)入 0 就會(huì)關(guān)閉 pwm 定時(shí)器了,同時(shí) pwm0 目錄會(huì)
被刪除,該目錄下有以下幾個(gè)文件:
enable:寫(xiě)入 1 使能 pwm,寫(xiě)入 0 關(guān)閉 pwm;
polarity:有 normal 或 inversed兩個(gè)參數(shù)選擇,表示輸出引腳電平翻轉(zhuǎn);
duty_cycle:在 normal 模式下,表示一個(gè)周期內(nèi)高電平持續(xù)的時(shí)間(單位:納秒),在
reversed 模式下,表示一個(gè)周期中低電平持續(xù)的時(shí)間(單位:納秒);
period:表示 pwm 波的周期(單位:納秒);
以下是 pwmchip0 的例子,設(shè)置 pwm0 輸出頻率 100K,占空比 50%, 極性為正極性:
cd /sys/class/pwm/pwmchip0/
echo 0 > export
cd pwm0
echo 10000 > period
echo 5000 > duty_cycle
echo normal > polarity
echo 1 > enable
PWM應(yīng)用實(shí)例
通常電子設(shè)備中應(yīng)用pwm是比較常見(jiàn)的,比如風(fēng)扇電機(jī)控制,電視背光控制, LED 照明調(diào)光、電動(dòng)工具馬達(dá)控制、汽車(chē)加熱器等領(lǐng)域。
這里簡(jiǎn)單介紹一下pwm控制LED燈實(shí)現(xiàn)呼吸燈效果。
呼吸燈需要燈的驅(qū)動(dòng)與PWM的驅(qū)動(dòng)結(jié)合,兩個(gè)驅(qū)動(dòng)之間傳遞數(shù)據(jù),我們可以在驅(qū)動(dòng)中調(diào)用其他的驅(qū)動(dòng)。
led是我需要的設(shè)備,這個(gè)設(shè)備用到了pwm,而pwm是用默認(rèn)的驅(qū)動(dòng)。
硬件上我們?cè)陂_(kāi)發(fā)板找到具有pwm功能的引腳
設(shè)備樹(shù)的修改如下:
/{
breathing_light {
compatible = "lhd,breathing_light_test";
backlight {
pwms = < &pwm8 0 25000 0 >;
pwm-names = "breathing_light";
};
};
};
&pwm8 {
status = "okay";
};
寫(xiě)一個(gè)驅(qū)動(dòng)。內(nèi)部在使用PWM子系統(tǒng)。形成了包含驅(qū)動(dòng)的驅(qū)動(dòng)。
示例代碼
驅(qū)動(dòng)程序
#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" /* 設(shè)備樹(shù)節(jié)點(diǎn)匹配屬性 */
#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 0x05
struct 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);//設(shè)置PWM信號(hào)的極性
pwm_enable(led_dev.red_led_pwm);//啟用指定PWM設(shè)備,使其開(kāi)始輸出PWM信號(hào)。
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)