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