wagiminator / MCU-Templates

Templates for bare-metal firmware development for some entry-level microcontrollers
Other
65 stars 8 forks source link

CH32X033 ADC issue #7

Open dzanis opened 6 days ago

dzanis commented 6 days ago

Hello. I tried the OLED and ADC on the CX32X033 chip. And I was surprised by the incomprehensible behavior of the readings output. On pin A0 there is a divider (10K/10K) of the voltage exactly in half, and on pin A1 there is a variable resistor. The readings are correct, but they are confused, I turn the variable resistor and it shows on A0, but it should be the other way around. I thought that maybe the chip is defective, because there are problems with the chip series ch32x33/35 Channel 3, channel 7, channel 11, channel 15 and I2C functions of the ADC are not available for products with a lot number with a penultimate 5 digit of 0; That's why I used your libraries, because there is no hardware I2C on the chip ch32x033 , thank you for this library i2c_soft.h. But I tried on another library (ch32v003fun and wch-hal) and the ADC works fine there. Here is the code I was talking about:


#include <ch32x035.h>
#include <system.h>
#include <gpio.h>
#include <ssd1306_txt.h> // OLED text functions

// MCU supply voltage
#define VDD_mV 3300 // 3.3V: 3300 , 5V: 5000

void OLED_print_float(uint16_t val) // print float value as (%.3f)
{
  OLED_printf("%d.%u", val / 1000, val % 1000);
}

int main(void)
{

  PORTA_enable();
  // Setup OLED
  OLED_init();
  OLED_clear();

  PIN_input_ADC(PA0); // set PIN as ADC input
  PIN_input_ADC(PA1);

  ADC_init();   // init and enable ADC (must be called first)
  ADC_enable(); // enable ADC (power-up)

  uint16_t adc_val = 0;
  uint16_t mV = 0;

  // Loop
  while (1)
  {
    OLED_clear();

    ADC_input(PA0); // voltage divider 10K/10K
    adc_val = ADC_read();
    mV = VDD_mV * adc_val / 4095;
    OLED_printf("PIN A0 %d/", adc_val);
    OLED_print_float(mV);OLED_printf("V\n");

    ADC_input(PA1);// variable resistor 10K
    adc_val = ADC_read();
    mV = VDD_mV * adc_val / 4095;
    OLED_printf("PIN A1 %d/", adc_val);
    OLED_print_float(mV);OLED_printf("V\n");

    // OLED_printf("VDD ");
    // OLED_print_float(ADC_read_VDD());OLED_printf("V\n");

    DLY_ms(20);
  }
}
wagiminator commented 2 days ago

Hi, and thanks for the hint! I'm a bit busy at the moment, but as soon as I have some free time, I'll try to find a solution.

dzanis commented 13 hours ago

Hi, and thanks for the hint! I'm a bit busy at the moment, but as soon as I have some free time, I'll try to find a solution.

Hello. There is something that can help understand the reason. It works fine if you don't use it ADC_enable() after initialization ADC_init(). It's strange, we still need to understand why (switch on) confuses the polling of more than one channel.