2025-03-04 1:33 PM - last edited on 2025-03-04 1:53 PM by Andrew Neil
The ADC values remain unchanged even when input signals does change. The C++ code provided below should hopefully clarify the situation, as I am a stuck. Thank you in advance for any help!
#include "mbed.h"
#include "stm32l4xx_hal.h"
//Once the buffer below is filled, transfer it over to the PC
#define ADC_BUF_SIZE 1024 // Number of samples in buffer
#define SAMPLE_RATE 50000 // Sampling rate in Hz (e.g., 50 kHz)
AnalogIn adc_pin(A0); // Use A0 as the analog input pin
// ADC and DMA handles
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
uint16_t adc_buffer[ADC_BUF_SIZE]; // ADC DMA buffer
volatile bool buffer_ready = false; // Flag to indicate data is ready
void ADC_Init() {
__HAL_RCC_ADC_CLK_ENABLE(); // Enable ADC Clock
__HAL_RCC_DMA1_CLK_ENABLE(); // Enable DMA Clock
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
printf("ADC Init Failed!\n");
}
// Configure ADC Channel
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_5; // Corresponds to A0
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5; // Adjust if needed
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
printf("ADC Channel Config Failed!\n");
}
}
void DMA_Init() {
// Configure DMA
hdma_adc1.Instance = DMA1_Channel1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK) {
printf("DMA Init Failed!\n");
}
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
// Enable Interrupt on DMA Transfer Complete
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
void Start_ADC_DMA() {
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_BUF_SIZE);
printf("ADC Sampling Started...\n");
}
extern "C" void DMA1_Channel1_IRQHandler() {
HAL_DMA_IRQHandler(&hdma_adc1);
}
// Callback function when buffer is full
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
if (hadc->Instance == ADC1) {
buffer_ready = true; // Signal that buffer is full
}
}
void Process_ADC_Data() {
if (buffer_ready) {
buffer_ready = false;
for (int i = 0; i < ADC_BUF_SIZE; i++) {
printf("Sample %d: %d\n", i, adc_buffer[i]);
}
}
}
int main() {
printf("Starting ADC DMA Sampling...\n");
ADC_Init(); //
DMA_Init(); //Direct memory access - giving permission to ADC to write into the memory
Start_ADC_DMA(); //Start DMA writing
while (1) {
Process_ADC_Data();
ThisThread::sleep_for(10ms); // Avoid CPU overload
}
}
Code formatting applied - please see How to insert source code for future reference.