From 6fb8fde0a26d7241e8c3e0318c0752a7f6bf9ab9 Mon Sep 17 00:00:00 2001 From: ZiTe Date: Thu, 29 Sep 2022 17:18:16 +0800 Subject: [PATCH] Add 'ADC interrupt' example --- README.md | 3 +- libopencm3/adc_interrupt/.gitignore | 5 + .../adc_interrupt/.vscode/extensions.json | 10 ++ libopencm3/adc_interrupt/platformio.ini | 25 +++ libopencm3/adc_interrupt/src/main.c | 159 ++++++++++++++++++ libopencm3/adc_interrupt/src/main.h | 60 +++++++ 6 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 libopencm3/adc_interrupt/.gitignore create mode 100644 libopencm3/adc_interrupt/.vscode/extensions.json create mode 100644 libopencm3/adc_interrupt/platformio.ini create mode 100644 libopencm3/adc_interrupt/src/main.c create mode 100644 libopencm3/adc_interrupt/src/main.h diff --git a/README.md b/README.md index af63bc5..a956b27 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ This repo contains some basic examples for STM32. | [PWM](./libopencm3/pwm/) | :heavy_check_mark: | :heavy_check_mark: | | | | | | [IWDG](./libopencm3/iwdg/) | :heavy_check_mark: | :heavy_check_mark: | | | | | | [WWDG](./libopencm3/wwdg/) | :heavy_check_mark: | :heavy_check_mark: | | | | | -| [ADC (Regular single channel)](./libopencm3/adc_single_channel_regular/) | :heavy_check_mark: | :heavy_check_mark: | | | | | +| [ADC (Regular single channel)](./libopencm3/adc_single_channel_regular/) | :heavy_check_mark: | :heavy_check_mark: | | | | | | [ADC (Injected multi channel)](./libopencm3/adc_multi_channel_injected/) | :x: | :heavy_check_mark: | | | | | +| [ADC (Interrupt)](./libopencm3/adc_interrupt/) | :heavy_check_mark: | :heavy_check_mark: | | | | | | [SPI (Master mode)](./libopencm3/spi_master/) | :heavy_check_mark: | :heavy_check_mark: | | | | | | [SPI (Slave mode)](./libopencm3/spi_slave/) | :heavy_check_mark: | :heavy_check_mark: | | | | | | [I2C (LCD 1602)](./libopencm3/i2c_lcd1602/) | :heavy_check_mark: | :heavy_check_mark: | | | | | diff --git a/libopencm3/adc_interrupt/.gitignore b/libopencm3/adc_interrupt/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/libopencm3/adc_interrupt/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/libopencm3/adc_interrupt/.vscode/extensions.json b/libopencm3/adc_interrupt/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/libopencm3/adc_interrupt/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/libopencm3/adc_interrupt/platformio.ini b/libopencm3/adc_interrupt/platformio.ini new file mode 100644 index 0000000..ecad292 --- /dev/null +++ b/libopencm3/adc_interrupt/platformio.ini @@ -0,0 +1,25 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = nucleo_f103rb + +; Set/Override default options for each [env:XXX] +[env] +platform = ststm32 +framework = libopencm3 + +[env:nucleo_f103rb] +board = nucleo_f103rb +build_flags = -D NUCLEO_F103RB + +[env:nucleo_f446re] +board = nucleo_f446re +build_flags = -D NUCLEO_F446RE diff --git a/libopencm3/adc_interrupt/src/main.c b/libopencm3/adc_interrupt/src/main.c new file mode 100644 index 0000000..24999bc --- /dev/null +++ b/libopencm3/adc_interrupt/src/main.c @@ -0,0 +1,159 @@ +/** + * @file main.c + * @brief ADC interrupt example for LibOpenCM3 with STM32. + * @author ZiTe (honmonoh@gmail.com) + * @copyright MIT License + */ + +#include "main.h" + +int main(void) +{ + rcc_setup(); + adc_setup(); + usart_setup(); + + printf("ADC Interrupt.\r\n"); + +/* Software start the first conversion. */ +#if defined(STM32F1) + adc_start_conversion_direct(ADC1); +#else + adc_start_conversion_regular(ADC1); +#endif + + /* Halt. */ + while (1) + { + } + return 0; +} + +static void rcc_setup(void) +{ +#if defined(STM32F1) + rcc_clock_setup_in_hse_8mhz_out_72mhz(); +#elif defined(STM32F4) + rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_84MHZ]); +#endif + + rcc_periph_clock_enable(RCC_USART_TX_GPIO); + rcc_periph_clock_enable(RCC_USART2); + rcc_periph_clock_enable(RCC_ADC_GPIO); + rcc_periph_clock_enable(RCC_ADC1); +} + +static void adc_setup(void) +{ +/* Set to input analog. */ +#if defined(STM32F1) + gpio_set_mode(GPIO_ADC_PORT, + GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, + GPIO_ADC_IN0_PIN); +#else + gpio_mode_setup(GPIO_ADC_PORT, + GPIO_MODE_ANALOG, + GPIO_PUPD_NONE, + GPIO_ADC_IN0_PIN); +#endif + + /* Setup ADC. */ + adc_power_off(ADC1); + + adc_disable_scan_mode(ADC1); + adc_disable_external_trigger_regular(ADC1); + adc_set_single_conversion_mode(ADC1); + adc_set_right_aligned(ADC1); + adc_set_sample_time_on_all_channels(ADC1, ADC_SIMPLE_TIME); + + /* Setup interrupt. */ + adc_enable_eoc_interrupt(ADC1); + nvic_enable_irq(ADC_IRQ); + + uint8_t channels[16]; + channels[0] = 0; + adc_set_regular_sequence(ADC1, 1, channels); + + adc_power_on(ADC1); + delay(800000); /* Wait a bit. */ + +#if defined(STM32F1) + adc_reset_calibration(ADC1); + adc_calibrate(ADC1); +#endif +} + +static void usart_setup(void) +{ + /* Set USART-Tx pin to alternate function. */ +#if defined(NUCLEO_F103RB) + gpio_set_mode(GPIO_USART_TX_PORT, + GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, + GPIO_USART_TX_PIN); +#else + gpio_mode_setup(GPIO_USART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_USART_TX_PIN); + gpio_set_af(GPIO_USART_TX_PORT, GPIO_USART_AF, GPIO_USART_TX_PIN); +#endif + + /* Config USART params. */ + usart_set_baudrate(USART2, USART_BAUDRATE); + usart_set_databits(USART2, 8); + usart_set_stopbits(USART2, USART_STOPBITS_1); + usart_set_parity(USART2, USART_PARITY_NONE); + usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE); + usart_set_mode(USART2, USART_MODE_TX); + + usart_enable(USART2); +} + +static void delay(uint32_t value) +{ + for (uint32_t i = 0; i < value; i++) + { + __asm__("nop"); /* Do nothing. */ + } +} + +/* For printf(). */ +int _write(int file, char *ptr, int len) +{ + int i; + + if (file == 1) + { + for (i = 0; i < len; i++) + { + usart_send_blocking(USART2, ptr[i]); + } + return i; + } + + errno = EIO; + return -1; +} + +/** + * @brief ADC Interrupt service routine. + */ +#if defined(STM32F1) +void adc1_2_isr(void) +#else +void adc_isr(void) +#endif +{ + /* Clear regular end of conversion flag. */ + ADC_SR(ADC1) &= ~ADC_SR_EOC; + + uint16_t value = adc_read_regular(ADC1); + printf("%4d\r\n", value); + delay(5000000); + + /* Sart a new conversion. */ +#if defined(STM32F1) + adc_start_conversion_direct(ADC1); +#else + adc_start_conversion_regular(ADC1); +#endif +} \ No newline at end of file diff --git a/libopencm3/adc_interrupt/src/main.h b/libopencm3/adc_interrupt/src/main.h new file mode 100644 index 0000000..f6aa4a0 --- /dev/null +++ b/libopencm3/adc_interrupt/src/main.h @@ -0,0 +1,60 @@ +/** + * @file main.h + * @brief ADC interrupt example for LibOpenCM3 with STM32. + * @author ZiTe (honmonoh@gmail.com) + * @copyright MIT License + */ + +#ifndef MAIN_H +#define MAIN_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include /* For printf(). */ +#include /* For printf(). */ +#include +#include +#include +#include +#include + +#define USART_BAUDRATE (9600) + +#if defined(NUCLEO_F103RB) + #define ADC_SIMPLE_TIME (ADC_SMPR_SMP_55DOT5CYC) + #define RCC_ADC_GPIO (RCC_GPIOA) + #define GPIO_ADC_PORT (GPIOA) + #define GPIO_ADC_IN0_PIN (GPIO0) /* Arduino-A0. */ + #define ADC_IRQ (NVIC_ADC1_2_IRQ) + + #define RCC_USART_TX_GPIO (RCC_GPIOA) + #define GPIO_USART_TX_PORT (GPIOA) + #define GPIO_USART_TX_PIN (GPIO2) /* ST-Link (Arduino-D1). */ +#elif defined(NUCLEO_F446RE) + #define ADC_SIMPLE_TIME (ADC_SMPR_SMP_56CYC) + #define RCC_ADC_GPIO (RCC_GPIOA) + #define GPIO_ADC_PORT (GPIOA) + #define GPIO_ADC_IN0_PIN (GPIO0) /* Arduino-A0. */ + #define ADC_IRQ (NVIC_ADC_IRQ) + + #define RCC_USART_TX_GPIO (RCC_GPIOA) + #define GPIO_USART_TX_PORT (GPIOA) + #define GPIO_USART_TX_PIN (GPIO2) /* ST-Link (Arduino-D1). */ + #define GPIO_USART_AF (GPIO_AF7) /* Ref: Table-11 in DS10693. */ +#else + #error "STM32 board not defined." +#endif + + static void rcc_setup(void); + static void usart_setup(void); + static void adc_setup(void); + static void delay(uint32_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* MAIN_H. */ \ No newline at end of file