stm: Improved ADC module; add BOARD_NAME config value.
This commit is contained in:
parent
b829b5caec
commit
51f3a6becd
239
stm/adc.c
239
stm/adc.c
@ -2,6 +2,7 @@
|
||||
#include <stm32f4xx.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "nlr.h"
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
@ -41,7 +42,7 @@ typedef struct {
|
||||
} gpio_t;
|
||||
|
||||
/* ADC GPIOs */
|
||||
static gpio_t adc_gpio[] = {
|
||||
static const gpio_t adc_gpio[] = {
|
||||
{GPIOA, GPIO_Pin_0}, /* ADC123_IN0 */
|
||||
{GPIOA, GPIO_Pin_1}, /* ADC123_IN1 */
|
||||
{GPIOA, GPIO_Pin_2}, /* ADC123_IN2 */
|
||||
@ -61,7 +62,7 @@ static gpio_t adc_gpio[] = {
|
||||
|
||||
};
|
||||
|
||||
void adc_init(uint32_t resolution) {
|
||||
void adc_init_all(uint32_t resolution) {
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
||||
@ -111,6 +112,54 @@ void adc_init(uint32_t resolution) {
|
||||
ADC_TempSensorVrefintCmd(ENABLE);
|
||||
}
|
||||
|
||||
void adc_init_single(uint32_t channel) {
|
||||
ADC_InitTypeDef ADC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
||||
|
||||
/* Enable ADCx, DMA and GPIO clocks */
|
||||
#if 0
|
||||
/* GPIO clocks enabled in main */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
|
||||
RCC_AHB1Periph_GPIOB |
|
||||
RCC_AHB1Periph_GPIOC, ENABLE);
|
||||
#endif
|
||||
RCC_APB2PeriphClockCmd(ADCx_CLK, ENABLE);
|
||||
|
||||
/* ADC Common Init */
|
||||
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
|
||||
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
|
||||
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
|
||||
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||
ADC_CommonInit(&ADC_CommonInitStructure);
|
||||
|
||||
/* Configure ADC GPIO for the single channel */
|
||||
GPIO_InitStructure.GPIO_Pin = adc_gpio[channel].pin;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(adc_gpio[channel].port, &GPIO_InitStructure);
|
||||
|
||||
/* ADCx Init */
|
||||
// ADC_DeInit();
|
||||
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
|
||||
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
|
||||
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
|
||||
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
|
||||
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
|
||||
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
|
||||
ADC_InitStructure.ADC_NbrOfConversion = 1;
|
||||
ADC_Init(ADCx, &ADC_InitStructure);
|
||||
|
||||
/* Enable ADCx */
|
||||
ADC_Cmd(ADCx, ENABLE);
|
||||
|
||||
/* Enable VBAT/VREF monitor */
|
||||
ADC_VBATCmd(ENABLE);
|
||||
|
||||
/* Enable temperature sensor */
|
||||
ADC_TempSensorVrefintCmd(ENABLE);
|
||||
}
|
||||
|
||||
uint32_t adc_read_channel(int channel)
|
||||
{
|
||||
int timeout = 10000;
|
||||
@ -213,91 +262,183 @@ float adc_read_core_vref()
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Micro Python bindings */
|
||||
/* Micro Python bindings : adc_all object */
|
||||
|
||||
typedef struct _pyb_adc_obj_t {
|
||||
typedef struct _pyb_obj_adc_all_t {
|
||||
mp_obj_base_t base;
|
||||
int adc_id;
|
||||
bool is_enabled;
|
||||
} pyb_adc_obj_t;
|
||||
} pyb_obj_adc_all_t;
|
||||
|
||||
static mp_obj_t adc_obj_read_channel(mp_obj_t self_in, mp_obj_t channel) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
static void adc_all_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
print(env, "<ADC all>");
|
||||
}
|
||||
|
||||
static mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) {
|
||||
pyb_obj_adc_all_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
uint32_t chan = mp_obj_get_int(channel);
|
||||
uint32_t data = adc_read_channel(chan);
|
||||
ret = mp_obj_new_int(data);
|
||||
return mp_obj_new_int(data);
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_obj_t adc_obj_read_core_temp(mp_obj_t self_in) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
static mp_obj_t adc_all_read_core_temp(mp_obj_t self_in) {
|
||||
pyb_obj_adc_all_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
int data = adc_read_core_temp();
|
||||
ret = mp_obj_new_int(data);
|
||||
return mp_obj_new_int(data);
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_obj_t adc_obj_read_core_vbat(mp_obj_t self_in) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
static mp_obj_t adc_all_read_core_vbat(mp_obj_t self_in) {
|
||||
pyb_obj_adc_all_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
float data = adc_read_core_vbat();
|
||||
ret = mp_obj_new_float(data);
|
||||
return mp_obj_new_float(data);
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_obj_t adc_obj_read_core_vref(mp_obj_t self_in) {
|
||||
mp_obj_t ret = mp_const_none;
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
static mp_obj_t adc_all_read_core_vref(mp_obj_t self_in) {
|
||||
pyb_obj_adc_all_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
float data = adc_read_core_vref();
|
||||
ret = mp_obj_new_float(data);
|
||||
return mp_obj_new_float(data);
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void adc_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_adc_obj_t *self = self_in;
|
||||
print(env, "<ADC %lu>", self->adc_id);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_2(adc_all_read_channel_obj, adc_all_read_channel);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_temp_obj, adc_all_read_core_temp);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vbat_obj, adc_all_read_core_vbat);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_core_vref_obj, adc_all_read_core_vref);
|
||||
|
||||
static MP_DEFINE_CONST_FUN_OBJ_2(adc_obj_read_channel_obj, adc_obj_read_channel);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_temp_obj, adc_obj_read_core_temp);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vbat_obj, adc_obj_read_core_vbat);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vref_obj, adc_obj_read_core_vref);
|
||||
|
||||
static const mp_method_t adc_methods[] = {
|
||||
{ "read_channel", &adc_obj_read_channel_obj},
|
||||
{ "read_core_temp", &adc_obj_read_core_temp_obj},
|
||||
{ "read_core_vbat", &adc_obj_read_core_vbat_obj},
|
||||
{ "read_core_vref", &adc_obj_read_core_vref_obj},
|
||||
static const mp_method_t adc_all_methods[] = {
|
||||
{ "read_channel", &adc_all_read_channel_obj},
|
||||
{ "read_core_temp", &adc_all_read_core_temp_obj},
|
||||
{ "read_core_vbat", &adc_all_read_core_vbat_obj},
|
||||
{ "read_core_vref", &adc_all_read_core_vref_obj},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const mp_obj_type_t adc_obj_type = {
|
||||
static const mp_obj_type_t adc_all_type = {
|
||||
{ &mp_const_type },
|
||||
"ADC",
|
||||
.print = adc_obj_print,
|
||||
.methods = adc_methods,
|
||||
"ADC_all",
|
||||
.print = adc_all_print,
|
||||
.methods = adc_all_methods,
|
||||
};
|
||||
|
||||
mp_obj_t pyb_ADC(mp_obj_t resolution) {
|
||||
mp_obj_t pyb_ADC_all(mp_obj_t resolution) {
|
||||
/* init ADC */
|
||||
adc_init(mp_obj_get_int(resolution));
|
||||
adc_init_all(mp_obj_get_int(resolution));
|
||||
|
||||
pyb_adc_obj_t *o = m_new_obj(pyb_adc_obj_t);
|
||||
o->base.type = &adc_obj_type;
|
||||
o->adc_id = 1;
|
||||
pyb_obj_adc_all_t *o = m_new_obj(pyb_obj_adc_all_t);
|
||||
o->base.type = &adc_all_type;
|
||||
o->is_enabled = true;
|
||||
return o;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_all_obj, pyb_ADC_all);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Micro Python bindings : adc object (single channel) */
|
||||
|
||||
typedef struct _pyb_obj_adc_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t pin_name;
|
||||
int channel;
|
||||
bool is_enabled;
|
||||
} pyb_obj_adc_t;
|
||||
|
||||
static void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_obj_adc_t *self = self_in;
|
||||
print(env, "<ADC on ");
|
||||
mp_obj_print_helper(print, env, self->pin_name, PRINT_STR);
|
||||
print(env, " channel=%lu>", self->channel);
|
||||
}
|
||||
|
||||
static mp_obj_t adc_read(mp_obj_t self_in) {
|
||||
pyb_obj_adc_t *self = self_in;
|
||||
|
||||
if (self->is_enabled) {
|
||||
uint32_t data = adc_read_channel(self->channel);
|
||||
return mp_obj_new_int(data);
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
|
||||
|
||||
static const mp_method_t adc_methods[] = {
|
||||
{ "read", &adc_read_obj},
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const mp_obj_type_t adc_type = {
|
||||
{ &mp_const_type },
|
||||
"ADC",
|
||||
.print = adc_print,
|
||||
.methods = adc_methods,
|
||||
};
|
||||
|
||||
mp_obj_t pyb_ADC(mp_obj_t pin_name_obj) {
|
||||
|
||||
pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
|
||||
o->base.type = &adc_type;
|
||||
o->pin_name = pin_name_obj;
|
||||
|
||||
// work out the channel from the pin name
|
||||
const char *pin_name = mp_obj_str_get_str(pin_name_obj);
|
||||
GPIO_TypeDef *port;
|
||||
switch (pin_name[0]) {
|
||||
case 'A': case 'a': port = GPIOA; break;
|
||||
case 'B': case 'b': port = GPIOB; break;
|
||||
case 'C': case 'c': port = GPIOC; break;
|
||||
default: goto pin_error;
|
||||
}
|
||||
uint pin_num = 0;
|
||||
for (const char *s = pin_name + 1; *s; s++) {
|
||||
if (!('0' <= *s && *s <= '9')) {
|
||||
goto pin_error;
|
||||
}
|
||||
pin_num = 10 * pin_num + *s - '0';
|
||||
}
|
||||
if (!(0 <= pin_num && pin_num <= 15)) {
|
||||
goto pin_error;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < ADC_NUM_CHANNELS; i++) {
|
||||
if (adc_gpio[i].port == port && adc_gpio[i].pin == (1 << pin_num)) {
|
||||
o->channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ADC_NUM_CHANNELS) {
|
||||
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not have ADC capabilities", pin_name));
|
||||
}
|
||||
|
||||
// init ADC just for this channel
|
||||
adc_init_single(o->channel);
|
||||
|
||||
o->is_enabled = true;
|
||||
|
||||
return o;
|
||||
|
||||
pin_error:
|
||||
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not exist", pin_name));
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_obj, pyb_ADC);
|
||||
|
@ -1 +1,2 @@
|
||||
mp_obj_t pyb_ADC(mp_obj_t resolution);
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_all_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_ADC_obj);
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "font_petme128_8x8.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#if defined(PYBOARD)
|
||||
#if defined(PYBOARD3)
|
||||
#define PYB_LCD_PORT (GPIOA)
|
||||
#define PYB_LCD_CS1_PIN (GPIO_Pin_0)
|
||||
#define PYB_LCD_RST_PIN (GPIO_Pin_1)
|
||||
|
@ -122,7 +122,7 @@ void SD_LowLevel_Init(void)
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
/*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */
|
||||
#if defined(PYBOARD)
|
||||
#if defined(PYBOARD3)
|
||||
// dpgeorge: PYBv2-v3: switch is normally open, connected to VDD when card inserted
|
||||
GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // needs to be 2MHz due to restrictions on PC13
|
||||
|
@ -41,7 +41,7 @@
|
||||
/**
|
||||
* @brief SD FLASH SDIO Interface
|
||||
*/
|
||||
#if defined(PYBOARD)
|
||||
#if defined(PYBOARD3)
|
||||
#define SD_DETECT_PIN GPIO_Pin_13 /* PC.13 */
|
||||
#define SD_DETECT_GPIO_PORT GPIOC /* GPIOC */
|
||||
#define SD_DETECT_GPIO_CLK RCC_AHB1Periph_GPIOC
|
||||
|
@ -518,7 +518,7 @@ uint8_t SD_Detect(void)
|
||||
__IO uint8_t status = SD_PRESENT;
|
||||
|
||||
/*!< Check GPIO to detect SD */
|
||||
#if defined(PYBOARD)
|
||||
#if defined(PYBOARD3)
|
||||
if (GPIO_ReadInputDataBit(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != Bit_SET)
|
||||
#elif defined(PYBOARD4)
|
||||
if (GPIO_ReadInputDataBit(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) == Bit_SET)
|
||||
|
@ -137,8 +137,10 @@ static const char *help_text =
|
||||
" pyb.switch() -- return True/False if switch pressed or not\n"
|
||||
" pyb.accel() -- get accelerometer values\n"
|
||||
" pyb.rand() -- get a 16-bit random number\n"
|
||||
" pyb.gpio(<port>) -- get port value (port='a4' for example)\n"
|
||||
" pyb.gpio(<port>) -- get port value (port='A4' for example)\n"
|
||||
" pyb.gpio(<port>, <val>) -- set port value, True or False, 1 or 0\n"
|
||||
" pyb.ADC(<port>) -- make an analog port object (port='C0' for example)\n"
|
||||
" ADC methods: read()\n"
|
||||
;
|
||||
|
||||
// get some help about available functions
|
||||
@ -348,7 +350,7 @@ int readline(vstr_t *line, const char *prompt) {
|
||||
}
|
||||
|
||||
void do_repl(void) {
|
||||
stdout_tx_str("Micro Python build <git hash> on 2/1/2014; PYBv3 with STM32F405RG\r\n");
|
||||
stdout_tx_str("Micro Python build <git hash> on 25/1/2014; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
|
||||
stdout_tx_str("Type \"help()\" for more information.\r\n");
|
||||
|
||||
vstr_t line;
|
||||
@ -654,7 +656,8 @@ soft_reset:
|
||||
rt_store_attr(m, MP_QSTR_I2C, rt_make_function_n(2, pyb_I2C));
|
||||
rt_store_attr(m, MP_QSTR_gpio, (mp_obj_t)&pyb_gpio_obj);
|
||||
rt_store_attr(m, MP_QSTR_Usart, rt_make_function_n(2, pyb_Usart));
|
||||
rt_store_attr(m, MP_QSTR_ADC, rt_make_function_n(1, pyb_ADC));
|
||||
rt_store_attr(m, qstr_from_str("ADC_all"), (mp_obj_t)&pyb_ADC_all_obj);
|
||||
rt_store_attr(m, MP_QSTR_ADC, (mp_obj_t)&pyb_ADC_obj);
|
||||
rt_store_name(MP_QSTR_pyb, m);
|
||||
|
||||
rt_store_name(MP_QSTR_open, rt_make_function_n(2, pyb_io_open));
|
||||
|
@ -23,11 +23,13 @@ machine_float_t machine_sqrt(machine_float_t x);
|
||||
// board specific definitions
|
||||
|
||||
// choose 1 of these boards
|
||||
//#define PYBOARD
|
||||
#define PYBOARD4
|
||||
#define PYBOARD3
|
||||
//#define PYBOARD4
|
||||
//#define STM32F4DISC
|
||||
|
||||
#if defined (PYBOARD)
|
||||
#if defined (PYBOARD3)
|
||||
#define MICROPY_HW_BOARD_NAME "PYBv3"
|
||||
|
||||
#define MICROPY_HW_HAS_SWITCH (1)
|
||||
#define MICROPY_HW_HAS_SDCARD (1)
|
||||
#define MICROPY_HW_HAS_MMA7660 (1)
|
||||
@ -68,6 +70,8 @@ machine_float_t machine_sqrt(machine_float_t x);
|
||||
#define PYB_LED_OFF(port, pin) (port->BSRRL = pin)
|
||||
|
||||
#elif defined (PYBOARD4)
|
||||
#define MICROPY_HW_BOARD_NAME "PYBv4"
|
||||
|
||||
#define MICROPY_HW_HAS_SWITCH (1)
|
||||
#define MICROPY_HW_HAS_SDCARD (1)
|
||||
#define MICROPY_HW_HAS_MMA7660 (1)
|
||||
@ -108,6 +112,8 @@ machine_float_t machine_sqrt(machine_float_t x);
|
||||
#define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
|
||||
|
||||
#elif defined (STM32F4DISC)
|
||||
#define MICROPY_HW_BOARD_NAME "F4DISC"
|
||||
|
||||
#define MICROPY_HW_HAS_SWITCH (1)
|
||||
#define MICROPY_HW_HAS_SDCARD (0)
|
||||
#define MICROPY_HW_HAS_MMA7660 (0)
|
||||
|
@ -77,7 +77,7 @@ void usart_init(pyb_usart_t usart_id, uint32_t baudrate) {
|
||||
case PYB_USART_3:
|
||||
USARTx = USART3;
|
||||
|
||||
#if defined(PYBOARD4)
|
||||
#if defined(PYBOARD3) || defined(PYBOARD4)
|
||||
GPIO_Port = GPIOB;
|
||||
GPIO_AF_USARTx = GPIO_AF_USART3;
|
||||
GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
|
||||
|
@ -44,7 +44,7 @@ void switch_init(void) {
|
||||
}
|
||||
|
||||
int switch_get(void) {
|
||||
#if defined (PYBOARD) || defined (PYBOARD4)
|
||||
#if defined (PYBOARD3) || defined (PYBOARD4)
|
||||
if (USRSW_PORT->IDR & USRSW_PIN) {
|
||||
// pulled high, so switch is not pressed
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user