From b282465ebb93b7402a1f16d6b6a43c03d1e1740a Mon Sep 17 00:00:00 2001 From: sintrb Date: Fri, 12 Jul 2024 00:18:50 +0800 Subject: [PATCH 1/2] add ADC support --- cores/arduino/Arduino.h | 3 + cores/arduino/wiring_digital.cpp | 145 +++++++++++++++++++++++++ examples/CH32V003-ADC/CH32V003-ADC.ino | 33 ++++++ 3 files changed, 181 insertions(+) create mode 100644 examples/CH32V003-ADC/CH32V003-ADC.ino diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index cfb1985..c017451 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -52,4 +52,7 @@ void analogReadResolution(int bits); void analogWriteResolution(int bits); +#define ADC_CH_REF 0x40 // Vref +#define ADC_CH_CAL 0x41 // Vcal + #endif \ No newline at end of file diff --git a/cores/arduino/wiring_digital.cpp b/cores/arduino/wiring_digital.cpp index 2f45e52..45b1e17 100644 --- a/cores/arduino/wiring_digital.cpp +++ b/cores/arduino/wiring_digital.cpp @@ -111,4 +111,149 @@ PinStatus digitalRead(pin_size_t pin) uint8_t p = gpioPin(gpio, pin); return (port->INDR & (1 << p)) != 0 ? HIGH : LOW; +} +int analogRead(uint8_t pin) +{ + /* + GPIO -> ADC Channel + PA2 -> A0 + PA1 -> A1 + PC4 -> A2 + PD2 -> A3 + PD3 -> A4 + PD5 -> A5 + PD6 -> A6 + PD4 -> A7 + ADC_CH_REF -> A8 + ADC_CH_CAL -> A9 + */ + static uint8_t last = 0xff; + if (last != pin) + { + uint32_t peripheral = 0; + uint8_t pin_index = 0; // Pin num + uint8_t adc_channel = 0; // Channel + GPIO_TypeDef *gpio; + switch (pin) + { + case A2: // A0 + peripheral = RCC_APB2Periph_GPIOA; + gpio = GPIOA; + pin_index = 2; + adc_channel = 0; + break; + + case A1: // A1 + peripheral = RCC_APB2Periph_GPIOA; + gpio = GPIOA; + pin_index = 1; + adc_channel = 1; + break; + + case C4: // A2 + peripheral = RCC_APB2Periph_GPIOC; + gpio = GPIOC; + pin_index = 4; + adc_channel = 2; + break; + + case D2: // A3 + peripheral = RCC_APB2Periph_GPIOD; + gpio = GPIOD; + pin_index = 2; + adc_channel = 3; + break; + + case D3: // A4 + peripheral = RCC_APB2Periph_GPIOD; + gpio = GPIOD; + pin_index = 3; + adc_channel = 4; + break; + + case D5: // A5 + peripheral = RCC_APB2Periph_GPIOD; + gpio = GPIOD; + pin_index = 5; + adc_channel = 5; + break; + + case D6: // A6 + peripheral = RCC_APB2Periph_GPIOD; + gpio = GPIOD; + pin_index = 6; + adc_channel = 6; + break; + + case D4: // A7 + peripheral = RCC_APB2Periph_GPIOD; + gpio = GPIOD; + pin_index = 4; + adc_channel = 7; + break; + + case ADC_CH_REF: // A8 + peripheral = 0; + gpio = NULL; + pin_index = 8; + adc_channel = 8; + break; + + case ADC_CH_CAL: // A9 + peripheral = 0; + gpio = NULL; + pin_index = 9; + adc_channel = 9; + break; + default: + return 0; + break; + } + + // ADCCLK = 24 MHz => RCC_ADCPRE = 0: divide by 2 + RCC->CFGR0 &= ~(0x1F << 11); + RCC->APB2PCENR |= peripheral | RCC_APB2Periph_ADC1; + + // PXi is analog input chl 7 + if (gpio) + gpio->CFGLR &= ~(0xf << (4 * pin_index)); // CNF = 00: Analog, MODE = 00: Input + + // Reset the ADC to init all regs + RCC->APB2PRSTR |= RCC_APB2Periph_ADC1; + RCC->APB2PRSTR &= ~RCC_APB2Periph_ADC1; + + // Set up single conversion on chl 7 + ADC1->RSQR1 = 0; + ADC1->RSQR2 = 0; + ADC1->RSQR3 = adc_channel; // A0通道 + + // set sampling time for chl 7 + ADC1->SAMPTR2 &= ~(ADC_SMP0 << (3 * 7)); + ADC1->SAMPTR2 |= 7 << (3 * 7); // 0:7 => 3/9/15/30/43/57/73/241 cycles + + // turn on ADC and set rule group to sw trig + ADC1->CTLR2 |= ADC_ADON | ADC_EXTSEL; + + // Reset calibration + ADC1->CTLR2 |= ADC_RSTCAL; + while (ADC1->CTLR2 & ADC_RSTCAL) + ; + + // Calibrate + ADC1->CTLR2 |= ADC_CAL; + while (ADC1->CTLR2 & ADC_CAL) + ; + last = pin; + } + + // should be ready for SW conversion now + + ADC1->CTLR2 |= ADC_SWSTART; + + // wait for conversion complete + while (!(ADC1->STATR & ADC_EOC)) + ; + + // get result + return ADC1->RDATAR; } \ No newline at end of file diff --git a/examples/CH32V003-ADC/CH32V003-ADC.ino b/examples/CH32V003-ADC/CH32V003-ADC.ino new file mode 100644 index 0000000..006623f --- /dev/null +++ b/examples/CH32V003-ADC/CH32V003-ADC.ino @@ -0,0 +1,33 @@ +#include +#include + + + +uint8_t adc_pins[] = { + A2, // A0 + A1, // A1 + C4, // A2 + D2, // A3 + D3, // A4 + D5, // A5 + D6, // A6 + D4, // A7 + ADC_CH_REF, // A8 + ADC_CH_CAL, // A9 +}; + + +void setup() +{ + +} + +void loop() +{ + printf("------------\n"); + for (int i = 0; i < sizeof(adc_pins); i++) + { + printf("ADC %d V=%d\n", i, analogRead(adc_pins[i])); + } + delay(3000); +} From ebf256ba514694d1ecdc736f6ecf6ee31edbcf26 Mon Sep 17 00:00:00 2001 From: sintrb Date: Fri, 6 Sep 2024 18:08:17 +0800 Subject: [PATCH 2/2] add ADC support --- cores/arduino/wiring_digital.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/arduino/wiring_digital.cpp b/cores/arduino/wiring_digital.cpp index 45b1e17..63ae54c 100644 --- a/cores/arduino/wiring_digital.cpp +++ b/cores/arduino/wiring_digital.cpp @@ -130,6 +130,7 @@ int analogRead(uint8_t pin) static uint8_t last = 0xff; if (last != pin) { + // Reset the ADC to init all regs uint32_t peripheral = 0; uint8_t pin_index = 0; // Pin num uint8_t adc_channel = 0; // Channel