• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# PWM
2
3## 概述
4
5### 功能简介
6
7PWM即脉冲宽度调制(Pulse Width Modulation)的缩写,是一种对模拟信号电平进行数字编码并将其转换为脉冲的技术。
8
9PWM接口定义了操作PWM设备的通用方法集合,包括:
10
11- PWM设备句柄获取和释放
12
13- PWM周期、占空比、极性的设置
14
15- PWM使能和关闭
16
17- PWM配置信息的获取和设置
18
19### 基本概念
20
21脉冲是“电脉冲”的简称,指电路中电流或电压短暂起伏的现象,其特点是突变和不连续性。脉冲的种类很多,常见的脉冲波形有:三角脉冲、尖脉冲、矩形脉冲、方形脉冲、梯形脉冲及阶梯脉冲等。脉冲的主要参数包括重复周期T(T=1/F,F为重复频率)、脉冲幅度U、脉冲前沿上升时间ts、后沿下降时间t、脉冲宽度tk等。
22
23### 运作机制
24
25在HDF框架中,PWM接口适配模式采用独立服务模式(如图1所示)。在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDF设备管理器的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
26
27独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为:
28
29- 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。
30
31- device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。
32
33PWM模块各分层作用:
34
35- 接口层提供打开PWM设备、设置PWM设备周期、设置PWM设备占空时间、设置PWM设备极性、设置PWM设备参数、获取PWM设备参数、使能PWM设备、禁止PWM设备、关闭PWM设备的接口。
36
37- 核心层主要提供PWM控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。
38
39- 适配层主要是将钩子函数的功能实例化,实现具体的功能。
40
41**图 1** PWM独立服务模式结构图
42
43![PWM独立服务模式结构图](figures/独立服务模式结构图.png)
44
45## 使用指导
46
47### 场景介绍
48
49通常情况下,在使用马达控制、背光亮度调节时会用到PWM模块。
50
51### 接口说明
52
53PWM模块设备属性如表1所示,PWM模块提供的主要接口如表2所示,具体API详见//drivers/hdf_core/framework/include/platform/pwm_if.h54
55**表 1** PwmConfig结构体介绍
56
57| 名称 | 描述 |
58| -------- | -------- |
59| duty | uint32_t类型,占空时间,以纳秒为单位。 |
60| period | uint32_t类型,PWM周期,以纳秒为单位。 |
61| number | uint32_t类型,要生成的方波数:<br/>-&nbsp;正值:表示将生成指定数量的方波<br/>-&nbsp;0:表示方波将不断产生 |
62| polarity | uint8_t类型,极性:正极性/反极性。 |
63| status | uint8_t类型,状态:启用状态/禁用状态。 |
64
65**表 2** PWM驱动API接口功能介绍
66
67| 接口名 | 接口描述|
68| ------------------------------------------------------------ | ------------------- |
69| DevHandle PwmOpen(uint32_t num) | 打开PWM设备 |
70| void PwmClose(DevHandle handle)| 关闭PWM设备 |
71| int32_t PwmSetPeriod(DevHandle handle, uint32_t period) | 设置PWM设备周期 |
72| int32_t PwmSetDuty(DevHandle handle, uint32_t duty) | 设置PWM设备占空时间 |
73| int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity) | 设置PWM设备极性 |
74| int32_t PwmEnable(DevHandle handle) | 使能PWM设备 |
75| int32_t PwmDisable(DevHandle handle) | 禁用PWM设备 |
76| int32_t PwmSetConfig(DevHandle handle, struct PwmConfig \*config) | 设置PWM设备参数 |
77| int32_t PwmGetConfig(DevHandle handle, struct PwmConfig \*config) | 获取PWM设备参数 |
78
79> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**<br>
80> 本文涉及PWM的所有接口,支持内核态及用户态使用。
81
82### 开发步骤
83
84使用PWM的一般流程如下图所示。
85
86**图 2** PWM使用流程图
87
88![PWM使用流程图](figures/PWM设备使用流程图.png)
89
90#### 获取PWM设备句柄
91
92在操作PWM设备时,首先要调用PwmOpen获取PWM设备句柄,该函数会返回指定设备号的PWM设备句柄。
93
94```c
95DevHandle PwmOpen(uint32_t num);
96```
97
98**表 3** PwmOpen参数和返回值描述
99
100| **参数** | **参数描述** |
101| -------- | -------- |
102| num | uint32_t类型,PWM设备号 |
103| **返回值** | **返回值描述** |
104| handle | 打开PWM设备成功,返回PWM设备句柄 |
105| NULL | 打开PWM设备失败 |
106
107假设系统中的PWM设备号为0,获取该PWM设备句柄的示例如下:
108
109```c
110uint32_t num = 0;         // PWM设备号
111DevHandle handle = NULL;
112
113handle = PwmOpen(num);    // 打开PWM 0设备并获取PWM设备句柄
114if (handle == NULL) {
115    HDF_LOGE("PwmOpen: open pwm_%u failed.\n", num);
116    return HDF_FAILURE;
117}
118```
119
120#### 销毁PWM设备句柄
121
122关闭PWM设备,系统释放对应的资源。
123
124```c
125void PwmClose(DevHandle handle);
126```
127
128**表 4** PwmClose参数描述
129
130| **参数** | **参数描述** |
131| -------- | -------- |
132| handle | DevHandle类型,PWM设备句柄  |
133
134```c
135PwmClose(handle);    // 关闭PWM设备销毁PWM设备句柄
136```
137
138#### 使能PWM设备
139
140```c
141int32_t PwmEnable(DevHandle handle);
142```
143
144**表 5** PwmEnable参数和返回值描述
145
146| **参数** | **参数描述** |
147| -------- | -------- |
148| handle | DevHandle类型,PWM设备句柄 |
149| **返回值** | **返回值描述** |
150| HDF_SUCCESS | 使能PWM设备成功 |
151| 负数 | 使能PWM设备失败 |
152
153```c
154int32_t ret;
155
156ret = PwmEnable(handle);    // 启用PWM设备
157if (ret != HDF_SUCCESS) {
158    HDF_LOGE("PwmEnable: enable pwm failed, ret:%d\n", ret);
159    return ret;
160}
161```
162
163#### 禁用PWM设备
164
165```c
166int32_t PwmDisable(DevHandle handle);
167```
168
169**表 6** PwmDisable参数和返回值描述
170
171| **参数** | **参数描述** |
172| -------- | -------- |
173| handle | DevHandle类型,PWM设备句柄 |
174| **返回值** | **返回值描述** |
175| HDF_SUCCESS | 禁用PWM设备成功 |
176| 负数 | 禁用PWM设备失败 |
177
178```c
179int32_t ret;
180
181ret = PwmDisable(handle);    // 禁用PWM设备
182if (ret != HDF_SUCCESS) {
183    HDF_LOGE("PwmDisable: disable pwm failed, ret:%d\n", ret);
184    return ret;
185}
186```
187
188#### 设置PWM设备周期
189
190```c
191int32_t PwmSetPeriod(DevHandle handle, uint32_t period);
192```
193
194**表 7** PwmSetPeriod参数和返回值描述
195
196| **参数** | **参数描述** |
197| -------- | -------- |
198| handle | DevHandle类型,PWM设备句柄 |
199| period | uint32_t类型,要设置的周期,单位为纳秒 |
200| **返回值** | **返回值描述** |
201| HDF_SUCCESS | 设置PWM设备周期成功 |
202| 负数 | 设置PWM设备周期失败 |
203
204```c
205int32_t ret;
206
207ret = PwmSetPeriod(handle, 50000000);    // 设置周期为50000000纳秒
208if (ret != HDF_SUCCESS) {
209    HDF_LOGE("PwmSetPeriod: pwm set period failed, ret:%d\n", ret);
210    return ret;
211}
212```
213
214#### 设置PWM设备占空时间
215
216```c
217int32_t PwmSetDuty(DevHandle handle, uint32_t duty);
218```
219
220**表 8** PwmSetDuty参数和返回值描述
221
222| **参数** | **参数描述** |
223| -------- | -------- |
224| handle | DevHandle类型,PWM设备句柄 |
225| duty | uint32_t类型,要设置的占空时间,单位为纳秒 |
226| **返回值** | **返回值描述** |
227| HDF_SUCCESS | 设置PWM设备占空时间成功 |
228| 负数 | 设置PWM设备占空时间失败 |
229
230
231```c
232int32_t ret;
233
234ret = PwmSetDuty(handle, 25000000);    // 设置占空时间为25000000纳秒
235if (ret != HDF_SUCCESS) {
236    HDF_LOGE("PwmSetDuty: pwm set duty failed, ret:%d\n", ret);
237    return ret;
238}
239```
240
241#### 设置PWM设备极性
242
243```c
244int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity);
245```
246
247**表 9** PwmSetPolarity参数和返回值描述
248
249| **参数** | **参数描述** |
250| -------- | -------- |
251| handle | DevHandle类型,PWM设备句柄 |
252| polarity | uint8_t类型,要设置的极性,正/反 |
253| **返回值** | **返回值描述** |
254| HDF_SUCCESS | 设置PWM设备极性成功 |
255| 负数 | 设置PWM设备极性失败 |
256
257
258```c
259int32_t ret;
260
261ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY);    // 设置极性为反
262if (ret != HDF_SUCCESS) {
263    HDF_LOGE("PwmSetPolarity: pwm set polarity failed, ret:%d\n", ret);
264    return ret;
265}
266```
267
268#### 设置PWM设备参数
269
270```c
271int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config);
272```
273
274**表 10** PwmSetConfig参数和返回值描述
275
276| **参数** | **参数描述** |
277| -------- | -------- |
278| handle | DevHandle类型,PWM设备句柄 |
279| config | 结构体指针类型,配置参数 |
280| **返回值** | **返回值描述** |
281| HDF_SUCCESS | 设置PWM设备参数成功 |
282| 负数 | 设置PWM设备参数失败 |
283
284```c
285int32_t ret;
286struct PwmConfig pcfg;
287
288pcfg.duty = 25000000;                     // 占空时间为25000000纳秒
289pcfg.period = 50000000;                   // 周期为50000000纳秒
290pcfg.number = 0;                          // 不断产生方波
291pcfg.polarity = PWM_INVERTED_POLARITY;    // 极性为反
292pcfg.status = PWM_ENABLE_STATUS;          // 运行状态为启用
293
294ret = PwmSetConfig(handle, &pcfg);        // 设置PWM设备参数
295if (ret != HDF_SUCCESS) {
296    HDF_LOGE("PwmSetConfig: pwm set config failed, ret:%d\n", ret);
297    return ret;
298}
299```
300
301#### 获取PWM设备参数
302
303```c
304int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config);
305```
306
307**表 11** PwmGetConfig参数和返回值描述
308
309| **参数** | **参数描述** |
310| -------- | -------- |
311| handle | DevHandle类型,PWM设备句柄 |
312| config | 结构体指针类型,配置参数 |
313| **返回值** | **返回值描述** |
314| HDF_SUCCESS | 获取PWM设备参数成功 |
315| 负数 | 获取PWM设备参数失败 |
316
317```c
318int32_t ret;
319struct PwmConfig pcfg;
320
321ret = PwmGetConfig(handle, &pcfg);    // 获取PWM设备参数
322if (ret != HDF_SUCCESS) {
323    HDF_LOGE("PwmGetConfig: pwm get config failed, ret:%d\n", ret);
324    return ret;
325}
326```
327
328## 使用实例
329
330下面将基于Hi3516DV300开发板展示使用PWM完整操作,步骤主要如下:
331
3321. 传入PWM设备号,打开PWM设备并获得PWM设备句柄。
333
3342. 通过PWM设备句柄及待设置的周期,设置PWM设备周期。
335
3363. 通过PWM设备句柄及待设置的占空时间,设置PWM设备占空时间。
337
3384. 通过PWM设备句柄及待设置的极性,设置PWM设备极性。
339
3405. 通过PWM设备句柄及待获取的设备参数,获取PWM设备参数。
341
3426. 通过PWM设备句柄,使能PWM设备。
343
3447. 通过PWM设备句柄及待设置的设备参数,设置PWM设备参数。
345
3468. 通过PWM设备句柄,禁用PWM设备。
347
3489. 通过PWM设备句柄,关闭PWM设备。
349
350```c
351#include "pwm_if.h"                                               // pwm标准接口头文件
352#include "hdf_log.h"                                              // 标准日志打印头文件
353
354static int32_t PwmTestSample(void)
355{
356    int32_t ret;
357    uint32_t num;
358    uint32_t period;
359    uint32_t duty;
360    DevHandle handle = NULL;
361
362    struct PwmConfig pcfg;
363    pcfg.duty = 20000000;                                         // 占空时间为20000000纳秒
364    pcfg.period = 40000000;                                       // 周期为40000000纳秒
365    pcfg.number = 100;                                            // 生成100个方波
366    pcfg.polarity = PWM_NORMAL_POLARITY;                          // 极性为正
367    pcfg.status = PWM_ENABLE_STATUS;                              // 运行状态为启用
368
369    num = 1;                                                      // PWM设备编号,要填写实际平台上的编号
370
371    handle = PwmOpen(num);                                        // 获取PWM设备句柄
372    if (handle == NULL) {
373        HDF_LOGE("PwmTestSample: open pwm_%u fail!\n", num);
374        return HDF_FAILURE;
375    }
376
377    period = 50000000;                                            // 设置周期为50000000纳秒
378    ret = PwmSetPeriod(handle, period);
379    if (ret != HDF_SUCCESS) {
380        HDF_LOGE("PwmTestSample: pwm set period fail, ret:%d\n", ret);
381        goto ERR;
382    }
383
384    duty = 25000000;                                              // 设置占空时间为25000000纳秒
385    ret = PwmSetDuty(handle, duty);
386    if (ret != HDF_SUCCESS) {
387        HDF_LOGE("PwmTestSample: pwm set duty fail, ret:%d\n", ret);
388        goto ERR;
389    }
390
391    ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY);          // 设置极性为反
392    if (ret != HDF_SUCCESS) {
393        HDF_LOGE("PwmTestSample: pwm set polarity fail, ret:%d\n", ret);
394        goto ERR;
395    }
396
397    ret = PwmGetConfig(handle, &pcfg);                            // 获取PWM设备参数
398    if (ret != HDF_SUCCESS) {
399        HDF_LOGE("PwmTestSample: get pwm config fail, ret:%d\n", ret);
400        goto ERR;
401    }
402
403    ret = PwmEnable(handle);                                      // 启用PWM设备
404    if (ret != HDF_SUCCESS) {
405        HDF_LOGE("PwmEnable: enable pwm fail, ret:%d\n", ret);
406        goto ERR;
407    }
408
409    ret = PwmSetConfig(handle, &pcfg);                            // 设置PWM设备参数
410    if (ret != HDF_SUCCESS) {
411        HDF_LOGE("PwmTestSample: set pwm config fail, ret:%d\n", ret);
412        goto ERR;
413    }
414
415    ret = PwmDisable(handle);                                     // 禁用PWM设备
416    if (ret != HDF_SUCCESS) {
417        HDF_LOGE("PwmTestSample: disable pwm fail, ret:%d\n", ret);
418        goto ERR;
419    }
420
421    HDF_LOGD("PwmTestSample: all tests end.");
422ERR:
423    PwmClose(handle);                                             // 销毁PWM设备句柄
424    return ret;
425}
426```
427