master
Ondřej Hruška 9 years ago
parent eadd4e353d
commit 57f9514057
  1. 4
      Makefile
  2. 56
      capture.c
  3. 8
      capture.h
  4. 3
      doc/controls.txt
  5. 1
      doc/output.txt
  6. 53
      init.c
  7. 2
      init.h
  8. 7
      lib/common.c
  9. 4
      lib/common.h
  10. 5
      lib/defs_adc.h
  11. 10
      lib/defs_base.h
  12. 18
      lib/defs_timers.h
  13. 109
      main.c
  14. 8
      proj.pro
  15. 79
      utils/str_utils.c
  16. 10
      utils/str_utils.h

@ -1,6 +1,6 @@
DEFS = -DSTM32L1 DEFS = -DSTM32L1
FP_FLAGS ?= -msoft-float FP_FLAGS ?= -msoft-float -mfloat-abi=soft
ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
LDSCRIPT = stm32l100rc.ld LDSCRIPT = stm32l100rc.ld
@ -21,8 +21,10 @@ OBJS += utils/usart.o
OBJS += utils/timebase.o OBJS += utils/timebase.o
OBJS += utils/debounce.o OBJS += utils/debounce.o
OBJS += utils/nvic.o OBJS += utils/nvic.o
OBJS += utils/str_utils.o
OBJS += init.o OBJS += init.o
OBJS += blink.o OBJS += blink.o
OBJS += capture.o
OBJS += lib/common.o OBJS += lib/common.o
################################################################ ################################################################

@ -0,0 +1,56 @@
#include "capture.h"
#include "utils/timebase.h"
uint16_t adc_measure(uint8_t channel)
{
ADC1_SQR5 = channel; // select n-th channel
ADC1_SQR1 = 0; // sets length to 1 (0000)
ADC1_CR2 |= ADC_CR2_SWSTART; // start conversion
// wait for end of conversion
while (!(ADC1_SR & ADC_SR_EOC));
return ADC1_DR;
}
float measure_angle(void)
{
uint16_t d = adc_measure(18);
return -135 + 270 * (d / 4095.0f);
}
float measure_exposure(void)
{
uint16_t d = adc_measure(8);
float alpha = d / 4095.0f;
return alpha * 100; // %
}
float measure_resistance(void)
{
uint16_t d = adc_measure(9);
float alpha = d / 4095.0f;
float ref_r = 330;
return (ref_r * alpha) / (1 - alpha);
}
float measure_temp(void)
{
uint16_t ts_data = adc_measure(ADC_CH_TEMP);
// temperature calibration constants for L100 are undocumented,
// probably because the sensor is broken.
// Temperature sensor is unstable and unreliable.
uint16_t ts_cal1 = MMIO16(0x1FF800FA);
uint16_t ts_cal2 = MMIO16(0x1FF800FE);
return ((80.0f / (ts_cal2 - ts_cal1)) * (ts_data - ts_cal1) + 30.0f);
}

@ -0,0 +1,8 @@
#pragma once
#include <common.h>
uint16_t adc_measure(uint8_t channel);
float measure_temp(void);
float measure_angle(void);
float measure_resistance(void);
float measure_exposure(void);

@ -0,0 +1,3 @@
b,d - změna střídy PWM, krok 50 (rozsah 0-1000)
m,n - změna hodnoty DAC, krok 117 (rozsah 0-4095)
g - nulovat počítadlo závory

@ -0,0 +1 @@
T -179.6°C | An -6.6° | R 589.2 | L 1.8% | G 0, #0 | DA 4095 | PWM 1000

