github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_stm32_adc_f1.go (about)

     1  //go:build stm32f103
     2  
     3  package machine
     4  
     5  import (
     6  	"device/stm32"
     7  	"unsafe"
     8  )
     9  
    10  const (
    11  	Cycles_1_5   = 0x0
    12  	Cycles_7_5   = 0x1
    13  	Cycles_13_5  = 0x2
    14  	Cycles_28_5  = 0x3
    15  	Cycles_41_5  = 0x4
    16  	Cycles_55_5  = 0x5
    17  	Cycles_71_5  = 0x6
    18  	Cycles_239_5 = 0x7
    19  )
    20  
    21  // InitADC initializes the registers needed for ADC1.
    22  func InitADC() {
    23  	// Enable ADC clock
    24  	enableAltFuncClock(unsafe.Pointer(stm32.ADC1))
    25  
    26  	// set scan mode
    27  	stm32.ADC1.CR1.SetBits(stm32.ADC_CR1_SCAN)
    28  
    29  	// clear CONT, ALIGN, EXTRIG and EXTSEL bits from CR2
    30  	stm32.ADC1.CR2.ClearBits(stm32.ADC_CR2_CONT | stm32.ADC_CR2_ALIGN | stm32.ADC_CR2_EXTTRIG_Msk | stm32.ADC_CR2_EXTSEL_Msk)
    31  
    32  	stm32.ADC1.SQR1.ClearBits(stm32.ADC_SQR1_L_Msk)
    33  	stm32.ADC1.SQR1.SetBits(2 << stm32.ADC_SQR1_L_Pos) // 2 means 3 conversions
    34  
    35  	// enable
    36  	stm32.ADC1.CR2.SetBits(stm32.ADC_CR2_ADON)
    37  
    38  	return
    39  }
    40  
    41  // Configure configures an ADC pin to be able to read analog data.
    42  func (a ADC) Configure(ADCConfig) {
    43  	a.Pin.Configure(PinConfig{Mode: PinInputModeAnalog})
    44  
    45  	// set sample time
    46  	ch := a.getChannel()
    47  	if ch > 9 {
    48  		stm32.ADC1.SMPR1.SetBits(Cycles_28_5 << (ch - 10) * stm32.ADC_SMPR1_SMP11_Pos)
    49  	} else {
    50  		stm32.ADC1.SMPR2.SetBits(Cycles_28_5 << (ch * stm32.ADC_SMPR2_SMP1_Pos))
    51  	}
    52  
    53  	return
    54  }
    55  
    56  // Get returns the current value of a ADC pin in the range 0..0xffff.
    57  // TODO: DMA based implementation.
    58  func (a ADC) Get() uint16 {
    59  	// set rank
    60  	ch := uint32(a.getChannel())
    61  	stm32.ADC1.SQR3.SetBits(ch)
    62  
    63  	// start conversion
    64  	stm32.ADC1.CR2.SetBits(stm32.ADC_CR2_SWSTART)
    65  
    66  	// wait for conversion to complete
    67  	for !stm32.ADC1.SR.HasBits(stm32.ADC_SR_EOC) {
    68  	}
    69  
    70  	// read result as 16 bit value
    71  	result := uint16(stm32.ADC1.DR.Get()) << 4
    72  
    73  	// clear flag
    74  	stm32.ADC1.SR.ClearBits(stm32.ADC_SR_EOC)
    75  
    76  	// clear rank
    77  	stm32.ADC1.SQR3.ClearBits(ch)
    78  
    79  	return result
    80  }
    81  
    82  func (a ADC) getChannel() uint8 {
    83  	switch a.Pin {
    84  	case PA0:
    85  		return 0
    86  	case PA1:
    87  		return 1
    88  	case PA2:
    89  		return 2
    90  	case PA3:
    91  		return 3
    92  	case PA4:
    93  		return 4
    94  	case PA5:
    95  		return 5
    96  	case PA6:
    97  		return 6
    98  	case PA7:
    99  		return 7
   100  	case PB0:
   101  		return 8
   102  	case PB1:
   103  		return 9
   104  	}
   105  
   106  	return 0
   107  }