Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
146 changes: 146 additions & 0 deletions cores/arduino/wiring_digital.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,149 @@ PinStatus digitalRead(pin_size_t 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)
{
// Reset the ADC to init all regs
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;
}
33 changes: 33 additions & 0 deletions examples/CH32V003-ADC/CH32V003-ADC.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <stdio.h>
#include <Arduino.h>



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);
}