cancel
Showing results for 
Search instead for 
Did you mean: 

Differential ADC measurment with Zephyr (STM32H563RG)

Lukas4
Visitor

Hello all,

 

I try to make a differential ADC-measurment with the Zephyr work. The console tells me, that "Differential channels are not supported", so I'm not sure what the problem is (Wrong config of the device-tree, missing config in proj.conf or wrong software". In my opinion this measurment should work. 

I'm using the STM32H563RG and want to perform the measurment on PA0 (ADC1_INN1) and PA1 (ADC1_INP1)
proj.conf:

CONFIG_ADC=y
CONFIG_ADC_STM32=y
CONFIG_LOG=y
CONFIG_GPIO=y
 
Devicetree
&clk_hse {
    clock-frequency = <DT_FREQ_M(25)>; /* STLink 25MHz clock */
    /*hse-bypass;*/
    status = "okay";
};

&clk_hsi48 {
    status = "okay";
};

&clk_hsi {
    status = "okay";
};

&clk_lse {
    status = "okay";
};

&pll {  /* SYSCLK 240MHz (250) */
    div-m = <5>;        /* 5 (4) */
    mul-n = <96>;       /* 96 (80) */
    div-p = <2>;
    div-q = <2>;
    div-r = <2>;
    clocks = <&clk_hse>;
    status = "okay";
};


&rcc {
    clocks = <&pll>;
    clock-frequency = <DT_FREQ_M(240)>; /* 240 */
    ahb-prescaler = <1>;
    apb1-prescaler = <2>;
    apb2-prescaler = <1>;
    apb3-prescaler = <2>;
};
 
/ {
    zephyr,user {
        io-channels = <&adc1 1>;
    };
};



&adc1{
    compatible = "st,stm32-adc";
    //reg = <0x42028000 0x400>;
    #address-cells = <1>;
    #size-cells = <0>;
    clocks = <&rcc STM32_CLOCK(AHB2, 10U)>;
    st,adc-clock-source="SYNC";
    st,adc-prescaler = <4>;
    status = "okay";
    vref-mv = <3300>;
    #io-channel-cells = <1>;
    resolutions = <STM32_ADC_RES(12, 0x00)>;
    sampling-times = <48>;
    st,adc-sequencer = "FULLY_CONFIGURABLE";
    st,adc-oversampler = "OVERSAMPLER_MINIMAL";
    pinctrl-names = "default";
    pinctrl-0 = <&adc1_inp1_pa1 &adc1_inn1_pa0>;
    // Kanal 1
    channel@1 {
        reg = <1>;  // Definiert, dass dies ADC-Kanal 1 ist
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_EXTERNAL0";
        zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10)>;
        zephyr,differential;  // Differenzielle Messung aktivieren
        zephyr,input-positive = <1>;  // Ersetzen Sie PIN_POSITIVE durch den positiven ADC-Pin
        zephyr,input-negative = <0>;  // Ersetzen Sie PIN_NEGATIVE durch den negativen ADC-Pin
        zephyr,resolution = <12>;
    };
};
 
/ {
    pinctrl {
        adc1_pins: adc1_pins {
            group0 {
                pinmux = <STM32_PINMUX('A', 0, ANALOG)>,
                         <STM32_PINMUX('A', 1, ANALOG)>;
            };
        };
    };
};
 
Code:
#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
    !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
#error "No suitable devicetree overlay specified"
#endif

#define DT_SPEC_AND_COMMA(node_id, prop, idx) ADC_DT_SPEC_GET_BY_IDX(node_id, idx),

#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
/* Data of ADC io-channels specified in devicetree. */
static const struct adc_dt_spec adc_channels[] = {
    DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, DT_SPEC_AND_COMMA)
};
static const int adc_channels_count = ARRAY_SIZE(adc_channels);
#else
#error "Unsupported board."
#endif
 
int adc_try_1()
{
    int err;
    uint32_t count = 0;
    uint16_t buf;
    struct adc_sequence sequence = {
        .buffer = &buf,
        //buffer size in bytes, not number of samples
        .buffer_size = sizeof(buf),
    };

    for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++)
    {
        if (!adc_is_ready_dt(&adc_channels[i]))
        {
            printk("ADC controller device %s not ready\n", adc_channels[i].dev->name);
            return 0;
        }
        else
        {
            printk("ADC controller device %s IS ready  :D  \n", adc_channels[i].dev->name);
        }

        err =adc_channel_setup_dt(&adc_channels[0]);
        if (err < 0) {
            printk("Could not setup channel #%d (%d)\n", 0, err);
            return 0;
        }
    }
}
 
Do you have an idea, what is missing?
 
best regards
Lukas
 
1 REPLY 1
Sarra.S
ST Employee

Hello @Lukas4, welcome to ST community, 

Looking at the ADC driver stm32h5xx_hal_adc.c the driver does support configuring the ADC for differential measurements, as you can check, the mode is set (single-ended or differential) for the channel usingLL_ADC_SetChannelSingleDiff

Edit: Also, looking at the dts/bindings/adc/st,stm32-adc.yaml file, the zephyr,differential property is not explicitly defined in the binding documentation, so, unless you have added it manually to the device tree binding, the ADC drive won't be able to read zephyr,differentialproperty and configure the ADC channels accordingly.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.