2020-03-19 12:00 PM
I am trying to set up the ADC to continuously scan a few channels in the background and store them in an array automatically using the DMA. I have been trying a vast number of things to get this work. If i don't set the the ADC to run in CONT then the OVR bit doesn't get set but I still only get one of my values in my array. I have been trying to figure this out for days now with no luck, any help would be appreciated
Here's my code:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
#define len(x) sizeof(x)/sizeof((x)[0])
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx.h"
#include <stdio.h>
#include <stdarg.h>
void SystemClock_Config(void);
void printfToSerial(char buf[], ...);
void printToSerial(char buf[], int length);
uint16_t sensorReadings[2] = {0, 0}, s2[2];
int main(void)
{
SystemClock_Config();
//ADC Setup
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
GPIOA->MODER |= 0xF;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
ADC->CCR |= ADC_CCR_ADCPRE_0 | ADC_CCR_ADCPRE_1;
ADC1->CR2 |= ADC_CR2_ADON | ADC_CR2_CONT;
ADC1->CR1 |= ADC_CR1_SCAN;
ADC1->CR2 |= ADC_CR2_DMA | ADC_CR2_DDS;
ADC1->SMPR2 |= ADC_SMPR2_SMP1_1 | ADC_SMPR2_SMP0_1;
ADC1->SQR1 |= 1 << ADC_SQR1_L_Pos;
ADC1->SQR3 |= 1 << 5;
//USART Setup
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
GPIOD->MODER |= 0xA << GPIO_MODER_MODER8_Pos;
GPIOD->AFR[1] |= 0x77;
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
USART3->CR1 |= USART_CR1_UE;
USART3->BRR |= 22 << USART_BRR_DIV_Mantissa_Pos | 13; //5 + 12/16 = 5.75
HAL_Delay(1);
//DMA Enable
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
DMA2_Stream4->PAR = (uint32_t) (&(ADC1->DR));
DMA2_Stream4->M0AR = (uint32_t) (sensorReadings);
// DMA2_Stream4->M1AR = (uint32_t) (&s2);
DMA2_Stream4->NDTR = 2;
DMA2_Stream4->CR |= DMA_SxCR_MSIZE_0 |
DMA_SxCR_PSIZE_0 |
DMA_SxCR_MINC |
DMA_SxCR_CIRC |
DMA_SxCR_PL_Msk;
DMA2_Stream4->CR = DMA_SxCR_EN;
ADC1->CR2 |= ADC_CR2_SWSTART;
while (1)
{
//printfToSerial("%d, %d\n", sensorReadings[0], sensorReadings[1]);
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct =
{ 0 };
RCC_ClkInitTypeDef RCC_ClkInitStruct =
{ 0 };
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct =
{ 0 };
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
RCC_OscInitStruct.PLL.PLLR = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
// Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
// Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48;
PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48CLKSOURCE_PLLQ;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
// Error_Handler();
}
}
void printToSerial(char buf[], int length)
{
USART3->CR1 |= USART_CR1_TE;
for (int i = 0; i < length; i++)
{
if (buf[i] == 0)
return;
while (!(USART3->SR & USART_SR_TXE))
;
USART3->DR = buf[i];
}
}
void printfToSerial(char buf[], ...)
{
char str[32];
va_list args;
va_start(args, buf);
vsprintf(str, buf, args);
printToSerial(str, len(str));
va_end(args);
}