• Home
Name Date Size #Lines LOC

..--

figures/12-May-2024-

BUILD.gnD12-May-20241.2 KiB3328

README_zh.mdD12-May-20249.5 KiB227196

hdf_pwm_test.cD12-May-20243.8 KiB152116

README_zh.md

1# Niobe407开发板OpenHarmony基于HDF驱动框架编程开发——PWM
2本示例将演示如何在Niobe407开发板上通过HDF驱动框架,使用TIM2和TIM3定时器模拟pwm进行输出。
3
4
5## 编译调试
6- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
7
8     `(Top) → Platform → Board Selection → select board niobe407 → use talkweb niobe407 application → niobe407 application choose`
9
10- 选择 `206_hdf_pwm`
11
12- 在menuconfig的`(Top) → Driver`选项中使能如下配置:
13
14```
15    [*] Enable Driver
16    [*]     HDF driver framework support
17    [*]         Enable HDF platform driver
18    [*]             Enable HDF platform pwm driver
19```
20- 回到sdk根目录,执行`hb build -f`脚本进行编译。
21
22### 运行结果
23
24示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志
25```
26[HDF:I/HDF_LOG_TAG]open pwm 2 success!
27
28[HDF:I/HDF_LOG_TAG]PwmSetConfig success ! duty is 10000000
29
30[HDF:I/HDF_LOG_TAG]open pwm 3 success!
31
32[HDF:I/HDF_LOG_TAG]PwmSetConfig success ! duty is 10000000
33```
34使用示波器接对应的管脚可以观察到对应的PWM输出波形如下图所示
35![image-20220310154004291](figures/pwm2.jpg)
36此图为PWM2的输出波形,频率为20hz, 占空比为20%,对应PA3 引脚
37![image-20220310154004291](figures/pwm3.jpg)
38此图为PWM3的输出波形,频率为10hz, 占空比为10% 对应PA6引脚
39# OpenHarmony驱动子系统开发—PWM
40
41## 概述
42    PWM(Pulse Width Modulator)即脉冲宽度调节器,在HDF框架中,PWM的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,增加内存占用。
43
44## 接口说明
45    1. pwm open初始化函数:DevHandle PwmOpen(uint32_t num);
46        参数说明:
47            num:     PWM设备编号
48            return:  获取成功返回PWM设备句柄,失败返回NULL
49    2. pwm close去初始化函数:void PwmClose(DevHandle handle);
50        参数说明:
51            handle:   pwm设备句柄,
52            return:    无
53    3. 设置PWM设备参数:int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config);
54        参数说明:
55            handle:   pwm设备句柄,
56            *config    参数指针
57            return:    返回0表示设置成功,返回负数表示失败
58## PWM HDF HCS配置文件解析
59- device_uart_info.hcs文件位于/device/board/talkweb/niobe407/sdk/hdf_config/device_pwm_info.hcs,本例子使用的是TIM2和TIM3定时器模拟的PWM信号
60```
61
62root {
63    module = "talkweb,stm32f407";
64    device_info {
65        match_attr = "hdf_manager";
66        template host {
67            hostName = "";
68            priority = 100;
69            template device {
70                template deviceNode {
71                    policy = 0;
72                    priority = 100;
73                    preload = 0;
74                    permission = 0664;
75                    moduleName = "";
76                    serviceName = "";
77                    deviceMatchAttr = "";
78                }
79            }
80        }
81        platform :: host {
82            hostName = "platform_host";
83            priority = 50;
84            device_pwm1 :: device {
85                pwm1 :: deviceNode {  //pwm config
86					 policy = 2;
87					 priority = 100;
88					 moduleName = "NIOBE_HDF_PLATFORM_PWM";
89					 serviceName = "HDF_PLATFORM_PWM_1"; // 编号要与PwmOpen入参一致,否则找不到service
90					 deviceMatchAttr = "config_pwm1";
91                }
92            }
93            device_pwm2 :: device {
94                pwm2 :: deviceNode {  //pwm config
95					 policy = 2;
96					 priority = 100;
97					 moduleName = "NIOBE_HDF_PLATFORM_PWM";
98					 serviceName = "HDF_PLATFORM_PWM_2"; // 编号要与PwmOpen入参一致,否则找不到service
99					 deviceMatchAttr = "config_pwm2";
100                }
101            }
102        }
103    }
104}
105```
106
107- hdf_uart.hcs文件位于/device/board/talkweb/niobe407/sdk/hdf_config/hdf_pwm.hcs,在此文件中配置串口对应的GPIO引脚信息,串口配置信息
108```
109#include "device_pwm_info.hcs"
110root {
111    platform {
112        pwm1_config {
113            gpio_pwm1{ // PWM2 配置的gpio信息
114                // 要配置的引脚个数,接下来的引脚名必须定义成gpio_num_1, gpio_num_2, gpio_num_3...
115                gpio_num_max = 1;
116                // port, pin, mode, speed, outputType, pull, alternate
117                gpio_num_1 = [0, 3, 2, 3, 0, 2, 1]; // tim2 ch4 pa3
118            }
119
120            pwmconfig : gpio_pwm1 {
121                match_attr = "config_pwm1"; // 本驱动默认使用pwm1模式 和上升计数模式
122                pwmTim = 1;  // 定时器ID tim2 0 :tim1, 1:tim2 ..... tim6 和 tim7不可用
123                pwmCh = 3;  // 对应chanel 4 0:ch1 1:ch2 2:ch3 3:ch4
124                prescaler = 4199; // 预分频器 例如tim2 时钟为84M, (84M/(4199+1)) = 20khz, 然后以20khz 为基准 ,tim2-tim7, tim12-tim14为84M,TIM1、TIM8~TIM11 为168M,tim6和tim7不能输出pwm
125                                  // tim1~tim5 tim8 有4个channel tim9,tim12有ch1, ch2,  tim10, tim11,tim13,tim14只有ch1
126            }
127        }
128        pwm2_config {
129            gpio_pwm2{ // pwm3配置的GPIO信息
130                // 要配置的引脚个数,接下来的引脚名必须定义成gpio_num_1, gpio_num_2, gpio_num_3...
131                gpio_num_max = 1;
132                // port, pin, mode, speed, outputType, pull, alternate
133                gpio_num_1 = [0, 6, 2, 3, 0, 2, 2]; // tim3 ch1 pa6
134            }
135
136            pwmconfig2 : gpio_pwm2 {
137                match_attr = "config_pwm2"; // 本驱动默认使用pwm1模式 和上升计数模式
138                pwmTim = 2;  // 定时器ID tim2 0 :tim1, 1:tim2 ..... tim6 和 tim7不可用
139                pwmCh = 0;  // 对应chanel 4 0:ch1 1:ch2 2:ch3 3:ch4
140                prescaler = 8399; // 预分频器 例如tim2 时钟为84M, (84M/(4199+1)) = 20khz, 然后以20khz 为基准,根据在pwmSetconfig 设置的period和duty,来计算频率 ,tim2-tim7, tim12-tim14为84M,TIM1、TIM8~TIM11 为168M,tim6和tim7不能输出pwm
141                                  // tim1~tim5 tim8 有4个channel tim9,tim12有ch1, ch2,  tim10, tim11,tim13,tim14只有ch1 这个值如果16位最大分频数位65535
142            }
143        }
144    }
145}
146
147```
148
149## 例程原理简介
150    NIOBE407开发板有可以使用TIM定时器来产生PWM波形,系统有TIM1和TIM8两个高级定时器,TIM2-TIM5,TIM9-TIM14为通用定时器,TIM6和TIM7是基本定时器,这两个定时器不用做PWM输出,Tim2-Tim7, Tim12-Tim14为84M,TIM1、TIM8~TIM11 为168M,Tim1~Tim5 Tim8 有4个channel Tim9,Tim12有ch1, ch2,  Tim10, Tim11,Tim13,Tim14只有ch1, 本例程使用TIM2的ch4 和 TIM3 的ch1来做示例,具体可前往device\board\talkweb\niobe407\sdk\hdf_config\hdf_pwm.hcs中根据您的开发板原理图进行修改
151
152## 示例代码解析
153```c
154static void* HdfPwmTestEntry(void* arg)
155{
156    int32_t ret;
157
158    uint32_t num;
159    DevHandle handle = NULL;
160
161    struct PwmConfig pcfg;
162    pcfg.duty = 10000000; /*占空时间为10000000纳秒, 占空比为20%*/
163    pcfg.period = 50000000; /*周期为50000000纳秒,计算出1s/50ms = 20hz为频率*/
164    pcfg.number = 0; /*生成无限个方波*/
165    pcfg.polarity = PWM_NORMAL_POLARITY; /*极性为正*/
166    pcfg.status = PWM_ENABLE_STATUS; /*运行状态为启用*/
167
168    /* PWM设备编号,要填写实际平台上的编号 */
169    num = 1; //tim2
170
171    /* 获取PWM设备句柄 */
172    handle = PwmOpen(num);
173    if (handle == NULL) {
174        HDF_LOGE("PwmOpen: failed!\n");
175        return;
176    } else {
177        HDF_LOGI("open pwm %u success!\n", num + 1);
178    }
179
180    /*设置PWM设备参数*/
181    ret = PwmSetConfig(handle, &pcfg);
182    if (ret != 0) {
183        HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret);
184        goto _ERR2;
185    } else {
186        HDF_LOGI("PwmSetConfig success ! duty is %u\n", pcfg.duty);
187    }
188
189    DevHandle handle1 = NULL;
190
191    struct PwmConfig pcfg1;
192    pcfg1.duty = 10000000; /*占空时间为10000000纳秒, 占空比为10%*/
193    pcfg1.period = 100000000; /*周期为100000000纳秒 1s/100ms = 10HZ 频率*/
194    pcfg1.number = 0; /*生成无限个方波*/
195    pcfg1.polarity = PWM_NORMAL_POLARITY; /*极性为正*/
196    pcfg1.status = PWM_ENABLE_STATUS; /*运行状态为启用*/
197
198    /* PWM设备编号,要填写实际平台上的编号 */
199    uint32_t num2 = 2; //tim2
200
201    handle1 = PwmOpen(num2);
202    if (handle1 == NULL) {
203        HDF_LOGE("PwmOpen: failed!\n");
204        return;
205    } else {
206        HDF_LOGI("open pwm %u success!\n", num2 + 1);
207    }
208
209    /*设置PWM设备参数*/
210    ret = PwmSetConfig(handle1, &pcfg1);
211    if (ret != 0) {
212        HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret);
213        goto _ERR1;
214    } else {
215        HDF_LOGI("PwmSetConfig success ! duty is %u\n", pcfg1.duty);
216    }
217
218    while (1) {
219        LOS_TaskDelay(1000);
220    }
221_ERR1:
222    /* 销毁PWM设备句柄 */
223    PwmClose(handle);
224_ERR2:
225    PwmClose(handle1);
226}
227```