@ -13,6 +13,8 @@ void init_gpios(void)
// LEDs // LEDs
gpio_set_mode(GPIOC, BIT8 | BIT9, MODER_OUTPUT); gpio_set_mode(GPIOC, BIT8 | BIT9, MODER_OUTPUT);
gpio_set_mode(GPIOC, BIT11, MODER_INPUT);
} }
@ -67,24 +69,71 @@ void init_systick(void)
void init_adc(void) void init_adc(void)
{ {
gpio_set_mode(GPIOB, BIT12, MODER_ANALOG); // B1 ... AN9 Vcc o--[330R]--(B1)--[?R]--| GND
// B0 ... AN8 fototransistor
// B12 .. AN18 "angle" potentiometer
// C5 ... AN15
gpio_set_mode(GPIOB, BIT1 | BIT0 | BIT12, MODER_ANALOG);
//gpio_set_mode(GPIOC, BIT5, MODER_ANALOG);
// enable clock for ADC
RCC_APB2ENR |= RCC_APB2ENR_ADC1EN;
// 12-bit, right aligned
ADC1_CR1 = 0;
ADC1_CR2 = 0;
// enable internal temperature sensor (16) & voltage reference (17)
ADC_CCR |= ADC_CCR_TSVREFE;
// TODO ADC1_SMPR3 = 0b100; // sample time
// turn ADC on
ADC1_CR2 |= ADC_CR2_ADON;
// Wait for ADONS
while (!(ADC1_SR & ADC_SR_ADONS));
} }
void init_dac(void)
{
RCC_APB1ENR |= RCC_APB1ENR_DACEN; // enable DAC
gpio_set_mode(GPIOA, BIT4, MODER_ANALOG); // PA4 - DAC CH1 out
DAC_CR |= DAC_CR_EN1; // enable first channel
}
void init_pwm1(void)
{
// enable clock for the timer
RCC_APB1ENR |= RCC_APB1ENR_TIM3EN;
// using timer 3, channel 1
gpio_set_af(GPIOA, BIT6, AF2);
patch_register(&TIM3_CCMR1, TIM_CCMR1_OC1M, TIM_OCM_PWM1); // set PWM1 mode
TIM3_CCMR1 |= TIM_CCMR1_OC1PE; // preload enable
TIM3_CR1 |= TIM_CR1_ARPE; // auto reload is buffered
TIM3_CCER |= TIM_CCER_CC1E; // enable output compare (PWM output)
patch_register(&TIM3_CR1, TIM_CR1_CMS, TIM_CMS_EDGE); // centering mode
patch_register(&TIM3_CR1, TIM_CR1_DIR, 0); // count upwards only
// frequency set to 16 kHz
TIM3_PSC = 0; // prescaller
TIM3_ARR = 1000; // sets frequency
TIM3_CCR1 = 0; // duty cycle
// generate update event to latch the value registers
TIM3_EGR |= TIM_EGR_UG;
TIM3_CR1 |= TIM_CR1_CEN; // enable timer.
}

@ -6,3 +6,5 @@ void init_gpios(void);
void init_usart(void); void init_usart(void);
void init_systick(void); void init_systick(void);
void init_adc(void); void init_adc(void);
void init_dac(void);
void init_pwm1(void);

@ -9,3 +9,10 @@ inline uint32_t __RBIT(uint32_t value)
return (result); return (result);
} }
__attribute__((always_inline))
inline void patch_register(io32_t reg, uint32_t mask, uint32_t replacement)
{
*reg &= ~mask;
*reg |= replacement << __CTZ(mask);
}

@ -30,6 +30,7 @@ typedef volatile uint64_t* io64_t;
#define wait_for_interrupt() __asm__("WFI") #define wait_for_interrupt() __asm__("WFI")
#define __CLZ(div) __builtin_clz(div) #define __CLZ(div) __builtin_clz(div)
#define __CTZ(div) __builtin_ctz(div)
#define count_leading_zeros(div) __CLZ(div) #define count_leading_zeros(div) __CLZ(div)
#define __REV(x) __builtin_bswap32(x) #define __REV(x) __builtin_bswap32(x)
@ -86,6 +87,9 @@ uint32_t __RBIT(uint32_t value); // defined in c file as inline asm
#define BIT31 BIT(31) #define BIT31 BIT(31)
void patch_register(io32_t reg, uint32_t mask, uint32_t replacement);
#include "defs_base.h" #include "defs_base.h"
#include "defs_gpio.h" #include "defs_gpio.h"

@ -20,6 +20,10 @@
// ADC1 // ADC1
// internal channels
#define ADC_CH_TEMP 16
#define ADC_CH_VREF 17
#define ADC1_SR MMIO32(ADC1_BASE + 0x00) // ADC status register, #define ADC1_SR MMIO32(ADC1_BASE + 0x00) // ADC status register,
#define ADC1_CR1 MMIO32(ADC1_BASE + 0x04) // ADC control register 1, #define ADC1_CR1 MMIO32(ADC1_BASE + 0x04) // ADC control register 1,
#define ADC1_CR2 MMIO32(ADC1_BASE + 0x08) // ADC control register 2, #define ADC1_CR2 MMIO32(ADC1_BASE + 0x08) // ADC control register 2,
@ -46,7 +50,6 @@
#define ADC1_SMPR0 MMIO32(ADC1_BASE + 0x5C) // ADC sample time register 0, #define ADC1_SMPR0 MMIO32(ADC1_BASE + 0x5C) // ADC sample time register 0,
//**************************************************************************** //****************************************************************************
//* //*
//* BIT MASKS AND DEFINITIONS //* BIT MASKS AND DEFINITIONS

