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