From d02d5618f069b3eecdf8e7ceea3666099ba6948b Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Thu, 11 Jun 2020 20:39:05 +0200 Subject: [PATCH] Adding simple PWM example app --- simple_pwm/Makefile | 21 ++++++ simple_pwm/README | 30 ++++++++ simple_pwm/main.c | 166 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 simple_pwm/Makefile create mode 100644 simple_pwm/README create mode 100644 simple_pwm/main.c diff --git a/simple_pwm/Makefile b/simple_pwm/Makefile new file mode 100644 index 0000000..41ae555 --- /dev/null +++ b/simple_pwm/Makefile @@ -0,0 +1,21 @@ +# Makefile for apps + +MODULE = $(shell basename $(shell cd .. && pwd && cd -)) +NAME = $(shell basename $(CURDIR)) + +# Add this to your ~/.vimrc in order to get proper function of :make in vim : +# let $COMPILE_FROM_IDE = 1 +ifeq ($(strip $(COMPILE_FROM_IDE)),) + PRINT_DIRECTORY = --no-print-directory +else + PRINT_DIRECTORY = + LANG = C +endif + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../../.. ${PRINT_DIRECTORY} NAME=$(NAME) MODULE=$(MODULE) apps/$(MODULE)/$(NAME)/$@ + +clean mrproper: + @make -C ../../.. ${PRINT_DIRECTORY} $@ + diff --git a/simple_pwm/README b/simple_pwm/README new file mode 100644 index 0000000..b543187 --- /dev/null +++ b/simple_pwm/README @@ -0,0 +1,30 @@ +Simple pwm using serial input for duty-cycle control + +Copyright 2016 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of PWM for simple led brightness or fan speed control. +PWM duty cycle is set by reading characters from the serial line. + +The PWM signal is output on port 0 pin 19 (LPC_TIMER_32B0_M1_PIO_0_19), using +32 bits timer 0, match channel 1. + +The PWM period is fixed to 1kHz. + + diff --git a/simple_pwm/main.c b/simple_pwm/main.c new file mode 100644 index 0000000..b31b3b9 --- /dev/null +++ b/simple_pwm/main.c @@ -0,0 +1,166 @@ +/**************************************************************************** + * simple_pwm/main.c + * + * Simple PWM example + * + * Copyright 2016 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include "core/system.h" +#include "core/systick.h" +#include "core/pio.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "extdrv/status_led.h" +#include "drivers/timers.h" + + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +#define LPC_TIMER_PIN_CONFIG (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL | LPC_IO_DRIVE_HIGHCURENT) + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* TIMER_32B1 */ + { LPC_TIMER_32B1_M0_PIO_0_23, LPC_TIMER_PIN_CONFIG }, + ARRAY_LAST_PIO, +}; + + +const struct pio status_led_green = LPC_GPIO_0_28; +const struct pio status_led_red = LPC_GPIO_0_29; + +/***************************************************************************** */ +static uint8_t timer = 0; +static uint8_t channel = 0; +static uint32_t pwm_one_step = 0; +int pwm_config(uint8_t timer_num, uint8_t pwm_chan, uint8_t uart_num) +{ + uint32_t pwm_period = 0; + struct lpc_timer_pwm_config timer_conf = { + .nb_channels = 1, + .period_chan = 3, + }; + + timer = timer_num; + channel = pwm_chan; + timer_conf.outputs[0] = pwm_chan; + + /* compute the period for the PWM signal */ + /* We want 1ms (1kHz), timer counts at main clock frequency */ + pwm_period = get_main_clock() / 10000; + pwm_one_step = (pwm_period / 100); + timer_conf.match_values[0] = 0; + timer_conf.period = pwm_period; + + timer_on(timer, 0, NULL); + timer_pwm_config(timer, &timer_conf); + timer_start(timer); + + uprintf(uart_num, "PWM configured (T%d : C%d), Period : %d, step : %d\n", + timer, channel, pwm_period, pwm_one_step); + + return 0; +} + +int set_duty_cycle(int c, int uart_num) +{ + uint16_t val = 0; + + val = (c - '0') * 10; + if (val > 100) { + val = 100; + } + /* When using a mosfet to drive the load, the signal must be inverted to compensate */ + val = 100 - val; + + timer_set_match(timer, channel, (val * pwm_one_step)); + uprintf(uart_num, "Channel %d duty cycle: %d%% (%d)\n", channel, (100 - val), val * pwm_one_step); + return val; +} + + +volatile int set_duty = -1; +void change_pos(uint8_t c) +{ + set_duty = c; +} + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + startup_watchdog_disable(); /* Do it right now, before it gets a chance to break in */ + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + uprintf(UART0, name); + while (1); +} + + + +/***************************************************************************** */ +int main(void) +{ + system_init(); + uart_on(UART0, 115200, change_pos); + + pwm_config(LPC_TIMER_32B1, 0, UART0); + + while (1) { + chenillard(500); + if (set_duty != -1) { + set_duty_cycle(set_duty, UART0); + set_duty = -1; + } + } + return 0; +} + + + -- 2.43.0