• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# PWM
2
3## Overview
4
5### Function
6
7Pulse width modulation (PWM) is a technology that digitally encodes analog signal levels and converts them into pulses.
8
9The PWM module provides a set of APIs for operating a PWM device, including:
10
11- Opening or closing a PWM device
12- Setting the PWM period, signal ON-state time, and polarity
13- Enabling or disabling a PWM device
14- Obtaining and setting PWM parameters
15
16### Basic Concepts
17
18A pulse (electrical pulse) is a burst of current or voltage, characterized by sudden change and discontinuity. There are many types of pulses. Common pulses include triangular, sharp, rectangular, square, trapezoidal, and zigzag pulses. Main pulse parameters include the repetition period **T** (**T** = 1/**F**, where **F** is the pulse repetition frequency), pulse amplitude **U**, rise time **ts** at the leading edge, fall time **t** at the trailing edge, and pulse width **tk**.
19
20### Working Principles
21
22In the Hardware Driver Foundation (HDF), the PWM uses the independent service mode (see Figure 1) for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage.
23
24In the independent service mode, the core layer does not publish a service for the upper layer. Therefore, a service must be published for each controller. To achieve this purpose:
25
26- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services.
27- The **policy** field of **deviceNode** in the **device_info.hcs** file can be **1** or **2**, but not **0**.
28
29The PWM module is divided into the following layers:
30
31- Interface layer: provides APIs for opening or closing a PWM device, setting the PWM period, signal ON-state time, PWM device polarity, or PWM device parameters, obtaining PWM device parameters, and enabling or disabling a PWM device
32- Core layer: provides the capabilities of adding or removing a PWM controller and managing PWM devices. The core layer interacts with the adaptation layer through hook functions.
33- Adaptation layer: instantiates the hook functions to implement specific features.
34
35**Figure 1** Independent service mode
36
37![image1](figures/independent-service-mode.png "PWM independent service mode")
38
39## Usage Guidelines
40
41### When to Use
42
43The PWM module is used for controlling vibrators and adjusting backlight brightness in smart devices.
44
45### Available APIs
46
47**Table 1** describes the **PwmConfig** structure, which defines the PWM device attributes. **Table 2** describes the APIs provided by the PWM module.
48
49**Table 1** PwmConfig structure
50
51| Parameter| Description|
52| -------- | -------- |
53| duty | Time that a signal is in the ON state, in ns.|
54| period | Time for a signal to complete an on-and-off cycle, in ns.|
55| number | Number of square waves to generate.<br>- Positive value: indicates the number of square waves to generate.<br>- **0**: indicates that square waves are generated continuously.|
56| polarity | PWM signal polarity, which can be normal or reverted. <br>A signal with normal polarity starts high for the duration of the duty cycle and goes low for the remaining of the period. <br>A signal with inverted polarity starts low for the duration of the duty cycle and goes high for the remaining of the period.|
57| status | PWM device status, which can be enabled or disabled.|
58
59**Table 2** PWM driver APIs
60
61| API                                                      |                     |
62| ------------------------------------------------------------ | ------------------- |
63| DevHandle PwmOpen(uint32_t num)                             | Opens a PWM device.        |
64| void PwmClose(DevHandle handle)                             | Closes a PWM device.        |
65| int32_t PwmSetPeriod(DevHandle handle, uint32_t period)     | Sets the PWM period.    |
66| int32_t PwmSetDuty(DevHandle handle, uint32_t duty)         | Sets the signal ON-state time.|
67| int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity)  | Sets the PWM signal polarity.    |
68| int32_t PwmEnable(DevHandle handle)                         | Enables a PWM device.        |
69| int32_t PwmDisable(DevHandle handle)                        | Disables a PWM device.        |
70| int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config) | Sets PWM device parameters.    |
71| int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config) | Obtains PWM device parameters.    |
72
73> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
74>
75> All the PWM APIs described in this document can be used in kernel mode and user mode.
76
77### How to Develop
78
79The following figure shows how to use PWM APIs.
80
81**Figure 2** Using PWM APIs
82
83![image2](figures/using-PWM-process.png)
84
85#### Opening a PWM Device
86
87Before performing operations on a PWM device, use **PwmOpen()** to obtain the device handle.
88
89```c
90DevHandle PwmOpen(uint32_t num);
91```
92
93**Table 3** Description of PwmOpen
94
95| **Parameter**| **Description**|
96| -------- | -------- |
97| num        | PWM device number.            |
98| **Return Value** | **Description**         |
99| handle     | The operation is successful. The PWM device handle is returned.|
100| NULL       | The operation fails.               |
101
102Example: Open PWM device 0.
103
104```c
105uint32_t num = 0;         // PWM device number.
106DevHandle handle = NULL;
107
108handle = PwmOpen(num);    // Open PWM device 0 and obtain the device handle.
109if (handle  == NULL) {
110    HDF_LOGE("PwmOpen: open pwm_%u failed.\n", num);
111    return;
112}
113```
114
115#### Closing a PWM Device
116
117Use **PwmClose()** to close a PWM device to release resources.
118
119```c
120void PwmClose(DevHandle handle);
121```
122
123**Table 4** Description of PwmClose
124
125| **Parameter**| **Description**|
126| -------- | -------- |
127| handle   | Handle of the PWM device to close. |
128
129```c
130PwmClose(handle);    // Close the PWM device and destroy the PWM device handle.
131```
132
133#### Enabling a PWM Device
134
135```c
136int32_t PwmEnable(DevHandle handle);
137```
138
139**Table 5** Description of PwmEnable
140
141| **Parameter**| **Description**|
142| -------- | -------- |
143| handle     | PWM device handle.   |
144| **Return Value** | **Description**|
145| HDF_SUCCESS          | The operation is successful.      |
146| Negative number      | The operation fails.      |
147
148```c
149int32_t ret;
150
151ret = PwmEnable(handle);    // Enable the PWM device.
152if (ret != HDF_SUCCESS) {
153    HDF_LOGE("PwmEnable: enable pwm failed, ret:%d\n", ret);
154    return ret;
155}
156```
157
158#### Disabling a PWM Device
159
160```c
161int32_t PwmDisable(DevHandle handle);
162```
163
164**Table 6** Description of PwmDisable
165
166| **Parameter**| **Description**|
167| -------- | -------- |
168| handle     | PWM device handle.   |
169| **Return Value** | **Description**|
170| HDF_SUCCESS          | The operation is successful.      |
171| Negative number      | The operation fails.      |
172
173```c
174int32_t ret;
175
176ret = PwmDisable(handle);    // Disable the PWM device.
177if (ret != HDF_SUCCESS) {
178    HDF_LOGE("PwmDisable: disable pwm failed, ret:%d\n", ret);
179    return ret;
180}
181```
182
183#### Setting the PWM Period
184
185```c
186int32_t PwmSetPeriod(DevHandle handle, uint32_t period);
187```
188
189**Table 7** Description of PwmSetPeriod
190
191| **Parameter**| **Description**|
192| -------- | -------- |
193| handle     | PWM device handle.             |
194| period     | PWM period to set, in ns.|
195| **Return Value**| **Description**          |
196| HDF_SUCCESS          | The operation is successful.                |
197| Negative number      | The operation fails.                |
198
199```c
200int32_t ret;
201
202ret = PwmSetPeriod(handle, 50000000);    // Set the PWM period to 50,000,000 ns.
203if (ret != HDF_SUCCESS) {
204    HDF_LOGE("PwmSetPeriod: pwm set period failed, ret:%d\n", ret);
205    return ret;
206}
207```
208
209#### Setting the Signal ON-State Time
210
211```c
212int32_t PwmSetDuty(DevHandle handle, uint32_t duty);
213```
214
215**Table 8** Description of PwmSetDuty
216
217| **Parameter**| **Description**|
218| -------- | -------- |
219| handle     | PWM device handle.                 |
220| duty       | Time that a signal is in the ON state, in ns.|
221| **Return Value**| **Description**              |
222| HDF_SUCCESS          | The operation is successful.                    |
223| Negative number      | The operation fails.                    |
224
225
226```c
227int32_t ret;
228
229ret = PwmSetDuty(handle, 25000000);    // Set the signal ON-state time to 25,000,000 ns.
230if (ret != HDF_SUCCESS) {
231    HDF_LOGE("PwmSetDuty: pwm set duty failed, ret:%d\n", ret);
232    return ret;
233}
234```
235
236#### Setting the PWM Signal Polarity
237
238```c
239int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity);
240```
241
242**Table 9** Description of PwmSetPolarity
243
244| **Parameter**| **Description**|
245| -------- | -------- |
246| handle     | PWM device handle.        |
247| polarity   | Polarity to set, which can be **PWM\_NORMAL\_POLARITY** or **PWM\_INVERTED\_POLARITY**.|
248| **Return Value**| **Description**     |
249| HDF_SUCCESS          | The operation is successful.           |
250| Negative number      | The operation fails.           |
251
252
253```c
254int32_t ret;
255
256ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY);    // Set the PWM signal polarity to inverted.
257if (ret != HDF_SUCCESS) {
258    HDF_LOGE("PwmSetPolarity: pwm set polarity failed, ret:%d\n", ret);
259    return ret;
260}
261```
262
263#### Setting PWM Device Parameters
264
265```c
266int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config);
267```
268
269**Table 10** Description of PwmSetConfig
270
271| **Parameter**| **Description**|
272| -------- | -------- |
273| handle     | PWM device handle.   |
274| \*config   | Pointer to the PWM parameters to set.      |
275| **Return Value**| **Description**|
276| HDF_SUCCESS          | The operation is successful.      |
277| Negative number      | The operation fails.      |
278
279```c
280int32_t ret;
281struct PwmConfig pcfg;
282
283The pcfg.duty = 25000000;               // Set the signal ON-state time to 25,000,000 ns.
284pcfg.period = 50000000;                 // Set the PWM period to 50,000,000 ns.
285pcfg.number = 0;                        // Generate square waves continuously.
286pcfg.polarity = PWM_INVERTED_POLARITY;  // Set the PWM signal polarity to inverted.
287pcfg.status = PWM_ENABLE_STATUS;        // Enable PWM.
288
289ret = PwmSetConfig(handle, &pcfg);      // Set PWM device parameters.
290if (ret != HDF_SUCCESS) {
291    HDF_LOGE("PwmSetConfig: pwm set config failed, ret:%d\n", ret);
292    return ret;
293}
294```
295
296#### Obtaining PWM Device Parameters
297
298```c
299int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config);
300```
301
302**Table 11** Description of PwmGetConfig
303
304| **Parameter**| **Description**|
305| -------- | -------- |
306| handle     | PWM device handle.   |
307| \*config   | Pointer to the PWM parameters obtained.      |
308| **Return Value**| **Description**|
309| HDF_SUCCESS          | The operation is successful.      |
310| Negative number      | The operation fails.      |
311
312```c
313int32_t ret;
314struct PwmConfig pcfg;
315
316ret = PwmGetConfig(handle, &pcfg);    // Obtain PWM device parameters.
317if (ret != HDF_SUCCESS) {
318    HDF_LOGE("PwmGetConfig: pwm get config failed, ret:%d\n", ret);
319    return ret;
320}
321```
322
323## Example
324
325The following uses the Hi3516D V300 development board as an example to describe how to use the PWM. The procedure is as follows:
326
3271. Open a PWM device and obtain the PWM device handle.
3282. Set the PWM device period.
3293. Set the signal ON-state time for the PWM device.
3304. Set the signal polarity for the PWM device.
3315. Obtain the PWM device parameters.
3326. Enable the PWM device.
3337. Set the PWM device parameters.
3348. Disable the PWM device.
3359. Close the PWM device.
336
337```c
338#include "pwm_if.h"                                              // Header file of PWM standard APIs.
339#include "hdf_log.h"                                             // Header file of the HDF log APIs.
340
341static int32_t PwmTestSample(void)
342{
343    int32_t ret;
344    uint32_t num;
345    uint32_t period
346    DevHandle handle = NULL;
347
348    struct PwmConfig pcfg;
349    pcfg.duty = 20000000;                                        // Set the signal ON-state time to 20,000,000 ns.
350    pcfg.period = 40000000;                                      // Set the PWM period to 40,000,000 ns.
351    pcfg.number = 100;                                           // Generate 100 square waves continuously.
352    pcfg.polarity = PWM_NORMAL_POLARITY;                         // Set the PWM signal polarity to normal.
353    pcfg.status = PWM_ENABLE_STATUS;                             // Enable the PWM device.
354
355    num = 1;                                                     // PWM device number.
356
357    handle = PwmOpen(num);                                       // Open a PWM device.
358    if (handle == NULL) {
359        HDF_LOGE("PwmOpen: open pwm_%u failed!\n", num);
360        return;
361    }
362
363    ret = PwmSetPeriod(handle, 50000000);                        // Set the PWM period to 50,000,000 ns.
364    if (ret != HDF_SUCCESS) {
365        HDF_LOGE("PwmSetPeriod: pwm set period failed, ret %d\n", ret);
366        goto ERR;
367    }
368
369    ret = PwmSetDuty(handle, 25000000);                          // Set the signal ON-state time to 25,000,000 ns.
370    if (ret != HDF_SUCCESS) {
371        HDF_LOGE("PwmSetDuty: pwm set duty failed, ret %d\n", ret);
372        goto ERR;
373    }
374
375    ret = PwmSetPolarity(handle, PWM_INVERTED_POLARITY);         // Set the PWM signal polarity to inverted.
376    if (ret != HDF_SUCCESS) {
377        HDF_LOGE("PwmSetPolarity: pwm set polarity failed, ret %d\n", ret);
378        goto ERR;
379    }
380
381    ret = PwmGetConfig(handle, &pcfg);                           // Obtain PWM device parameters.
382    if (ret != HDF_SUCCESS) {
383        HDF_LOGE("PwmGetConfig: get pwm config failed, ret %d\n", ret);
384        goto ERR;
385    }
386
387    ret = PwmEnable(handle);                                     // Enable the PWM device.
388    if (ret != HDF_SUCCESS) {
389        HDF_LOGE("PwmEnable: enable pwm failed, ret %d\n", ret);
390        goto ERR;
391    }
392
393    ret = PwmSetConfig(handle, &pcfg);                           // Set PWM device parameters.
394    if (ret != HDF_SUCCESS) {
395        HDF_LOGE("PwmSetConfig: set pwm config failed, ret %d\n", ret);
396        goto ERR;
397    }
398
399    ret = PwmDisable(handle);                                    // Disable the PWM device.
400    if (ret != HDF_SUCCESS) {
401        HDF_LOGE("PwmDisable: disable pwm failed, ret %d\n", ret);
402        goto ERR;
403    }
404
405ERR:
406    PwmClose(handle);                                            // Close the PWM device.
407    return ret;
408}
409```
410