Skip to content

Commit

Permalink
Switch everything around and add funAnalog*, add ANALOG_ macros, impr…
Browse files Browse the repository at this point in the history
…ove documentation about GPIO/examples
  • Loading branch information
cnlohr committed Sep 27, 2024
1 parent 72a1fd9 commit 1061595
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 109 deletions.
40 changes: 40 additions & 0 deletions ch32v003fun/ch32v003fun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1472,6 +1472,46 @@ WEAK int putchar(int c)
return 1;
}

void funAnalogInit()
{
//RCC->CFGR0 &= ~(0x1F<<11); // Assume ADCPRE = 0
RCC->APB2PCENR |= RCC_APB2Periph_ADC1;

// Reset ADC.
RCC->APB2PRSTR |= RCC_APB2Periph_ADC1;
RCC->APB2PRSTR &= ~RCC_APB2Periph_ADC1;

// set sampling time for all channels to 15 (A good middleground) ADC_SMP0_1.
ADC1->SAMPTR2 = (ADC_SMP0_1<<(3*0)) | (ADC_SMP0_1<<(3*1)) | (ADC_SMP0_1<<(3*2)) | (ADC_SMP0_1<<(3*3)) | (ADC_SMP0_1<<(3*4)) | (ADC_SMP0_1<<(3*5)) | (ADC_SMP0_1<<(3*6)) | (ADC_SMP0_1<<(3*7)) | (ADC_SMP0_1<<(3*8)) | (ADC_SMP0_1<<(3*9));
ADC1->SAMPTR1 = (ADC_SMP0_1<<(3*0)) | (ADC_SMP0_1<<(3*1)) | (ADC_SMP0_1<<(3*2)) | (ADC_SMP0_1<<(3*3)) | (ADC_SMP0_1<<(3*4)) | (ADC_SMP0_1<<(3*5));

ADC1->CTLR2 |= ADC_ADON | ADC_EXTSEL; // turn on ADC and set rule group to sw trig

// Reset calibration
ADC1->CTLR2 |= ADC_RSTCAL;
while(ADC1->CTLR2 & ADC_RSTCAL);

// Calibrate
ADC1->CTLR2 |= ADC_CAL;
while(ADC1->CTLR2 & ADC_CAL);

}


int funAnalogRead( int nAnalogNumber )
{
ADC1->RSQR3 = nAnalogNumber;

// start sw conversion (auto clears)
ADC1->CTLR2 |= ADC_SWSTART;

// wait for conversion complete
while(!(ADC1->STATR & ADC_EOC));

// get result
return ADC1->RDATAR;
}