@ -114,10 +114,12 @@
#define DESIG_UNIQUE_ID2 MMIO32(DESIG_UNIQUE_ID_BASE + 0x14) #define DESIG_UNIQUE_ID2 MMIO32(DESIG_UNIQUE_ID_BASE + 0x14)
/* ST provided factory calibration values @ 3.0V */ /* ST provided factory calibration values @ 3.0V */
#define ST_VREFINT_CAL MMIO16(0x1FF80078) //#define ST_VREFINT_CAL MMIO16(0x1FF80078)
#define ST_TSENSE_CAL1_30C MMIO16(0x1FF8007A) //#define ST_TSENSE_CAL1_30C MMIO16(0x1FF8007A)
#define ST_TSENSE_CAL2_110C MMIO16(0x1FF8007E) //#define ST_TSENSE_CAL2_110C MMIO16(0x1FF8007E)
#define ST_VREFINT_CAL MMIO16(0x1FF800F8)
#define ST_TSENSE_CAL1_30C MMIO16(0x1FF800FA)
#define ST_TSENSE_CAL2_110C MMIO16(0x1FF800FE)
// ---- ARMv7M+ only ---- // ---- ARMv7M+ only ----

@ -253,6 +253,13 @@
#define TIM_CR1_CMS_0 0x0020 // Bit 0 #define TIM_CR1_CMS_0 0x0020 // Bit 0
#define TIM_CR1_CMS_1 0x0040 // Bit 1 #define TIM_CR1_CMS_1 0x0040 // Bit 1
enum TIM_CenterAlignMode {
TIM_CMS_EDGE = 0,
TIM_CMS_CENTER_FLAGS_UP = 1,
TIM_CMS_CENTER_FLAGS_DOWN = 2,
TIM_CMS_CENTER_FLAGS_BOTH = 3,
};
#define TIM_CR1_ARPE 0x0080 // Auto-reload preload enable #define TIM_CR1_ARPE 0x0080 // Auto-reload preload enable
#define TIM_CR1_CKD 0x0300 // CKD[1:0] bits (clock division) #define TIM_CR1_CKD 0x0300 // CKD[1:0] bits (clock division)
@ -344,6 +351,17 @@
#define TIM_CCMR1_OC1M_1 0x0020 // Bit 1 #define TIM_CCMR1_OC1M_1 0x0020 // Bit 1
#define TIM_CCMR1_OC1M_2 0x0040 // Bit 2 #define TIM_CCMR1_OC1M_2 0x0040 // Bit 2
enum TIM_OutputCompareMode {
TIM_OCM_FROZEN = 0,
TIM_OCM_HIGH_ON_MATCH = 1,
TIM_OCM_LOW_ON_MATCH = 2,
TIM_OCM_TOGGLE_ON_MATCH = 3,
TIM_OCM_FORCE_LOW = 4,
TIM_OCM_FORCE_HIGH = 5,
TIM_OCM_PWM1 = 6,
TIM_OCM_PWM2 = 7,
};
#define TIM_CCMR1_OC1CE 0x0080 // Output Compare 1Clear Enable #define TIM_CCMR1_OC1CE 0x0080 // Output Compare 1Clear Enable
#define TIM_CCMR1_CC2S 0x0300 // CC2S[1:0] bits (Capture/Compare 2 Selection) #define TIM_CCMR1_CC2S 0x0300 // CC2S[1:0] bits (Capture/Compare 2 Selection)

109
main.c

