Best approach to get an ADC to serial example working on a board/chip like F1x0?
crosswick opened this issue · 17 comments
Hi - I see that in terms of ADC examples, there's currently only two for the F30x range.
When I simply open the polling one of those and add my F1x0 board to the platform.ini and the include, I get a bunch of errors, amongst which:
src/main.c:64:22: error: 'GPIO_MODE_AF_PP' undeclared (first use in this function); did you mean 'GPIO_MODE_AF'?
64 | gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
| ^~~~~~~~~~~~~~~
| GPIO_MODE_AF
src/main.c:64:22: note: each undeclared identifier is reported only once for each function it appears in
src/main.c:65:22: error: 'GPIO_MODE_IN_FLOATING' undeclared (first use in this function); did you mean 'GPIO_MODE_ANALOG'?
65 | gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
| ^~~~~~~~~~~~~~~~~~~~~
| GPIO_MODE_ANALOG
src/main.c: In function 'rcu_config':
src/main.c:102:29: error: 'RCU_ADC0' undeclared (first use in this function); did you mean 'RCU_ADC'?
Do the APIs for these chips indeed differ in this way? I'd be happy to learn the best approach here, thanks in advance.
Yeah using the different API styles for analog reads can be done, the code will just get a but messy with it. I'll expand the examples.
If your goal is to have one clean project with code only targeting the F1x0, you should be taking the code from the official SPL example that's always in the SPL firmware folders: https://github.com/CommunityGD32Cores/gigadevice-firmware-and-docs/blob/main/GD32F1x0/GD32F1x0_Firmware_Library_V3.3.2/Examples/ADC/ADC0_software_trigger_regular_channel_polling/main.c
Most of the SPL project here are based on these projects, and slightly modified to work in a few more configurations.
Ah great, thank you, that will certainly do for now for me.
Oops yes, the SPL repo currently works with the older firmware package version 3.1.0, not 3.3.2 (https://github.com/CommunityGD32Cores/gd32-pio-spl-package/blob/main/gd32/cmsis/variants/gd32f1x0/gd32f1x0.h#L6-L13). You should be using the suggested ADC_EXTTRIG_REGULAR_SWRCST
there for the older version.
Alright - then it still is not working somehow; it seems to lock up on the adc_channel_sample function call here:
//int i = 0;
while (1)
{
adc_value[0] = adc_channel_sample(ADC_CHANNEL_1);
printf("Hello World\n");
//printf("GPIOA1 is seeing a value of: %u\n", adc_value[0]);
//printf("a usart transmit test example! iteration %d\n", i++);
delay_1ms(500);
}
Because this doesn't output anything over serial... when I comment out that adc_value line it does output the HelloWorlds
I think there might be some more dependencies? The 'ADC software trigger regular channel polling' example did not exist yet in 3.1.0...
I might better use a different 3.1.0 example or wait a bit for your expanded examples.
The closest reference example is https://github.com/CommunityGD32Cores/gigadevice-firmware-and-docs/blob/main/GD32F1x0/GD32F1x0_Firmware_Library_v3.1.0/Examples/ADC/Temperature_Vref_Vbat/main.c for V_TEMP and it does the adc_config() a bit differently, especially with adc_external_trigger_config(ADC_INSERTED_CHANNEL,ENABLE);
and adc_inserted_channel_config(0,ADC_CHANNEL_16,ADC_SAMPLETIME_239POINT5);
for the trigger configuration.
I'll update the SPL package to 3.3.1 quickly so that these issues are resolved, no point in staying on the older version.
Please open a CLI and execute pio platform update gd32
, then try the project https://github.com/CommunityGD32Cores/gd32-pio-projects/tree/main/gd32-spl-adc-polling-gd32f1x0
Will do, afk now
I'm getting misformatted usart messages:
<␀␜�␎␀␇�␞�␇ �X␃�␜␀␏�␀��<@␆�␀� �␜�␎u␇␅␝ �8�<�␜
␇�␜B␏�␃�␁�␜Ȱ�␜��8@␏��␀�<␀␏␀␇�␞�␀␃␆�:�␝�␕0␌␀␞�␀␃␃�␃�␝�J␆���␃�8@��␁ ��␝�<␀␇�
Oh, I forgot to se monitor_speed = 115200
at the top.
Fixed in 84ea6ce
Yes that did the trick. Not that it's super important for my current application, but: I am seeing a reported value of 2.11V when I input 2V according to my bench power supply
When you replace ADC_SAMPLETIME_7POINT5
with ADC_SAMPLETIME_239POINT5
in the code, does it get more accurate? What does the connection to the analog-power rails VDDA and VSSA look like? It should have some decoupling / filtering going on like this in the hardware.
Also the value will fluctuate if VDDA is not exactly the expected 3.300000V.
Looks like it was down to the 3.2V from my USB-USART dongle. When I power the board via USB the value is much closer to 2V, namely 1.98V
The microcontroller (every gd32 chip basically) has the capability to measure a V_REFINT internal reference voltage (1.2V per user manual page 239) and with that one can get the actual supply voltage and correct the ADC count -> voltage conversion adc_value[i] * 3.3f / 4095.f
with respect to the statically-assumed 3.3V
value there. There is example code for reading VREFINT
(and VTEMP
and VBAT
) at https://github.com/CommunityGD32Cores/gigadevice-firmware-and-docs/blob/main/GD32F1x0/GD32F1x0_Firmware_Library_v3.1.0/Examples/ADC/Temperature_Vref_Vbat/main.c, that plus a bit of math will make the measurements much more correct -- not implented in the example for simplicity though.
Good to know! As far as I'm concerned this issue is now resolved, thanks again for your swift assistance