文章目錄
11 PWM編程應(yīng)用開發(fā)
11.1 PWM概述
11.1.1 PWM的參數(shù)說明
11.2 用戶層查看PWM
11.3 PWM的SYSFS使用
11.4 PWM應(yīng)用編程
11.4.1 修改設(shè)備樹
11.4.2 修改配置文件
11.4.3 添加驅(qū)動(dòng)
11.4.4 運(yùn)行測試
11 PWM編程應(yīng)用開發(fā)
11.1 PWM概述
? PWM,英文名Pulse Width Modulation,是脈沖寬度調(diào)制縮寫,它是通過對一系列脈沖的寬度進(jìn)行調(diào)制,等效出所需要的波形(包含形狀以及幅值),對模擬信號電平進(jìn)行數(shù)字編碼,也就是說通過調(diào)節(jié)占空比的變化來調(diào)節(jié)信號、能量等的變化,占空比就是指在一個(gè)周期內(nèi),信號處于高電平的時(shí)間占據(jù)整個(gè)信號周期的百分比,例如方波的占空比就是50%。是利用微處理器的數(shù)字輸出來對模擬電路進(jìn)行控制的一種非常有效的技術(shù)。

? PWM信號把模擬信號轉(zhuǎn)化為數(shù)字電路所需要的編碼,現(xiàn)在基本是采用數(shù)字電路,因此在很多場合都采用PWM信號,我們經(jīng)常見到的就是交流調(diào)光電路,也可以說是無級調(diào)速,高電平占多一點(diǎn),也就是占空比大一點(diǎn)亮度就亮一點(diǎn),占空比小一點(diǎn)亮度就沒有那么亮,前提是PWM的頻率要大于我們?nèi)搜圩R(shí)別頻率,要不然會(huì)出現(xiàn)閃爍現(xiàn)象。除了在調(diào)光電路應(yīng)用,還有在直流斬波電路、蜂鳴器驅(qū)動(dòng)、電機(jī)驅(qū)動(dòng)、逆變電路、加濕機(jī)霧化量等都會(huì)有應(yīng)用。