void SetupDebugPrintf()
{
// Clear out the sending flag.
Expand Down
26 changes: 23 additions & 3 deletions ch32v003fun/ch32v003fun.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
funPinMode( PA2, GPIO_CFGLR_OUT_10Mhz_PP );
funDigitalWrite( PA2, FUN_HIGH );
funDigitalWrite( PA2, FUN_HIGH );
funAnalogRead( 0 ); // Not Pin number, but rather analog number.

4. Delays
Delay_Us(n)
Expand Down Expand Up @@ -13659,9 +13660,28 @@ extern "C" {
#define funGpioInitA() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA ); }
#define funGpioInitC() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC ); }
#define funGpioInitD() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD ); }
#define funDigitalRead( pin ) ((GpioOf(pin)->INDR >> ((pin)&0xf)) & 1)


#define funDigitalRead( pin ) ((int)((GpioOf(pin)->INDR >> ((pin)&0xf)) & 1))


#define ANALOG_0 0
#define ANALOG_1 1
#define ANALOG_2 2
#define ANALOG_3 3
#define ANALOG_4 4
#define ANALOG_5 5
#define ANALOG_6 6
#define ANALOG_7 7
#define ANALOG_8 8
#define ANALOG_9 9
#define ANALOG_10 10
#define ANALOG_11 11

// Initialize the ADC calibrate it and set some sane defaults.
void funAnalogInit();

// Read an analog input (not a GPIO pin number)
// Be sure to call funAnalogInit first.
int funAnalogRead( int nAnalogNumber );

#if defined(__riscv) || defined(__riscv__) || defined( CH32V003FUN_BASE )

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
all : flash

TARGET:=gpio_and_adc_injection_test
TARGET:=adc_injection

include ../../ch32v003fun/ch32v003fun.mk

Expand Down
95 changes: 95 additions & 0 deletions examples/adc_injection/adc_injection.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Basic GPIO and Injection-Mode ADC Example using modern funPinMode / funDigitalWrite / etc... modes.
//
// The ADC has two modes: Rule and Injection.
// Injection allows you to read up to 4 ADCs in rapid succession.
// But there is no rule at the end for checking completion of conversion... So it's usually only good for continuous monitoring.
//
// This demo should alternate between 0 and 1023 for the first 3 channels, and the 4th channel will go a little bit up/down but only because of latent capacitance.

#include "ch32v003fun.h"
#include <stdio.h>

int main()
{
SystemInit();

funGpioInitAll();

// You can use pull-up/pull-down in conjuction with ADC.
funPinMode( PA1, GPIO_CFGLR_IN_PUPD );
funPinMode( PA2, GPIO_CFGLR_IN_PUPD );
funPinMode( PC4, GPIO_CFGLR_IN_PUPD );
funPinMode( PD2, GPIO_CFGLR_IN_ANALOG );

// Enable ADC
RCC->APB2PCENR |= RCC_APB2Periph_ADC1;

// Reset the ADC to init all regs
RCC->APB2PRSTR |= RCC_APB2Periph_ADC1;
RCC->APB2PRSTR &= ~RCC_APB2Periph_ADC1;

// Setup channel conversion situation
ADC1->ISQR=
ADC_JL_0 | ADC_JL_1 | // 4 Total channels
ADC_JSQ4_1 | ADC_JSQ4_0 | // Channel 3 (PD2)
ADC_JSQ3_1 | // Channel 2 (PC4)
ADC_JSQ2_0 | // Channel 1 (PA1)
0; // Channel 0 (PA2)

// Once we read the analog values will be populated in the following:
// ADC1->JSQ1 = Channel 0 (PA2)
// ADC1->JSQ2 = Channel 1 (PA1)
// ADC1->JSQ3 = Channel 2 (PC4)
// ADC1->JSQ3 = Channel 3 (PD2)

// Setup sampling time
// 0:7 => 3/9/15/30/43/57/73/241 cycles
ADC1->SAMPTR2 |=
ADC_SMP0_0 | ADC_SMP0_1 | ADC_SMP0_2 | \
ADC_SMP1_0 | ADC_SMP1_1 | ADC_SMP1_2 | \
ADC_SMP2_0 | ADC_SMP2_1 | ADC_SMP2_2 | \
ADC_SMP3_1 | ADC_SMP3_1 | ADC_SMP3_2;

// turn on ADC and set rule group to sw trig
// Additionally ADC_CONT says just continuously read the values.
ADC1->CTLR2 = ADC_ADON | ADC_JEXTSEL | ADC_CONT;

ADC1->CTLR1 = ADC_SCAN;

// Reset calibration
ADC1->CTLR2 |= ADC_RSTCAL;
while(ADC1->CTLR2 & ADC_RSTCAL);

// Calibrate
ADC1->CTLR2 |= ADC_CAL;
while(ADC1->CTLR2 & ADC_CAL);

// Tell the ADC to start converting, continously.
ADC1->CTLR2 |= ADC_JSWSTART;

while(1)
{
funDigitalWrite( PD2, FUN_HIGH );
funDigitalWrite( PC4, FUN_HIGH );
funDigitalWrite( PA1, FUN_HIGH );
funDigitalWrite( PA2, FUN_HIGH );

Delay_Us(50); // Give the pins about 50us to get some ADC readings in.

printf( "1: %d %d %d %d\n", (int)ADC1->IDATAR1, (int)ADC1->IDATAR2, (int)ADC1->IDATAR3, (int)ADC1->IDATAR4 );

Delay_Ms(1000);

funDigitalWrite( PD2, FUN_LOW );
funDigitalWrite( PC4, FUN_LOW );
funDigitalWrite( PA1, FUN_LOW );
funDigitalWrite( PA2, FUN_LOW );

Delay_Us(50); // Give the pins about 50us to get some ADC readings in.

printf( "0: %d %d %d %d\n", (int)ADC1->IDATAR1, (int)ADC1->IDATAR2, (int)ADC1->IDATAR3, (int)ADC1->IDATAR4 );

Delay_Ms(1000);
}
}

File renamed without changes.
10 changes: 10 additions & 0 deletions examples/gpio_and_adc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
all : flash

TARGET:=gpio_and_adc

include ../../ch32v003fun/ch32v003fun.mk

flash : cv_flash
clean : cv_clean


7 changes: 7 additions & 0 deletions examples/gpio_and_adc/funconfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef _FUNCONFIG_H
#define _FUNCONFIG_H

#define CH32V003 1

#endif

93 changes: 93 additions & 0 deletions examples/gpio_and_adc/gpio_and_adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Basic GPIO and Injection-Mode ADC Example using modern funPinMode / funDigitalWrite / etc... modes.
//
// Modes (Assume processor VCC = 3.3V)
// Push/Pull:
// * ADC Works.
// * Output 1: GPIO Sources 50mA
// * Output 0: GPIO Sinks 52mA
// Open Drain
// (PC1, 2, 5, 6, 5V tolerant pins)
// * Output 1: if 5V is applied, no current flows.
// * Output 0: Pin is driven low.
// Open Drain (Other pins)
// * Very high Z - "1"
// * Sink 52mA - "0"
// * If 5V is applied, pin sinks 20mA (or 86mA if driven low)
// Analog or Float
// * No sinking or sourcing
// * Output 0 or 1 has no effect.
// * No analog pins are 5V tolerant.
// * If 5V is applied to 5v-tolearnt pin (PC1, 2, 5, 6, 5V tolerant pins) no current flows.
// * If 5V is applied to other pins, pin sinks 20mA from 5V
// PU/PD
// * Pull-up and Pull-down.
// * Output 1: pin sources 76uA from GND.
// * Output 0: pin sinks 76uA from 3.3v.
// * I.e. If you want to have a pull-up, configure PUPD, then set output to 1.
// * If 5V is applied, pin sinks 20mA.
// * If within 0...3.3V, pretend it has 45k Ohms.

#include "ch32v003fun.h"
#include <stdio.h>

int main()
{
SystemInit();

funGpioInitAll();
funAnalogInit();

funPinMode( PA1, GPIO_CFGLR_IN_ANALOG ); // Corresponds to analog in A0
funPinMode( PA2, GPIO_CFGLR_IN_PUPD ); // Corresponds to analog in A1
funPinMode( PC4, GPIO_CFGLR_OUT_50Mhz_OD ); // Corresponds to analog in A2
funPinMode( PD2, GPIO_CFGLR_OUT_50Mhz_PP ); // Corresponds to analog in A3
funPinMode( PC1, GPIO_CFGLR_OUT_50Mhz_OD ); // PC1 = 5V tolerant (so no ADC)

while(1)
{
// Drive digitals high
funDigitalWrite( PA1, FUN_HIGH /* = 1 */ );
funDigitalWrite( PA2, FUN_HIGH );
funDigitalWrite( PC4, FUN_HIGH );
funDigitalWrite( PD2, FUN_HIGH );
funDigitalWrite( PC1, FUN_HIGH ); // 5v tolerant, no ADC

Delay_Ms(1000);

printf( "1: %d %d %d %d\n",
funAnalogRead( ANALOG_0 ),
funAnalogRead( ANALOG_1 ),
funAnalogRead( ANALOG_2 ),
funAnalogRead( ANALOG_3 ) );

printf( " %d %d %d %d %d\n\n",
funDigitalRead( PA1 ),
funDigitalRead( PA2 ),
funDigitalRead( PC4 ),
funDigitalRead( PD2 ),
funDigitalRead( PC1 ) );

// Drive digitals low
funDigitalWrite( PA1, FUN_LOW /* = 0 */ );
funDigitalWrite( PA2, FUN_LOW );
funDigitalWrite( PC4, FUN_LOW );
funDigitalWrite( PD2, FUN_LOW );
funDigitalWrite( PC1, FUN_LOW ); // 5v tolerant, no ADC

Delay_Ms(1000);

printf( "0: %d %d %d %d\n",
funAnalogRead( ANALOG_0 ),
funAnalogRead( ANALOG_1 ),
funAnalogRead( ANALOG_2 ),
funAnalogRead( ANALOG_3 ) );

printf( " %d %d %d %d %d\n\n",
funDigitalRead( PA1 ),
funDigitalRead( PA2 ),
funDigitalRead( PC4 ),
funDigitalRead( PD2 ),
funDigitalRead( PC1 ) );
}
}

Loading

0 comments on commit 1061595

Please sign in to comment.