libOpenCM3 opamp config routines and definitions for STM32F303
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
libopencm3_stm32f3_opamp/opamp.h

286 lignes
7.2 KiB

#pragma once
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/f3/memorymap.h>
// Opamp base address (just one register)
#define OPAMP1_BASE OPAMP_BASE + 0x38
#define OPAMP2_BASE OPAMP_BASE + 0x3C
#define OPAMP3_BASE OPAMP_BASE + 0x40
#define OPAMP4_BASE OPAMP_BASE + 0x44
// opamp constants
#define OPAMP1 OPAMP1_BASE
#define OPAMP2 OPAMP2_BASE
#define OPAMP3 OPAMP3_BASE
#define OPAMP4 OPAMP4_BASE
#define OPAMP_CSR(opamp_base) MMIO32(opamp_base + 0)
#define OPAMP_CSR_LOCK (1 << 31)
#define OPAMP_CSR_OUTCAL (1 << 30)
#define OPAMP_CSR_TSTREF (1 << 29)
// trim registers
#define OPAMP_CSR_TRIMOFFSETN_SHIFT 24
#define OPAMP_CSR_TRIMOFFSETP_SHIFT 19
#define OPAMP_CSR_TRIMOFFSETN_MSK (0x1F << OPAMP_CSR_TRIMOFFSETN_SHIFT)
#define OPAMP_CSR_TRIMOFFSETP_MSK (0x1F << OPAMP_CSR_TRIMOFFSETP_SHIFT)
// user trim
#define OPAMP_CSR_USER_TRIM (1 << 18)
// PGA gain
#define OPAMP_CSR_PGA_GAIN_SHIFT 14
#define OPAMP_CSR_PGA_GAIN_MSK (0b0011 << OPAMP_CSR_PGA_GAIN_SHIFT)
#define OPAMP_CSR_PGA_MIDPOINT_MSK (0b1100 << OPAMP_CSR_PGA_GAIN_SHIFT)
// lower two bits
enum OPAMP_PGA_GAIN {
OPAMP_PGA_GAIN_2 = (0 << OPAMP_CSR_PGA_GAIN_SHIFT),
OPAMP_PGA_GAIN_4 = (1 << OPAMP_CSR_PGA_GAIN_SHIFT),
OPAMP_PGA_GAIN_8 = (2 << OPAMP_CSR_PGA_GAIN_SHIFT),
OPAMP_PGA_GAIN_16 = (3 << OPAMP_CSR_PGA_GAIN_SHIFT)
};
// Masks that can be used to adjust PGA value
enum OPAMP_PGA_MIDPOINT {
OPAMP_PGA_MIDPOINT_NONE = 0,
OPAMP_PGA_MIDPOINT_VM0 = (0b1000 << OPAMP_CSR_PGA_GAIN_SHIFT),
OPAMP_PGA_MIDPOINT_VM1 = (0b1100 << OPAMP_CSR_PGA_GAIN_SHIFT)
};
// Calibration select
#define OPAMP_CSR_CALSEL_SHIFT 12
#define OPAMP_CSR_CALSEL_MSK (0b11 << OPAMP_CSR_CALSEL_SHIFT)
enum OPAMP_CALSEL {
OPAMP_CALSEL_3P3 = (0 << OPAMP_CSR_CALSEL_SHIFT),
OPAMP_CALSEL_10 = (1 << OPAMP_CSR_CALSEL_SHIFT),
OPAMP_CALSEL_50 = (2 << OPAMP_CSR_CALSEL_SHIFT),
OPAMP_CALSEL_90 = (3 << OPAMP_CSR_CALSEL_SHIFT),
};
// Cal On
#define OPAMP_CSR_CALON (1 << 11)
// Non-inverting input, secondary
#define OPAMP_CSR_VPS_SEL_SHIFT 9
#define OPAMP_CSR_VPS_SEL_MSK (0b11 << OPAMP_CSR_VPS_SEL_SHIFT)
enum OPAMP_VPS_SEL {
OPAMP_VPS_SEL_VP0 = (0 << OPAMP_CSR_VPS_SEL_SHIFT),
OPAMP_VPS_SEL_VP1 = (1 << OPAMP_CSR_VPS_SEL_SHIFT),
OPAMP_VPS_SEL_VP2 = (2 << OPAMP_CSR_VPS_SEL_SHIFT),
OPAMP_VPS_SEL_VP3 = (3 << OPAMP_CSR_VPS_SEL_SHIFT),
// The following are just aliases for convenience, mapped for F303.
// probably should not be included in the library, as they're too specific.
// same for the following enums.
OPAMP1_VPS_SEL_PA7 = OPAMP_VPS_SEL_VP0,
OPAMP1_VPS_SEL_PA5 = OPAMP_VPS_SEL_VP1,
OPAMP1_VPS_SEL_PA3 = OPAMP_VPS_SEL_VP2,
OPAMP1_VPS_SEL_PA1 = OPAMP_VPS_SEL_VP3,
OPAMP2_VPS_SEL_PD14 = OPAMP_VPS_SEL_VP0,
OPAMP2_VPS_SEL_PB14 = OPAMP_VPS_SEL_VP1,
OPAMP2_VPS_SEL_PB0 = OPAMP_VPS_SEL_VP2,
OPAMP2_VPS_SEL_PA7 = OPAMP_VPS_SEL_VP3,
OPAMP3_VPS_SEL_PB13 = OPAMP_VPS_SEL_VP0,
OPAMP3_VPS_SEL_PA5 = OPAMP_VPS_SEL_VP1,
OPAMP3_VPS_SEL_PA1 = OPAMP_VPS_SEL_VP2,
OPAMP3_VPS_SEL_PB0 = OPAMP_VPS_SEL_VP3,
OPAMP4_VPS_SEL_PD11 = OPAMP_VPS_SEL_VP0,
OPAMP4_VPS_SEL_PB11 = OPAMP_VPS_SEL_VP1,
OPAMP4_VPS_SEL_PA4 = OPAMP_VPS_SEL_VP2,
OPAMP4_VPS_SEL_PB13 = OPAMP_VPS_SEL_VP3
};
// Inverting input, secondary
#define OPAMP_CSR_VMS_SEL_SHIFT 8
#define OPAMP_CSR_VMS_SEL_MSK (1 << OPAMP_CSR_VMS_SEL_SHIFT)
enum OPAMP_VMS_SEL {
OPAMP_VMS_SEL_VM0 = (0 << OPAMP_CSR_VMS_SEL_SHIFT),
OPAMP_VMS_SEL_VM1 = (1 << OPAMP_CSR_VMS_SEL_SHIFT),
OPAMP1_VMS_SEL_PC5 = OPAMP_VMS_SEL_VM0,
OPAMP1_VMS_SEL_PA3 = OPAMP_VMS_SEL_VM1,
OPAMP2_VMS_SEL_PC5 = OPAMP_VMS_SEL_VM0,
OPAMP2_VMS_SEL_PA5 = OPAMP_VMS_SEL_VM1,
OPAMP3_VMS_SEL_PB10 = OPAMP_VMS_SEL_VM0,
OPAMP3_VMS_SEL_PB2 = OPAMP_VMS_SEL_VM1,
OPAMP4_VMS_SEL_PB10 = OPAMP_VMS_SEL_VM0,
OPAMP4_VMS_SEL_PD8 = OPAMP_VMS_SEL_VM1,
};
// Cal On
#define OPAMP_CSR_TCM_EN (1 << 7)
// Inverting input, primary
#define OPAMP_CSR_VM_SEL_SHIFT 5
#define OPAMP_CSR_VM_SEL_MSK (0b11 << OPAMP_CSR_VM_SEL_SHIFT)
enum OPAMP_VM_SEL {
OPAMP_VM_SEL_VM0 = (0 << OPAMP_CSR_VM_SEL_SHIFT),
OPAMP_VM_SEL_VM1 = (1 << OPAMP_CSR_VM_SEL_SHIFT),
OPAMP_VM_SEL_PGA = (2 << OPAMP_CSR_VM_SEL_SHIFT),
OPAMP_VM_SEL_FLW = (3 << OPAMP_CSR_VM_SEL_SHIFT),
OPAMP1_VM_SEL_PC5 = OPAMP_VM_SEL_VM0,
OPAMP1_VM_SEL_PA3 = OPAMP_VM_SEL_VM1,
OPAMP1_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
OPAMP1_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
OPAMP2_VM_SEL_PC5 = OPAMP_VM_SEL_VM0,
OPAMP2_VM_SEL_PA5 = OPAMP_VM_SEL_VM1,
OPAMP2_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
OPAMP2_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
OPAMP3_VM_SEL_PB10 = OPAMP_VM_SEL_VM0,
OPAMP3_VM_SEL_PB2 = OPAMP_VM_SEL_VM1,
OPAMP3_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
OPAMP3_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
OPAMP4_VM_SEL_PB10 = OPAMP_VM_SEL_VM0,
OPAMP4_VM_SEL_PD8 = OPAMP_VM_SEL_VM1,
OPAMP4_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
OPAMP4_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
};
// Non-inverting input, primary
#define OPAMP_CSR_VP_SEL_SHIFT 2
#define OPAMP_CSR_VP_SEL_MSK (0b11 << OPAMP_CSR_VP_SEL_SHIFT)
enum OPAMP_VP_SEL {
OPAMP_VP_SEL_VP0 = (0 << OPAMP_CSR_VP_SEL_SHIFT),
OPAMP_VP_SEL_VP1 = (1 << OPAMP_CSR_VP_SEL_SHIFT),
OPAMP_VP_SEL_VP2 = (2 << OPAMP_CSR_VP_SEL_SHIFT),
OPAMP_VP_SEL_VP3 = (3 << OPAMP_CSR_VP_SEL_SHIFT),
OPAMP1_VP_SEL_PA7 = OPAMP_VP_SEL_VP0,
OPAMP1_VP_SEL_PA5 = OPAMP_VP_SEL_VP1,
OPAMP1_VP_SEL_PA3 = OPAMP_VP_SEL_VP2,
OPAMP1_VP_SEL_PA1 = OPAMP_VP_SEL_VP3,
OPAMP2_VP_SEL_PD14 = OPAMP_VP_SEL_VP0,
OPAMP2_VP_SEL_PB14 = OPAMP_VP_SEL_VP1,
OPAMP2_VP_SEL_PB0 = OPAMP_VP_SEL_VP2,
OPAMP2_VP_SEL_PA7 = OPAMP_VP_SEL_VP3,
OPAMP3_VP_SEL_PB13 = OPAMP_VP_SEL_VP0,
OPAMP3_VP_SEL_PA5 = OPAMP_VP_SEL_VP1,
OPAMP3_VP_SEL_PA1 = OPAMP_VP_SEL_VP2,
OPAMP3_VP_SEL_PB0 = OPAMP_VP_SEL_VP3,
OPAMP4_VP_SEL_PD11 = OPAMP_VP_SEL_VP0,
OPAMP4_VP_SEL_PB11 = OPAMP_VP_SEL_VP1,
OPAMP4_VP_SEL_PA4 = OPAMP_VP_SEL_VP2,
OPAMP4_VP_SEL_PB13 = OPAMP_VP_SEL_VP3
};
// Forve VP - VP connected to calibration reference
#define OPAMP_CSR_FORCE_VP (1 << 1)
// Enable opamp
#define OPAMP_CSR_OPAMPEN (1 << 0)
// -------------- Functions ----------------
/** Lock the opamp config. No way to unlock until restart. */
void opamp_lock(uint32_t opamp);
/**
* Enable OPAMP
* Must also enable RCC_SYSCFG_COMP in RCC
*/
void opamp_enable(uint32_t opamp);
/** Disable OPAMP */
void opamp_disable(uint32_t opamp);
/** Send reference to ADC input channel */
void opamp_ref_to_adc(uint32_t opamp, bool yes);
/** Send reference to non-inverting input */
void opamp_ref_to_vp(uint32_t opamp, bool yes);
/**
* Set PGA gain.
* To use PGA, call opamp_mode_pga() first.
*/
void opamp_pga_set_gain(uint32_t opamp, enum OPAMP_PGA_GAIN gain);
/** Set PGA midpoint routing */
void opamp_pga_set_midpoint(uint32_t opamp, enum OPAMP_PGA_MIDPOINT midpoint);
/** Connect VM pin (can be used to select follower and PGA mode) */
void opamp_vm_select(uint32_t opamp, enum OPAMP_VM_SEL vm);
/** Connect the VP pin */
void opamp_vp_select(uint32_t opamp, enum OPAMP_VP_SEL vp);
/**
* Set opamp to PGA mode (shortcut function)
* Midpoint can be connected to VM pins with opamp_pga_set_midpoint()
*/
void opamp_mode_pga(uint32_t opamp);
/**
* Set opamp to follower mode (shortcut function).
* VM is not connected to GPIO in this mode.
*/
void opamp_mode_follower(uint32_t opamp);
/** Select reference value to use */
void opamp_ref_select(uint32_t opamp, enum OPAMP_CALSEL ref);
/** Calibrate an OpAmp */
bool opamp_calibrate(uint32_t opamp);