From 4cb6f85e3ce0b24bda5188c2222c612a012eaee4 Mon Sep 17 00:00:00 2001 From: Nico Tonnhofer Date: Wed, 2 Dec 2015 00:32:48 +0100 Subject: [PATCH] STM32F411: implement analog-stm32.c It's not that easy like LPC. We need later an DMA to control all ADCs, because there is only one register to read the ADC. --- analog-stm32.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ analog.c | 1 + arduino_stm32f411.h | 26 +++++++++--- 3 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 analog-stm32.c diff --git a/analog-stm32.c b/analog-stm32.c new file mode 100644 index 0000000..3b3f606 --- /dev/null +++ b/analog-stm32.c @@ -0,0 +1,96 @@ + +/** \file + \brief Analog subsystem, ARM specific part. + +*/ + +#if defined TEACUP_C_INCLUDE && defined __ARM_STM32F411__ + +#include "cmsis-stm32f4xx.h" +#include "arduino.h" +#include "temp.h" + + +/** Inititalise the analog subsystem. + + Initialise the ADC and start hardware scan loop for all used sensors. +*/ +void analog_init() { + + if (NUM_TEMP_SENSORS) { // At least one channel in use. + + PIOC_2_PORT->MODER |= (GPIO_MODER_MODER0 << ((PIOC_2_PIN) << 1)); // analog mode + PIOC_2_PORT->PUPDR &= ~(3 << ((PIOC_2_PIN) << 1)); // no pullup + PIOC_2_PORT->OSPEEDR |= (3 << ((PIOC_2_PIN) << 1)); // high speed + + RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable clock + + /* Set ADC parameters */ + /* Set the ADC clock prescaler */ + /* Datasheet says max. ADC-clock is 36MHz + We don't need that much. 12MHz is slowest possible. + */ + ADC->CCR |= (ADC_CCR_ADCPRE); + + /* Set ADC scan mode */ + // scan mode disabled + // reset resolution + // discontinous mode disabled + ADC1->CR1 &= ~( ADC_CR1_SCAN | + ADC_CR1_RES | + ADC_CR1_DISCEN); + + /* Set ADC resolution */ + // resoltion 10bit + ADC1->CR1 |= ADC_CR1_RES_0; + + /* Set ADC data alignment */ + // reset = right align + // reset external trigger + // + // disable continous conversion mode + // disable ADC DMA continuous request + // disable ADC end of conversion selection + ADC1->CR2 &= ~( ADC_CR2_ALIGN | + ADC_CR2_EXTSEL | + ADC_CR2_EXTEN | + ADC_CR2_CONT | + ADC_CR2_DDS | + ADC_CR2_EOCS); + + /* Set ADC number of conversion */ + // 1 conversion + ADC1->SQR1 &= ~(ADC_SQR1_L); + + } +} + +/** Read analog value. + + \param channel Channel to be read. + + \return Analog reading, 10-bit right aligned. + + STM32F4 goes a different way. The ADC don't have a register for + each channel. We need a DMA soon to convert and hold all datas. +*/ +//#include "delay.h" +uint16_t analog_read(uint8_t index) { + // 11.8.2 Managing a sequence of conversions without using the DMA + // page 220 + + ADC1->SMPR1 &= ~(ADC_SMPR1_SMP12); // PIOC_2_ADC 12 + // 3 CYCLES + + ADC1->SQR3 &= ~(ADC_SQR3_SQ1); // rank 1 + ADC1->SQR3 |= PIOC_2_ADC; // << (5 * (rank - 1)) + + ADC1->CR2 |= ADC_CR2_ADON // A/D Converter ON / OFF + | ADC_CR2_SWSTART; // Start Conversion of regular channels + + while (!(ADC1->SR & ADC_SR_EOC) == ADC_SR_EOC); + + return ADC1->DR; +} + +#endif /* defined TEACUP_C_INCLUDE && defined __ARM_STM32F411__ */ diff --git a/analog.c b/analog.c index 243f045..25c9340 100644 --- a/analog.c +++ b/analog.c @@ -36,6 +36,7 @@ static uint8_t adc_channel[NUM_TEMP_SENSORS] = { #define TEACUP_C_INCLUDE #include "analog-avr.c" #include "analog-lpc.c" +#include "analog-stm32.c" #undef TEACUP_C_INCLUDE // No common code so far. diff --git a/arduino_stm32f411.h b/arduino_stm32f411.h index b942c45..95940fc 100644 --- a/arduino_stm32f411.h +++ b/arduino_stm32f411.h @@ -11,7 +11,7 @@ functions, spread over various files, slow execution (pin toggling about 15 times slower than what we have here). - FASTIO by setting the BSRR (bit set/reset register), + FASTIO by setting the BSRR (bit set/reset register), - Bit0-15 to set - Bit16-31 to reset. @@ -24,10 +24,10 @@ /** Pins for UART, the serial port. */ -#define RXD_PORT PIOA_3_PORT -#define RXD_PIN PIOA_3_PIN -#define TXD_PORT PIOA_2_PORT -#define TXD_PIN PIOA_2_PIN +#define RXD_PORT PA_3_PORT +#define RXD_PIN PA_3_PIN +#define TXD_PORT PA_2_PORT +#define TXD_PIN PA_2_PIN /** We define only pins available on the Nucleo F411RE here. @@ -36,27 +36,35 @@ #define PA_0_PIN 0 #define PA_0_PORT GPIOA +#define PA_0_ADC 0 #define PA_1_PIN 1 #define PA_1_PORT GPIOA +#define PA_1_ADC 1 #define PA_2_PIN 2 #define PA_2_PORT GPIOA +#define PA_2_ADC 2 #define PA_3_PIN 3 #define PA_3_PORT GPIOA +#define PA_3_ADC 3 #define PA_4_PIN 4 #define PA_4_PORT GPIOA +#define PA_4_ADC 4 #define PA_5_PIN 5 #define PA_5_PORT GPIOA +#define PA_5_ADC 5 #define PA_6_PIN 6 #define PA_6_PORT GPIOA +#define PA_6_ADC 6 #define PA_7_PIN 7 #define PA_7_PORT GPIOA +#define PA_7_ADC 7 #define PA_8_PIN 8 #define PA_8_PORT GPIOA @@ -84,9 +92,11 @@ #define PB_0_PIN 0 #define PB_0_PORT GPIOB +#define PB_0_ADC 8 #define PB_1_PIN 1 #define PB_1_PORT GPIOB +#define PB_1_ADC 9 #define PB_2_PIN 2 #define PB_2_PORT GPIOB @@ -129,21 +139,27 @@ #define PC_0_PIN 0 #define PC_0_PORT GPIOC +#define PC_0_ADC 10 #define PC_1_PIN 1 #define PC_1_PORT GPIOC +#define PC_1_ADC 11 #define PC_2_PIN 2 #define PC_2_PORT GPIOC +#define PC_2_ADC 12 #define PC_3_PIN 3 #define PC_3_PORT GPIOC +#define PC_3_ADC 13 #define PC_4_PIN 4 #define PC_4_PORT GPIOC +#define PC_4_ADC 14 #define PC_5_PIN 5 #define PC_5_PORT GPIOC +#define PC_5_ADC 15 #define PC_6_PIN 6 #define PC_6_PORT GPIOC