From 016923e6541fcb4dd66b1f3ef82f555abbfc3bf8 Mon Sep 17 00:00:00 2001 From: Piotr Esden-Tempski Date: Thu, 15 Jan 2015 01:06:48 -0800 Subject: [PATCH] [stm32f429i-discovery] Added dac dma example. --- .../f4/stm32f429i-discovery/dac-dma/Makefile | 25 +++ .../f4/stm32f429i-discovery/dac-dma/README | 17 ++ .../f4/stm32f429i-discovery/dac-dma/dac-dma.c | 157 ++++++++++++++++++ .../dac-dma/scope-output.png | Bin 0 -> 3484 bytes 4 files changed, 199 insertions(+) create mode 100644 examples/stm32/f4/stm32f429i-discovery/dac-dma/Makefile create mode 100644 examples/stm32/f4/stm32f429i-discovery/dac-dma/README create mode 100644 examples/stm32/f4/stm32f429i-discovery/dac-dma/dac-dma.c create mode 100644 examples/stm32/f4/stm32f429i-discovery/dac-dma/scope-output.png diff --git a/examples/stm32/f4/stm32f429i-discovery/dac-dma/Makefile b/examples/stm32/f4/stm32f429i-discovery/dac-dma/Makefile new file mode 100644 index 0000000..5402b5c --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/dac-dma/Makefile @@ -0,0 +1,25 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library 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 Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +BINARY = dac-dma + +LDSCRIPT = ../stm32f429i-discovery.ld + +include ../../Makefile.include + diff --git a/examples/stm32/f4/stm32f429i-discovery/dac-dma/README b/examples/stm32/f4/stm32f429i-discovery/dac-dma/README new file mode 100644 index 0000000..3b53fc7 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/dac-dma/README @@ -0,0 +1,17 @@ +DAC test with DMA and timer 2 trigger + +Timer 2 is setup to provide a trigger signal on OC1, with a period of 142 Hz + +The DAC is setup on channel 1 to output a sample on the timer trigger. + +DMA controller 1, stream 5, channel 7 is used to move data from a +predefined array in circular mode when the DAC requests. + +DMA transfer complete occurs when the data array has been passed through. +In the ISR port PC1 is toggled to provide a CRO trigger. + +The analogue output appears on PA4 (DAC channel 1). + +Tested and working, example capture from an oscilloscope is included + +Ken Sarkies 15/01/2014 diff --git a/examples/stm32/f4/stm32f429i-discovery/dac-dma/dac-dma.c b/examples/stm32/f4/stm32f429i-discovery/dac-dma/dac-dma.c new file mode 100644 index 0000000..5477a18 --- /dev/null +++ b/examples/stm32/f4/stm32f429i-discovery/dac-dma/dac-dma.c @@ -0,0 +1,157 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Ken Sarkies + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +/* Timer 2 count period, 16 microseconds for a 72MHz APB2 clock */ +#define PERIOD 1152 + +/* Globals */ +uint8_t waveform[256]; + +/*--------------------------------------------------------------------*/ +static void clock_setup(void) +{ + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); +} + +/*--------------------------------------------------------------------*/ +static void gpio_setup(void) +{ + /* Port A and C are on AHB1 */ + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOC); + /* Set the digital test output on PC1 */ + gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO1); + gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO1); + /* Set PA4 for DAC channel 1 to analogue, ignoring drive mode. */ + gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4); +} + +/*--------------------------------------------------------------------*/ +static void timer_setup(void) +{ + /* Enable TIM2 clock. */ + rcc_periph_clock_enable(RCC_TIM2); + timer_reset(TIM2); + /* Timer global mode: - No divider, Alignment edge, Direction up */ + timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, + TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_continuous_mode(TIM2); + timer_set_period(TIM2, PERIOD); + timer_disable_oc_output(TIM2, TIM_OC2 | TIM_OC3 | TIM_OC4); + timer_enable_oc_output(TIM2, TIM_OC1); + timer_disable_oc_clear(TIM2, TIM_OC1); + timer_disable_oc_preload(TIM2, TIM_OC1); + timer_set_oc_slow_mode(TIM2, TIM_OC1); + timer_set_oc_mode(TIM2, TIM_OC1, TIM_OCM_TOGGLE); + timer_set_oc_value(TIM2, TIM_OC1, 500); + timer_disable_preload(TIM2); + /* Set the timer trigger output (for the DAC) to the channel 1 output + compare */ + timer_set_master_mode(TIM2, TIM_CR2_MMS_COMPARE_OC1REF); + timer_enable_counter(TIM2); +} + +/*--------------------------------------------------------------------*/ +static void dma_setup(void) +{ + /* DAC channel 1 uses DMA controller 1 Stream 5 Channel 7. */ + /* Enable DMA1 clock and IRQ */ + rcc_periph_clock_enable(RCC_DMA1); + nvic_enable_irq(NVIC_DMA1_STREAM5_IRQ); + dma_stream_reset(DMA1, DMA_STREAM5); + dma_set_priority(DMA1, DMA_STREAM5, DMA_SxCR_PL_LOW); + dma_set_memory_size(DMA1, DMA_STREAM5, DMA_SxCR_MSIZE_8BIT); + dma_set_peripheral_size(DMA1, DMA_STREAM5, DMA_SxCR_PSIZE_8BIT); + dma_enable_memory_increment_mode(DMA1, DMA_STREAM5); + dma_enable_circular_mode(DMA1, DMA_STREAM5); + dma_set_transfer_mode(DMA1, DMA_STREAM5, + DMA_SxCR_DIR_MEM_TO_PERIPHERAL); + /* The register to target is the DAC1 8-bit right justified data + register */ + dma_set_peripheral_address(DMA1, DMA_STREAM5, (uint32_t) &DAC_DHR8R1); + /* The array v[] is filled with the waveform data to be output */ + dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t) waveform); + dma_set_number_of_data(DMA1, DMA_STREAM5, 256); + dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5); + dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7); + dma_enable_stream(DMA1, DMA_STREAM5); +} + +/*--------------------------------------------------------------------*/ +static void dac_setup(void) +{ + /* Enable the DAC clock on APB1 */ + rcc_periph_clock_enable(RCC_DAC); + /* Setup the DAC channel 1, with timer 2 as trigger source. + * Assume the DAC has woken up by the time the first transfer occurs */ + dac_trigger_enable(CHANNEL_1); + dac_set_trigger_source(DAC_CR_TSEL1_T2); + dac_dma_enable(CHANNEL_1); + dac_enable(CHANNEL_1); +} + +/*--------------------------------------------------------------------*/ +/* The ISR simply provides a test output for a CRO trigger */ + +void dma1_stream5_isr(void) +{ + if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_TCIF)) { + dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF); + /* Toggle PC1 just to keep aware of activity and frequency. */ + gpio_toggle(GPIOC, GPIO1); + } +} + +/*--------------------------------------------------------------------*/ +int main(void) +{ + /* Fill the array with funky waveform data */ + /* This is for dual channel 8-bit right aligned */ + uint16_t i, x; + for (i = 0; i < 256; i++) { + if (i < 10) { + x = 10; + } else if (i < 121) { + x = 10 + ((i*i) >> 7); + } else if (i < 170) { + x = i/2; + } else if (i < 246) { + x = i + (80 - i/2); + } else { + x = 10; + } + waveform[i] = x; + } + clock_setup(); + gpio_setup(); + timer_setup(); + dma_setup(); + dac_setup(); + + while (1); + + return 0; +} diff --git a/examples/stm32/f4/stm32f429i-discovery/dac-dma/scope-output.png b/examples/stm32/f4/stm32f429i-discovery/dac-dma/scope-output.png new file mode 100644 index 0000000000000000000000000000000000000000..07b334bce901e3a3e8f2bf3ff72753590a28636a GIT binary patch literal 3484 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