[examples f1] ADC+DAC very basic example

Just shows some basic working examples of using the DAC with the ADC. No
special features, but very little hardware required to demonstrate.
This commit is contained in:
Karl Palsson
2013-01-22 10:55:58 +00:00
parent 20bfcaeb1c
commit 13dedaafc1
3 changed files with 203 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2013 Karl Palsson <karlp@tweak.net.au>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/dac.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/adc.h>
#define LED_DISCOVERY_USER_PORT GPIOC
#define LED_DISCOVERY_USER_PIN GPIO8
#define USART_CONSOLE USART2
void clock_setup(void)
{
rcc_clock_setup_in_hsi_out_24mhz();
/* Enable clocks for USART2 and DAC*/
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_DACEN);
/* and the ADC and IO ports */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
}
void usart_setup(void)
{
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX);
usart_set_baudrate(USART_CONSOLE, 115200);
usart_set_databits(USART_CONSOLE, 8);
usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1);
usart_set_mode(USART_CONSOLE, USART_MODE_TX);
usart_set_parity(USART_CONSOLE, USART_PARITY_NONE);
usart_set_flow_control(USART_CONSOLE, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART_CONSOLE);
}
/**
* Use USART_CONSOLE as a console.
* This is a syscall for newlib
* @param file
* @param ptr
* @param len
* @return
*/
int _write(int file, char *ptr, int len)
{
int i;
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
for (i = 0; i < len; i++) {
if (ptr[i] == '\n') {
usart_send_blocking(USART_CONSOLE, '\r');
}
usart_send_blocking(USART_CONSOLE, ptr[i]);
}
return i;
}
errno = EIO;
return -1;
}
void adc_setup(void)
{
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0);
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1);
/* Make sure the ADC doesn't run during config. */
adc_off(ADC1);
/* We configure everything for one single conversion. */
adc_disable_scan_mode(ADC1);
adc_set_single_conversion_mode(ADC1);
adc_disable_external_trigger_regular(ADC1);
adc_set_right_aligned(ADC1);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_power_on(ADC1);
/* Wait for ADC starting up. */
int i;
for (i = 0; i < 800000; i++) /* Wait a bit. */
__asm__("nop");
adc_reset_calibration(ADC1);
adc_calibration(ADC1);
}
void dac_setup(void)
{
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO5);
dac_disable(CHANNEL_2);
dac_disable_waveform_generation(CHANNEL_2);
dac_enable(CHANNEL_2);
dac_set_trigger_source(DAC_CR_TSEL2_SW);
}
u16 read_adc_naiive(u8 channel)
{
u8 channel_array[16];
channel_array[0] = channel;
adc_set_regular_sequence(ADC1, 1, channel_array);
adc_start_conversion_direct(ADC1);
while (!adc_eoc(ADC1));
u16 reg16 = adc_read_regular(ADC1);
return reg16;
}
int main(void)
{
int i;
int j = 0;
clock_setup();
usart_setup();
printf("hi guys!\n");
adc_setup();
dac_setup();
gpio_set_mode(LED_DISCOVERY_USER_PORT, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, LED_DISCOVERY_USER_PIN);
while (1) {
u16 input_adc0 = read_adc_naiive(0);
u16 target = input_adc0 / 2;
dac_load_data_buffer_single(target, RIGHT12, CHANNEL_2);
dac_software_trigger(CHANNEL_2);
u16 input_adc1 = read_adc_naiive(1);
printf("tick: %d: adc0= %u, target adc1=%d, adc1=%d\n",
j++, input_adc0, target, input_adc1);
gpio_toggle(LED_DISCOVERY_USER_PORT, LED_DISCOVERY_USER_PIN); /* LED on/off */
for (i = 0; i < 1000000; i++) /* Wait a bit. */
__asm__("NOP");
}
return 0;
}