@ -1,16 +1,19 @@
#include <common.h> #include <common.h>
#include <stdio.h>
#include "utils/usart.h" #include "utils/usart.h"
#include "utils/timebase.h" #include "utils/timebase.h"
#include "utils/debounce.h" #include "utils/debounce.h"
#include "utils/str_utils.h"
#include "init.h" #include "init.h"
#include "blink.h" #include "blink.h"
#include "capture.h"
void say_hello(void) // Gate state
{ static bool gate_closed = false;
usart_tx_string(USART3, "HELLO\r\n"); static uint32_t gate_cnt = 0;
}
/** IRQ */ /** IRQ */
@ -24,8 +27,34 @@ void USART2_IRQHandler(void)
if (USART2_SR & USART_SR_RXNE) { if (USART2_SR & USART_SR_RXNE) {
blue_blink(); blue_blink();
// handle incoming char.
char c = usart_rx_char(USART2); char c = usart_rx_char(USART2);
usart_tx_char(USART2, c);
switch (c) {
case 'g': // nulovat pocitadlo preruseni
gate_cnt = 0;
break;
case 'm': // zvysit DAC hodnotu
if (DAC_DHR12R1 < 4095) DAC_DHR12R1 += 117;
break;
case 'n': // snizit DAC hodnotu
if (DAC_DHR12R1 > 0) DAC_DHR12R1 -= 117;
break;
case 'b': // zvysit PWM stridu
if (TIM3_CCR1 < 1000) TIM3_CCR1 += 50;
break;
case 'd': // snizit PWM stridu
if (TIM3_CCR1 > 0) TIM3_CCR1 -= 50;
break;
default:
break;
}
USART2_SR ^= USART_SR_RXNE; USART2_SR ^= USART_SR_RXNE;
} }
@ -33,7 +62,21 @@ void USART2_IRQHandler(void)
/** Called by startup script, before main() */ // Gate close handler
void gate_close(void)
{
gate_closed = 1;
gate_cnt++;
}
// Gate open handler
void gate_open(void)
{
gate_closed = 0;
}
/** Init peripherals; Called by startup script, before main() */
void SystemInit(void) void SystemInit(void)
{ {
init_clock(); init_clock();
@ -41,12 +84,62 @@ void SystemInit(void)
init_gpios(); init_gpios();
init_usart(); init_usart();
init_adc(); init_adc();
init_dac();
init_pwm1();
register_periodic_task(green_toggle, 1000); // indicate running state
register_periodic_task(green_toggle, 1000); register_debounced_pin(GPIOB, 11, gate_close, gate_open); // gate handler
} }
int main(void) int main(void)
{ {
while (1); char buf[200];
usart_tx_string(USART2, "DAQ system started.\n");
while (1) {
delay_ms(200);
float cels = measure_temp();
float angle = measure_angle();
float resis = measure_resistance();
float expos = measure_exposure();
buf_reset(buf);
buf_append_str(buf, "T ");
buf_append_flt(buf, cels, 1);
buf_append_str(buf, "°C | ");
buf_append_str(buf, "An ");
buf_append_flt(buf, angle, 1);
buf_append_str(buf, "° | ");
buf_append_str(buf, "R ");
buf_append_flt(buf, resis, 1);
buf_append_str(buf, " | ");
buf_append_str(buf, "L ");
buf_append_flt(buf, expos, 1);
buf_append_str(buf, "% | ");
buf_append_str(buf, "G ");
buf_append_str(buf, gate_closed ? "1" : "0");
buf_append_str(buf, ", #");
buf_append_int(buf, gate_cnt);
buf_append_str(buf, " | ");
buf_append_str(buf, "DA ");
buf_append_int(buf, DAC_DHR12R1);
buf_append_str(buf, " | ");
buf_append_str(buf, "PWM ");
buf_append_int(buf, TIM3_CCR1);
buf_append_str(buf, "\n");
usart_tx_string(USART2, buf);
}
} }

@ -31,7 +31,9 @@ SOURCES += \
utils/debounce.c \ utils/debounce.c \
blink.c \ blink.c \
lib/common.c \ lib/common.c \
utils/nvic.c utils/nvic.c \
capture.c \
utils/str_utils.c
HEADERS += \ HEADERS += \
lib/common.h \ lib/common.h \
@ -58,5 +60,7 @@ HEADERS += \
lib/defs_spi.h \ lib/defs_spi.h \
lib/defs_timers.h \ lib/defs_timers.h \
lib/defs_nvic.h \ lib/defs_nvic.h \
utils/nvic.h utils/nvic.h \
capture.h \
utils/str_utils.h

@ -0,0 +1,79 @@
#include "str_utils.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
void buf_reset(char *buf)
{
buf[0] = 0;
}
void buf_append_int(char *buf, int d)
{
buf += strlen(buf);
sprintf(buf, "%d", d);
}
void buf_append_flt(char *buf, float f, uint8_t places)
{
buf += strlen(buf);
if (isnan(f)) {
sprintf(buf, "NAN");
return;
}
if (isinf(f)) {
sprintf(buf, "INF");
return;
}
if (isinf(f) && f < 0) {
sprintf(buf, "-INF");
return;
}
bool minus = 0;
if (f < 0) {
minus = 1;
f = -f;
}
int ones = 0, dec = 0;
ones = (int)f;
f -= ones;
if (minus) {
buf[0] = '-';
buf++;
}
switch (places) {
case 0:
sprintf(buf, "%d", ones);
return;
case 1:
dec = (f * 10);
sprintf(buf, "%d.%01d", ones, dec);
return;
case 2:
dec = (f * 100);
sprintf(buf, "%d.%02d", ones, dec);
return;
default:
case 3:
dec = (f * 1000);
sprintf(buf, "%d.%03d", ones, dec);
return;
}
}
void buf_append_str(char *buf, const char *app)
{
sprintf(buf + strlen(buf), "%s", app);
}

@ -0,0 +1,10 @@
#pragma once
#include <common.h>
void buf_reset(char *buf);
void buf_append_flt(char *buf, float f, uint8_t places);
void buf_append_str(char *buf, const char *app);
void buf_append_int(char *buf, int d);
Loading…
Cancel
Save