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/>- 正值:表示将生成指定数量的方波<br/>- 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