11.1.1 PWM的參數(shù)說明
https://www.kernel.org/doc/Documentation/pwm.txt
period
PWM信號的總周期(讀/寫)。
值以納秒為單位,是活動(dòng)和非活動(dòng)的總和
PWM的時(shí)間。
duty_cycle(占空比)
PWM信號的有效時(shí)間(讀/寫)。
值以納秒為單位,且必須小于周期。
在NORMAL模式下,表示一個(gè)周期內(nèi)高電平持續(xù)的時(shí)間
在INVERTED模式下,表示一個(gè)周期中低電平持續(xù)的時(shí)間
polarity
改變PWM信號的極性(讀/寫)。
寫入此屬性僅在PWM芯片支持更改時(shí)才有效
極性。只有PWM不能改變極性
啟用。值是字符串“normal”或“inversed”。
enable
啟用/禁用PWM信號(讀/寫)。
0 - 禁用
1 - 啟用
11.2 用戶層查看PWM
? 如果在內(nèi)核配置中啟用了CONFIG_SYSFS,則會(huì)提供一個(gè)簡單的sysfs接口來使用用戶空間的PWM。它在/ sys / class / pwm /中公開。每個(gè)被探測的PWM控制器/芯片將被輸出為pwmchipN,其中N是PWM芯片的基礎(chǔ)。你在目錄里面會(huì)發(fā)現(xiàn):
1 echo 0 > /sys/class/pwm/pwmchip0/export /*設(shè)置PWM4輸出,調(diào)出pwm0目錄下設(shè)備節(jié)點(diǎn),用于以下配置 */
2 echo 1000000 >/sys/class/pwm/pwmchip0/pwm0/period /*設(shè)置PWM4一個(gè)周期的持續(xù)時(shí)間,單位為ns,即1K Hz */
3 echo 500000 >/sys/class/pwm/pwmchip0/pwm0/duty_cycle /*設(shè)置一個(gè)周期中的”O(jiān)N”時(shí)間,單位為ns,即占空比=duty_cycle/period=50% */
4 echo 1 >/sys/class/pwm/pwmchip0/pwm0/enable /*設(shè)置PWM4使能 */
11.3 PWM的SYSFS使用
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define dbmsg(fmt, args ...) printf("%s[%d]: "fmt"n", __FUNCTION__, __LINE__,##args)
#define DUTY "duty"
#define PERIOD "1000000"
#define DUTYCYCLE "500000"
#define LENGTH 100
int fd_period = 0,fd_duty = 0,fd_enable = 0,duty_m = 0;
int usage()
{
printf("usage:n");
printf("./pwm-sysfs-test duty <0/1> : 0-->static; 1-->dynamic n");
return 0;
}
int pwm_setup()
{
int fd,ret;
fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
if(fd < 0)
{
dbmsg("open export errorn");
return -1;
}
ret = write(fd, "0", strlen("0"));
if(ret < 0)
{
dbmsg("creat pwm0 errorn");
return -1;
}else
dbmsg("export pwm0 okn");
fd_period = open("/sys/class/pwm/pwmchip0/pwm0/period", O_RDWR);
fd_duty = open("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", O_RDWR);
fd_enable = open("/sys/class/pwm/pwmchip0/pwm0/enable", O_RDWR);
if((fd_period < 0)||(fd_duty < 0)||(fd_enable < 0))
{
dbmsg("open errorn");
return -1;
}
ret = write(fd_period, PERIOD,strlen(PERIOD));
if(ret < 0)
{
dbmsg("change period errorn");
return -1;
}else
dbmsg("change period okn");
ret = write(fd_duty, DUTYCYCLE, strlen(DUTYCYCLE));
if(ret < 0)
{
dbmsg("change duty_cycle errorn");
return -1;
}else
dbmsg("change duty_cycle okn");
ret = write(fd_enable, "1", strlen("1"));
if(ret < 0)
{
dbmsg("enable pwm0 errorn");
return -1;
}else
dbmsg("enable pwm0 okn");
duty_m = atoi(DUTYCYCLE)/2;
printf("duty_m: %d n",duty_m);
return 0;
}
int main ( int argc, char *argv[] )
{
int ret;
int num;
if(argc < 2)
{
usage();
return -1;
}
if(strncmp(argv[1],DUTY, sizeof(DUTY)) == 0)
{
dbmsg("%s", DUTY);
if(argc != 3)
{
usage();
return -1;
}
pwm_setup();
}
return 0;
}
11.4 PWM應(yīng)用編程
The main useful user API are the following:
devm_pwm_get() or pwm_get() / pwm_put(): this API is used to look up, request, then free a PWM device.
pwm_init_state(),pwm_get_state(), pwm_apply_state(): this API is used to initialize, retrieve and apply the current PWM device state.
pwm_config(): this API updates the PWM device configuration (period and duty cycle).
11.4.1 修改設(shè)備樹
beeper {
compatible = "pwm-beeper";
pwms = <&pwm 0 1000000 0>;
pinctrl-names = "default";
pinctrl-0 = <&pwm0_pin>;
};
11.4.2 修改配置文件
Activate PWM framework in the kernel configuration through the Linux menuconfig tool, Menuconfig or how to configure kernel (CONFIG_PWM=y): Device Drivers ---> [*] Pulse-Width Modulation (PWM) Support --->
11.4.3 添加驅(qū)動(dòng)
#include
#include
#include
#include
#include
#include
//#include
#define PWM_ON 0x100001
#define PWM_OFF 0x100002
struct pwm_device *pwm_dev_2;
struct pwm_device *pwm_dev_3;
static long pwm_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
int ret;
switch(cmd) {
case PWM_ON:
ret = pwm_config(pwm_dev_2,200000,500000);
if(ret < 0){
printk("pwm_dev_2 ioctl fail");
return 0;
}
ret = pwm_config(pwm_dev_3,300000,500000);
if(ret < 0){
printk("pwm_dev_3 ioctl fail");
}
pwm_enable(pwm_dev_2);
pwm_enable(pwm_dev_3);
break;
case PWM_OFF:
ret = pwm_config(pwm_dev_2,0,500000);
if(ret < 0){
printk("pwm_dev_2 ioctl fail");
return 0;
}
ret = pwm_config(pwm_dev_3,0,500000);
if(ret < 0){
printk("pwm_dev_3 ioctl fail");
}
pwm_disable(pwm_dev_2);
pwm_disable(pwm_dev_3);
break;
}
return 0;
}
//定義初始化硬件操作方法
static struct file_operations pwm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = pwm_ioctl
};
//定義初始化混雜設(shè)備對象
static struct miscdevice pwm_misc = {
.minor = MISC_DYNAMIC_MINOR, //動(dòng)態(tài)分配次設(shè)備號
.name = "mypwm", //dev/mypwm
.fops = &pwm_fops
};
static int pwm_init(void)
{
int ret;
printk("regisger pwm_misc devicen");
//1.申請pwm資源,設(shè)置輸出為0
pwm_dev_2 = pwm_request(1,"pwm_2");
if(pwm_dev_2 == NULL){
printk("pwm_dev_2 register failn");
}
pwm_dev_3 = pwm_request(2,"pwm_3");
if(pwm_dev_3 == NULL){
printk("pwn_dev_3 register failn");
}
ret = pwm_config(pwm_dev_2,0,500000);
if(ret < 0){
printk("pwm_config_2 init failn");
return 0;
}
ret = pwm_config(pwm_dev_3,0,500000);
if(ret < 0){
printk("pwm_config_3 init failn");
return 0;
}
ret = pwm_enable(pwm_dev_2);
if(ret == 0){
printk("pwm_enable_dev_2 init successn");
}
if(ret < 0 ){
printk("pwm_enable_dev_2 init failn");
return 0;
}
ret = pwm_enable(pwm_dev_3);
if(ret == 0){
printk("pwm_enable_dev_3 init successn");
}
if(ret < 0 ){
printk("pwm_enable_dev_3 init failn");
return 0;
}
//2.注冊混雜設(shè)備
misc_register(&pwm_misc);
return 0;
}
static void pwm_exit(void)
{
printk("unregister pwm_misc devicen");
//1.卸載混雜設(shè)備
misc_deregister(&pwm_misc);
//2.釋放pwm資源
pwm_config(pwm_dev_2,0,500000);
pwm_disable(pwm_dev_2);
pwm_free(pwm_dev_2);
pwm_config(pwm_dev_3,0,500000);
pwm_disable(pwm_dev_3);
pwm_free(pwm_dev_3);
}
module_init(pwm_init);
module_exit(pwm_exit);
MODULE_LICENSE("GPL");
11.4.4 運(yùn)行測試
#include
#include
#include
#include
#define PWM_ON 0x100001
#define PWM_OFF 0x100002
int main(void)
{
int fd;
int a;
fd = open("/dev/mypwm", O_RDWR);
if (fd < 0)
return -1;
while(1) {
ioctl(fd, PWM_ON);
}
close(fd);
return 0;
}
審核編輯 黃昊宇
-
PWM
+關(guān)注
關(guān)注
116文章
5874瀏覽量
225841 -
Linux
+關(guān)注
關(guān)注
88文章
11772瀏覽量
219129
發(fā)布評論請先 登錄
明德?lián)P視頻分享點(diǎn)撥FPGA課程--第十一章 ?Signaltapll的使用技巧
至芯科技之a(chǎn)ltera 系列FPGA教程 第十一篇 添加激勵(lì)
視頻詳解:上海尤老師verilog入門到實(shí)戰(zhàn)第十一課
「正點(diǎn)原子Linux連載」第十一章模仿STM32驅(qū)動(dòng)開發(fā)格式實(shí)驗(yàn)
藍(lán)橋杯第十一屆省賽單片機(jī)組
迅為iMX6ULL開發(fā)板使用手冊資料下載
【傾心力作!】i.MX8MM嵌入式linux開發(fā)指南+全覆蓋開發(fā)資料
更新 | 持續(xù)開源 迅為RK3568驅(qū)動(dòng)指南第十一篇-pinctrl子系統(tǒng)
三相電路原理(第十一章)
模擬電路網(wǎng)絡(luò)課件 第十一節(jié):小信號模型分析法
第十一屆高交會(huì)電子展今日開鑼
第十一屆藍(lán)橋杯嵌入式設(shè)計(jì)與開發(fā) (省賽)
【正點(diǎn)原子FPGA連載】第十一章觸摸按鍵控制LED燈實(shí)驗(yàn) -摘自【正點(diǎn)原子】新起點(diǎn)之FPGA開發(fā)指南_V2.1
Linux應(yīng)用開發(fā)【第十一章】PWM編程應(yīng)用開發(fā)
評論