Open fpistm opened 7 years ago
From @palmerr23 on May 6, 2017 7:3
Frederic,
I've tested a number of ADC modes - polling, interrupt, DMA.
Example files are in https://github.com/palmerr23/Black-F407VET6-cube/tree/master/examples
Currently debugging Dual Mode Interleaved (edit: now working).
Proposed to move on the new repo Arduino_Core_STM32 as this one is deprecated. (same code).
From @palmerr23 on May 24, 2017 8:36
Frederic, Fine by me. I'm shifting across to the new core also.
Q: instead of adding stuff to the arduino-compatible analogRead have you considered using a different ADC API altogether? Leave analogRead for compatibility purposes but make something better available for advanced uses. The main benefit I see is that a new API allows set-up/tear-down to be separated from the actual reading function. For example, https://github.com/rogerclarkmelbourne/Arduino_STM32/tree/master/STM32F1/libraries/STM32ADC looks pretty darn nice to me and should not be a ton of work to port to LL (if that has all the functionality necessary).
Yes, this is what I would like. Like for timer: HardwareTimer...
Ok, I got a very minimal first version working on STM32L0 doing just single conversions (plus Vcc and Temp). See https://github.com/tve/goobies/tree/master/libraries/STM32ADC/src I would appreciate a review and feedback. I'm not sure how to really handle the clock stuff without introducing a lot of complexity and a lot of code... If this is an interesting direction, I'm happy to get a PR going.
A simple test sketch I'm using to print ADC value for one channel, Vcc, and temperature:
// ADC tester - Displays ADC value
#include <Arduino.h>
#include <stdio.h>
#include <STM32ADC.h>
STM32ADC adc(ADC1);
void setup() {
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
Serial.begin(115200);
delay(10);
printf("===== ADC tester starting\n");
if (!adc.begin(PB1)) printf("ADC.begin() failed!\n");
pinMode(PB1, INPUT);
}
uint8_t led=0;
void loop() {
adc.startConversion();
uint32_t v = adc.read();
uint32_t vcc = adc.measureVcc();
int16_t temp = adc.measureTemp();
printf("ADC: %lu, vcc: %lumV temp: %dC\n", v, vcc, temp);
delay(1000);
}
Output looks something like:
ADC: 2057, vcc: 3260mV temp: 21C
ADC: 2055, vcc: 3258mV temp: 21C
ADC: 2057, vcc: 3258mV temp: 21C
ADC: 2057, vcc: 3258mV temp: 21C
ADC: 2058, vcc: 3247mV temp: 21C
ADC: 2061, vcc: 3260mV temp: 21C
ADC: 2060, vcc: 3258mV temp: 21C
ADC: 2057, vcc: 3258mV temp: 21C
ADC: 2057, vcc: 3258mV temp: 21C
From @palmerr23 on May 6, 2017 7:3
Frederic,
I've tested a number of ADC modes - polling, interrupt, DMA.
Example files are in https://github.com/palmerr23/Black-F407VET6-cube/tree/master/examples
Currently debugging Dual Mode Interleaved (edit: now working).
@fpistm Hi Frederic, I see in your examples that you're able to define HAL_ADC_Msp_Init() conserving, at the same time, the ability to use all the "builtin" Arduino functions such, for example, Serial.print().
I would need to do the same in PlatformIO, using your official STM32 Core Arduino and an STM32F407VGT6 (STM32F4 Discovery board). Like you said, one need to redefine HAL_ADC_Msp_Init() for being able to use the advanced ADC modes (interrupt, DMA, interleaved etc etc) but, obviously, if I try to (re)define my own HAL_ADC_Msp_Init() the compiler complains that that function is already defined in your implementation of Analog.c
Is there a way to circumvent the obstacle?
Moreover, in trying to use the adc in regular conversion interrupt mode, I've also tried with an "unconventional" way trying circumvent the obstacle:
1) created handle and a configuration for my adc: ADC_Handle_Typedef MyAdcHandle; ADC_ChannelConfTypeDef MyAdcChannelConf = {}; 2) Initialized all the handle members: MyAdcHandle.Instance = ADC1 MyAdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4; My_AdcHandle.Init.Resolution = ADC_RESOLUTION_12B; etc etc etc 3)Called HAL_ADC_Init(&MyAdcHandle)--> this will call your HAL_ADC_Msp_Init(), initializing __HAL_RCC_ADC1_CLK_ENABLE(); etc etc etc
/*CIRCUMVENT PART**/ 4)Added the following lines of code: HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);//HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); HAL_NVIC_EnableIRQ(ADC_IRQn); /**END CIRCUMVENT PART***/
5)Created the HAL_ADC_ConvCpltCallback() and ADC_IRQHandler() functions and correctly managed them 6)Initializied the pin of the adc I want to use using: GPIO_InitTypeDef gpioInit; __GPIOC_CLK_ENABLE(); gpioInit.Pin = GPIO_PIN_1; gpioInit.Mode = GPIO_MODE_ANALOG; gpioInit.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOC, &gpioInit);
....and......it doesn't work when using Arduino framework in PlatformIO but it works when using HAL framework in PlatformIO
Please, any suggestion is very very welcome!
Hi,
I hope I am not off topic here. I am working on a project where I need the arduino framework to work on both stm32 and gd32, so I am often comparing stm32duino and arduinocore-gd32. It's not handling all scenarios and has some bugs, but there they initialize the adc's only once, and only set up the channel and do the polling the next times.
That could help you with the speed topic. And with this mechanism, I could also get injected adc and analogread to work in parallel.
Hope it helps.
Just to prove it works Candas1@e4a41dc
Thanks, anyway, I guess there is an issue when using different ADCx.
Sorry I didn't get you. It's just a proof of concept. The gd32 implementation uses an array of ADCx. Another possibility would be to check if the ADC is already enabled with ADC_IS_ENABLE() for example.
Hi @fpistm,
Is there any interest in this ? Would you accept a PR ?
All PR are welcome.
From @palmerr23 on April 26, 2017 5:23
Frederic,
I've been testing the advanced ADC\DAC modes (beyond single conversion, polling) using the templates from STM32Cube_FW_F4_V1.15.0\Projects\STM324x9I_EVAL\Examples\ADC\ and \DAC\
When using these other analog routines, HAL_ADC_MspInit() etc need to be customised for each configuration.
Now I'm trying out the dual-interleaved mode, it has become clear that the code in analog.c is just an initial test.
As HAL_ADC_MspInit() needs to be customised for each configuration, I'm looking at hiding the MSP_Init functions in analog.c at the system level and moving the code up to a library. The Init functions can then be customised for each mode.
When I tried this, other functions break - like dac_stop() and pwm_stop(). I think I'll be able to leave them in analog.c
Give me a few days and I'll have something workable.
Single-Polling and Single-interrupt are working already, using pretty much standard code from the Cube libraries, next up is dual-interleaved
Richard
_Copied from original issue: stm32duino/Arduino_CoreSTM32F4#11