From c905a09a24eec7f42e2bf5016eefc0e7384ab580 Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Thu, 24 May 2018 15:30:06 +0800 Subject: [PATCH] feat(pwm): update pwm lib for release/v2.xx 1. Add API to stop PWM. 2. Add API to set the phase of each PWM channel. 3. Add pwm example. --- examples/pwm_test/Makefile | 128 ++++++++++++++ examples/pwm_test/gen_misc.bat | 172 +++++++++++++++++++ examples/pwm_test/gen_misc.sh | 191 +++++++++++++++++++++ examples/pwm_test/include/user_config.h | 29 ++++ examples/pwm_test/readme.txt | 56 ++++++ examples/pwm_test/user/Makefile | 44 +++++ examples/pwm_test/user/user_main.c | 144 ++++++++++++++++ include/espressif/pwm.h | 217 ++++++++++++++++-------- lib/libpwm.a | Bin 9282 -> 16776 bytes 9 files changed, 908 insertions(+), 73 deletions(-) create mode 100644 examples/pwm_test/Makefile create mode 100755 examples/pwm_test/gen_misc.bat create mode 100755 examples/pwm_test/gen_misc.sh create mode 100644 examples/pwm_test/include/user_config.h create mode 100644 examples/pwm_test/readme.txt create mode 100644 examples/pwm_test/user/Makefile create mode 100644 examples/pwm_test/user/user_main.c diff --git a/examples/pwm_test/Makefile b/examples/pwm_test/Makefile new file mode 100644 index 00000000..39547c65 --- /dev/null +++ b/examples/pwm_test/Makefile @@ -0,0 +1,128 @@ +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of object file images to be generated () +# GEN_BINS - list of binaries to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +TARGET = eagle +#FLAVOR = release +FLAVOR = debug + +#EXTRA_CCFLAGS += -u + +ifndef PDIR # { +GEN_IMAGES= eagle.app.v6.out +GEN_BINS= eagle.app.v6.bin +SPECIAL_MKTARGETS=$(APP_MKTARGETS) +SUBDIRS= \ + user +endif # } PDIR + +LDDIR = $(SDK_PATH)/ld + +CCFLAGS += -Os + +TARGET_LDFLAGS = \ + -nostdlib \ + -Wl,-EL \ + --longcalls \ + --text-section-literals + +ifeq ($(FLAVOR),debug) + TARGET_LDFLAGS += -g -O2 +endif + +ifeq ($(FLAVOR),release) + TARGET_LDFLAGS += -g -O0 +endif + +COMPONENTS_eagle.app.v6 = \ + user/libuser.a + +LINKFLAGS_eagle.app.v6 = \ + -L$(SDK_PATH)/lib \ + -Wl,--gc-sections \ + -nostdlib \ + -T$(LD_FILE) \ + -Wl,--no-check-sections \ + -u call_user_start \ + -Wl,-static \ + -Wl,--start-group \ + -lcirom \ + -lcrypto \ + -lespconn \ + -lespnow \ + -lfreertos \ + -lgcc \ + -lhal \ + -ljson \ + -llwip \ + -lmain \ + -lmirom \ + -lnet80211 \ + -lnopoll \ + -lphy \ + -lpp \ + -lsmartconfig \ + -lspiffs \ + -lssl \ + -lwpa \ + -lwps \ + -lpwm \ + $(DEP_LIBS_eagle.app.v6) \ + -Wl,--end-group + +DEPENDS_eagle.app.v6 = \ + $(LD_FILE) \ + $(LDDIR)/eagle.rom.addr.v6.ld + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# + +#UNIVERSAL_TARGET_DEFINES = \ + +# Other potential configuration flags include: +# -DTXRX_TXBUF_DEBUG +# -DTXRX_RXBUF_DEBUG +# -DWLAN_CONFIG_CCX +CONFIGURATION_DEFINES = -DICACHE_FLASH + +DEFINES += \ + $(UNIVERSAL_TARGET_DEFINES) \ + $(CONFIGURATION_DEFINES) + +DDEFINES += \ + $(UNIVERSAL_TARGET_DEFINES) \ + $(CONFIGURATION_DEFINES) + + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +sinclude $(SDK_PATH)/Makefile + +.PHONY: FORCE flash +FORCE: + diff --git a/examples/pwm_test/gen_misc.bat b/examples/pwm_test/gen_misc.bat new file mode 100755 index 00000000..fbb53be7 --- /dev/null +++ b/examples/pwm_test/gen_misc.bat @@ -0,0 +1,172 @@ +@echo off + +Rem ******NOTICE****** +Rem MUST set SDK_PATH & BIN_PATH firstly!!! +Rem example: +Rem set SDK_PATH=/c/esp_iot_sdk_freertos +Rem set BIN_PATH=/c/esp8266_bin + +set SDK_PATH="" +set BIN_PATH="" + +echo gen_misc.bat version 20150911 +echo . + +if not %SDK_PATH% == "" ( + echo SDK_PATH: %SDK_PATH% +) else ( + echo ERROR: Please set SDK_PATH in gen_misc.bat firstly, exit!!! + goto end +) + +if not %BIN_PATH% == "" ( + echo BIN_PATH: %BIN_PATH% +) else ( + echo ERROR: Please set BIN_PATH in gen_misc.bat firstly, exit!!! + goto end +) + +echo . +echo Please check SDK_PATH/BIN_PATH, enter (Y/y) to continue: +set input=default +set /p input= + +if not %input% == Y ( + if not %input% == y ( + goto end + ) +) + +echo . +echo Please follow below steps(1-5) to generate specific bin(s): +echo STEP 1: use boot_v1.2+ by default +set boot=new + +echo boot mode: %boot% +echo. + +echo STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin) +set input=default +set /p input=enter (0/1/2, default 0): + +if %input% equ 1 ( + if %boot% equ none ( + set app=0 + echo choose no boot before + echo generate bin: eagle.flash.bin+eagle.irom0text.bin + ) else ( + set app=1 + echo generate bin: user1.bin + ) +) else ( +if %input% equ 2 ( + if %boot% equ none ( + set app=0 + echo choose no boot before + echo generate bin: eagle.flash.bin+eagle.irom0text.bin + ) else ( + set app=2 + echo generate bin: user2.bin + ) +) else ( + if %boot% neq none ( + set boot=none + echo ignore boot + ) + set app=0 + echo generate bin: eagle.flash.bin+eagle.irom0text.bin +)) + +echo. + +echo STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz) +set input=default +set /p input=enter (0/1/2/3, default 2): + +if %input% equ 0 ( + set spi_speed=20 +) else ( +if %input% equ 1 ( + set spi_speed=26.7 +) else ( +if %input% equ 3 ( + set spi_speed=80 +) else ( + set spi_speed=40 +))) + +echo spi speed: %spi_speed% MHz +echo. + +echo STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT) +set input=default +set /p input=enter (0/1/2/3, default 0): + +if %input% equ 1 ( + set spi_mode=QOUT +) else ( +if %input% equ 2 ( + set spi_mode=DIO +) else ( +if %input% equ 3 ( + set spi_mode=DOUT +) else ( + set spi_mode=QIO +))) + +echo spi mode: %spi_mode% +echo. + +echo STEP 5: choose flash size and map +echo 0= 512KB( 256KB+ 256KB) +echo 2=1024KB( 512KB+ 512KB) +echo 3=2048KB( 512KB+ 512KB) +echo 4=4096KB( 512KB+ 512KB) +echo 5=2048KB(1024KB+1024KB) +echo 6=4096KB(1024KB+1024KB) +set input=default +set /p input=enter (0/1/2/3/4/5/6, default 0): + +if %input% equ 2 ( + set spi_size_map=2 + echo spi size: 1024KB + echo spi ota map: 512KB + 512KB +) else ( + if %input% equ 3 ( + set spi_size_map=3 + echo spi size: 2048KB + echo spi ota map: 512KB + 512KB + ) else ( + if %input% equ 4 ( + set spi_size_map=4 + echo spi size: 4096KB + echo spi ota map: 512KB + 512KB + ) else ( + if %input% equ 5 ( + set spi_size_map=5 + echo spi size: 2048KB + echo spi ota map: 1024KB + 1024KB + ) else ( + if %input% equ 6 ( + set spi_size_map=6 + echo spi size: 4096KB + echo spi ota map: 1024KB + 1024KB + ) else ( + set spi_size_map=0 + echo spi size: 512KB + echo spi ota map: 256KB + 256KB + ) + ) + ) + ) +) + +echo. +echo start... +echo. + +make clean + +make COMPILE=xcc BOOT=%boot% APP=%app% SPI_SPEED=%spi_speed% SPI_MODE=%spi_mode% SPI_SIZE_MAP=%spi_size_map% + +:end \ No newline at end of file diff --git a/examples/pwm_test/gen_misc.sh b/examples/pwm_test/gen_misc.sh new file mode 100755 index 00000000..11bd9d0c --- /dev/null +++ b/examples/pwm_test/gen_misc.sh @@ -0,0 +1,191 @@ +#!/bin/bash + +:< + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __USER_CONFIG_H__ +#define __USER_CONFIG_H__ + +#endif + diff --git a/examples/pwm_test/readme.txt b/examples/pwm_test/readme.txt new file mode 100644 index 00000000..288a84cf --- /dev/null +++ b/examples/pwm_test/readme.txt @@ -0,0 +1,56 @@ +This is a simple project template. + +sample_lib is an example for multi-level folder Makefile, notice the folder structure and each Makefile, you can get the clue. + + +HOWTO: +1. Copy this folder to anywhere. +Example: + Copy to ~/workspace/project_template + You can rename this folder as you like. + +2. Export SDK_PATH and BIN_PATH. +Example: + Your SDK path is ~/esp_iot_rtos_sdk, and want generate bin at ~/esp8266_bin. + Do follow steps: + 1>. export SDK_PATH=~/esp_iot_rtos_sdk + 2>. export BIN_PATH=~/esp8266_bin + SDK and project are seperate, you can update SDK without change your project. + +3. Enter project_template folder, run ./gen_misc.sh, and follow the tips and steps. + + +Compile Options: +(1) COMPILE + Possible value: xcc + Default value: + If not set, use gcc by default. + +(2) BOOT + Possible value: none/old/new + none: no need boot + old: use boot_v1.1 + new: use boot_v1.2 + Default value: new + +(3) APP + Possible value: 0/1/2 + 0: original mode, generate eagle.app.v6.flash.bin and eagle.app.v6.irom0text.bin + 1: generate user1 + 2: generate user2 + Default value: 0 + +(3) SPI_SPEED + Possible value: 20/26.7/40/80 + Default value: 40 + +(4) SPI_MODE + Possible value: QIO/QOUT/DIO/DOUT + Default value: QIO + +(4) SPI_SIZE_MAP + Possible value: 0/2/3/4/5/6 + Default value: 0 + +For example: + make COMPILE=gcc BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=QIO SPI_SIZE_MAP=0 diff --git a/examples/pwm_test/user/Makefile b/examples/pwm_test/user/Makefile new file mode 100644 index 00000000..dd3837c7 --- /dev/null +++ b/examples/pwm_test/user/Makefile @@ -0,0 +1,44 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = libuser.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/examples/pwm_test/user/user_main.c b/examples/pwm_test/user/user_main.c new file mode 100644 index 00000000..3627baf7 --- /dev/null +++ b/examples/pwm_test/user/user_main.c @@ -0,0 +1,144 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2015 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "esp_common.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "pwm.h" + +#define PWM_0_OUT_IO_MUX PERIPHS_IO_MUX_MTDI_U +#define PWM_0_OUT_IO_NUM 12 +#define PWM_0_OUT_IO_FUNC FUNC_GPIO12 + +#define PWM_1_OUT_IO_MUX PERIPHS_IO_MUX_MTCK_U +#define PWM_1_OUT_IO_NUM 13 +#define PWM_1_OUT_IO_FUNC FUNC_GPIO13 + +#define PWM_2_OUT_IO_MUX PERIPHS_IO_MUX_MTMS_U +#define PWM_2_OUT_IO_NUM 14 +#define PWM_2_OUT_IO_FUNC FUNC_GPIO14 + +#define PWM_3_OUT_IO_MUX PERIPHS_IO_MUX_MTDO_U +#define PWM_3_OUT_IO_NUM 15 +#define PWM_3_OUT_IO_FUNC FUNC_GPIO15 + +//PWM period 500us(2Khz) +#define PWM_PERIOD (500) + +/****************************************************************************** + * FunctionName : user_rf_cal_sector_set + * Description : SDK just reversed 4 sectors, used for rf init data and paramters. + * We add this function to force users to set rf cal sector, since + * we don't know which sector is free in user's application. + * sector map for last several sectors : ABCCC + * A : rf cal + * B : rf init data + * C : sdk parameters + * Parameters : none + * Returns : rf cal sector +*******************************************************************************/ +uint32 user_rf_cal_sector_set(void) +{ + flash_size_map size_map = system_get_flash_size_map(); + uint32 rf_cal_sec = 0; + + switch (size_map) { + case FLASH_SIZE_4M_MAP_256_256: + rf_cal_sec = 128 - 5; + break; + + case FLASH_SIZE_8M_MAP_512_512: + rf_cal_sec = 256 - 5; + break; + + case FLASH_SIZE_16M_MAP_512_512: + case FLASH_SIZE_16M_MAP_1024_1024: + rf_cal_sec = 512 - 5; + break; + + case FLASH_SIZE_32M_MAP_512_512: + case FLASH_SIZE_32M_MAP_1024_1024: + rf_cal_sec = 1024 - 5; + break; + case FLASH_SIZE_64M_MAP_1024_1024: + rf_cal_sec = 2048 - 5; + break; + case FLASH_SIZE_128M_MAP_1024_1024: + rf_cal_sec = 4096 - 5; + break; + default: + rf_cal_sec = 0; + break; + } + + return rf_cal_sec; +} +/****************************************************************************** + * FunctionName : user_init + * Description : entry of user application, init user function here + * Parameters : none + * Returns : none +*******************************************************************************/ + +//pwm out_put io +uint32 io_info[][3] = { + { PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC, PWM_0_OUT_IO_NUM }, + { PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC, PWM_1_OUT_IO_NUM }, + { PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC, PWM_2_OUT_IO_NUM }, + { PWM_3_OUT_IO_MUX, PWM_3_OUT_IO_FUNC, PWM_3_OUT_IO_NUM }, +}; + +//dutys table +uint32 dutys[][4] = { + {250, 250, 250, 250}, +}; + +//phase table +int phase[][4] = { + {0, 0, 50, -50}, +}; + +void user_init(void) +{ + printf("SDK version:%s\n", system_get_sdk_version()); + pwm_init(PWM_PERIOD, dutys[0], 4, io_info); + pwm_set_channel_reverse(0x1<<0); + pwm_set_phases(phase[0]); + pwm_start(); + int count = 0; + while(1) { + if(count == 20) { + //channel0, 1 output hight level. + //channel2, 3 output low level. + pwm_stop(0x3); + printf("PWM stop\n"); + } else if(count == 30){ + pwm_start(); + printf("PWM re-start\n"); + count = 0; + } + count++; + vTaskDelay(1000 / portTICK_RATE_MS); + } +} diff --git a/include/espressif/pwm.h b/include/espressif/pwm.h index 629c3448..84096a6e 100644 --- a/include/espressif/pwm.h +++ b/include/espressif/pwm.h @@ -1,5 +1,5 @@ /* - * ESPRSSIF MIT License + * ESPRESSIF MIT License * * Copyright (c) 2015 * @@ -25,118 +25,189 @@ #ifndef __PWM_H__ #define __PWM_H__ +#include + #ifdef __cplusplus extern "C" { #endif -/** \defgroup Driver_APIs Driver APIs - * @brief Driver APIs - */ - -/** @addtogroup Driver_APIs - * @{ - */ - -/** \defgroup PWM_Driver_APIs PWM Driver APIs - * @brief PWM driver APIs - */ - -/** @addtogroup PWM_Driver_APIs - * @{ - */ - -struct pwm_param { - uint32 period; /**< PWM period */ - uint32 freq; /**< PWM frequency */ - uint32 duty[8]; /**< PWM duty */ -}; - -#define PWM_DEPTH 1023 /** - * @brief PWM function initialization, including GPIO, frequency and duty cycle. + * @brief PWM function initialization, including GPIO, frequency and duty cycle. * * @attention This API can be called only once. * - * @param uint32 period : pwm frequency - * @param uint32 *duty : duty cycle - * @param uint32 pwm_channel_num : PWM channel number - * @param uint32 (*pin_info_list)[3] : GPIO parameter of PWM channel, it is a pointer - * of n x 3 array which defines GPIO register, IO - * reuse of corresponding pin and GPIO number. + * @param uint32_t period : PWM period, unit : us. + * e.g.: For 1KHz PWM, period is 1000 us. + * @param uint32_t *duty : duty cycle of each channels. + * @param uint32_t pwm_channel_num : PWM channel number, maximum is 8 + * @param uint32_t (*pin_info_list)[3] : GPIO parameter of PWM channel, it is a pointer + * of n x 3 array which defines GPIO register, IO reuse of corresponding pin and GPIO number. * - * @return null + * @return null */ -void pwm_init(uint32 period, uint32 *duty, uint32 pwm_channel_num, uint32(*pin_info_list)[3]); +void pwm_init(uint32_t period, uint32_t *duty, uint32_t pwm_channel_num, uint32_t(*pin_info_list)[3]); /** - * @brief Set the duty cycle of a PWM channel. + * @brief Set the duty cycle of a PWM channel. + * Set the time that high level or low(if you reverse the output of this channel) + * signal will last, the duty cycle cannot exceed the period. + * + * @attention After set configuration, pwm_start needs to be called to take effect. * - * Set the time that high level signal will last, duty depends on period, - * the maximum value can be 1023. - * + * @param uint32_t duty : duty cycle + * @param uint8_t channel_num : PWM channel number + * the channel_num cannot exceed the value initialized by pwm_init. + * + * @return null + */ +void pwm_set_duty(uint32_t duty, uint8_t channel_num); + +/** + * @brief Get the duty cycle of a PWM channel. + * + * @param uint8_t channel_num : PWM channel number + * the channel_num cannot exceed the value initialized by pwm_init. + * + * @return Duty cycle of specified channel + */ +uint32_t pwm_get_duty(uint8_t channel_num); + +/** + * @brief Set PWM period, unit : us. * * @attention After set configuration, pwm_start needs to be called to take effect. * - * @param uint32 duty : duty cycle - * @param uint8 channel : PWM channel number + * @param uint32_t period : PWM period, unit : us + * For example, for 1KHz PWM, period is 1000. * - * @return null + * @return null */ -void pwm_set_duty(uint32 duty, uint8 channel); +void pwm_set_period(uint32_t period); /** - * @brief Get the duty cycle of a PWM channel. + * @brief Get PWM period, unit : us. * - * @param uint8 channel : PWM channel number + * @param null * - * @return Duty cycle of PWM output. + * @return PWM period, unit : us */ -uint32 pwm_get_duty(uint8 channel); +uint32_t pwm_get_period(void); /** - * @brief Set PWM period, unit : us. - * - * For example, for 1KHz PWM, period is 1000 us. - * - * @attention After set configuration, pwm_start needs to be called to take effect. - * - * @param uint32 period : PWM period, unit : us. - * - * @return null - */ -void pwm_set_period(uint32 period); - -/** - * @brief Get PWM period, unit : us. - * - * @param null - * - * @return PWM period, unit : us. - */ -uint32 pwm_get_period(void); - -/** - * @brief Starts PWM. + * @brief Starts PWM. * * @attention This function needs to be called after PWM configuration is changed. * - * @param null + * @param null * - * @return null + * @return null */ void pwm_start(void); /** - * @} + * @brief Stop all PWM channel. + * Stop PWM and set the output of each channel to the specified level. + * Calling pwm_start can re-start PWM output. + * + * @param uint32_t stop_level : Out put level after PWM is stoped + * e.g.: We initialize 8 channels, if stop_level_mask = 0x0f, + * channel 0,1,2 and 3 will output high level, and channel 4,5,6 and 7 will output low level. + * + * @return null */ +void pwm_stop(uint32_t stop_level_mask); /** - * @} + * @brief Set the duty cycle of all channels. + * + * @attention After set configuration, pwm_start needs to be called to take effect. + * + * @param uint32_t *duty : An array that store the duty cycle of each channel, + * the array elements number needs to be the same as the number of channels. + * + * @return null */ +void pwm_set_dutys(uint32_t *duty); + +/** + * @brief Set the phase of a PWM channel. + * + * @attention After set configuration, pwm_start needs to be called to take effect. + * + * @param int phase : The phase of this PWM channel, the phase range is (-180 ~ 180). + * @param uint8_t channel_num : PWM channel number + * the channel_num cannot exceed the value initialized by pwm_init. + * + * @return null + */ +void pwm_set_phase(int phase, uint8_t channel_num); + +/** + * @brief Set the phase of all channels. + * + * @attention After set configuration, pwm_start needs to be called to take effect. + * + * @param int *phase : An array that store the phase of each channel, + * the array elements number needs to be the same as the number of channels. + * + * @return null + */ +void pwm_set_phases(int *phase); + +/** + * @brief Get the phase of a PWM channel. + * + * @param uint8_t channel_num : PWM channel number + * the channel_num cannot exceed the value initialized by pwm_init. + * + * @return PWM phase of specified channel. + */ +int pwm_get_phase(uint8_t channel_num); + +/** + * @brief Set PWM period and duty of each PWM channel. + * + * @attention After set configuration, pwm_start needs to be called to take effect. + * + * @param uint32_t period : PWM period, unit : us + * For example, for 1KHz PWM, period is 1000. + * @param uint32_t *duty : An array that store the duty cycle of each channel, + * the array elements number needs to be the same as the number of channels. + * + * @return null + */ +void pwm_set_period_dutys(uint32_t period, uint32_t *duty); + +/** + * @brief Set the inverting output PWM channel. + * + * @attention After set configuration, pwm_start needs to be called to take effect. + * + * @param uint16_t channel_mask : The channel bitmask that used to reverse the output + * e.g.: We initialize 8 channels, if channel_mask = 0x0f, channels 0, 1, 2 and 3 will reverse the output. + * + * @return null + */ +void pwm_set_channel_reverse(uint16_t channel_mask); + +/** + * @brief Clear the inverting output PWM channel. + * This function only works for the PWM channel that is already in the inverted output states. + * + * @attention After set configuration, pwm_start needs to be called to take effect. + * + * @param uint16_t channel_mask : The channel bitmask that need to clear + * e.g.: The outputs of channels 0, 1, 2 and 3 are already in inverted state. If channel_mask = 0x07, + * the output of channel 0, 1, and 2 will return to normal, the channel 3 will keep inverting output. + * + * @return null + */ +void pwm_clear_channel_reverse(uint16_t channel_mask); + #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/lib/libpwm.a b/lib/libpwm.a index 9f21de0cb2425e5dd2418e74c85681bc507fc9de..644152665c6d25d5c82776a4dd7c0aa572c4ebd1 100644 GIT binary patch literal 16776 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ßT-H?8@&vZ)Yaaw+TP3tvLW)a?+W9L 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 KN6CSt{(k|*)E4Lf literal 9282 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