restructuring

This commit is contained in:
2022-03-10 11:04:14 +03:00
parent 29560b7c0c
commit 733dbd75d2
1758 changed files with 14 additions and 26855 deletions

View File

@@ -0,0 +1,157 @@
BINARY = steppers
BOOTPORT ?= /dev/ttyUSB0
BOOTSPEED ?= 57600
# MCU FAMILY
FAMILY ?= F0
# MCU code
MCU ?= F072xB
DEFS += -DEBUG
# change this linking script depending on particular MCU model,
# for example, if you have STM32F103VBT6, you should write:
LDSCRIPT ?= stm32f072B.ld
# autoincremental version & build date
VERSION_FILE = version.inc
NEXTVER := $(shell expr $$(awk '/#define BUILD_NUMBER/' $(VERSION_FILE) | tr -cd "[0-9]") + 1)
BUILDDATE := $(shell date +%Y-%m-%d)
INDEPENDENT_HEADERS=
FP_FLAGS ?= -msoft-float
ASM_FLAGS = -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
###############################################################################
# Executables
OPREFIX ?= /opt/bin/arm-none-eabi
#PREFIX ?= /usr/x86_64-pc-linux-gnu/arm-none-eabi/gcc-bin/7.3.0/arm-none-eabi
PREFIX ?= $(OPREFIX)
RM := rm -f
RMDIR := rmdir
CC := $(PREFIX)-gcc
LD := $(PREFIX)-gcc
AR := $(PREFIX)-ar
AS := $(PREFIX)-as
OBJCOPY := $(OPREFIX)-objcopy
OBJDUMP := $(OPREFIX)-objdump
GDB := $(OPREFIX)-gdb
STFLASH := $(shell which st-flash)
STBOOT := $(shell which stm32flash)
DFUUTIL := $(shell which dfu-util)
###############################################################################
# Source files
OBJDIR = mk
LDSCRIPT ?= $(BINARY).ld
SRC := $(wildcard *.c)
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
STARTUP = $(OBJDIR)/startup.o
OBJS += $(STARTUP)
DEPS := $(OBJS:.o=.d)
INC_DIR ?= ../inc
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
LIB_DIR := $(INC_DIR)/ld
###############################################################################
# C flags
CFLAGS += -O2 -g -MD -D__thumb2__=1
CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
CFLAGS += -Wredundant-decls $(INCLUDE)
# -Wmissing-prototypes -Wstrict-prototypes
CFLAGS += -fno-common -ffunction-sections -fdata-sections
###############################################################################
# Linker flags
LDFLAGS += --static -nostartfiles
#--specs=nano.specs
LDFLAGS += -L$(LIB_DIR)
LDFLAGS += -T$(LDSCRIPT)
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map
LDFLAGS += -Wl,--gc-sections
###############################################################################
# Used libraries
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU)
#.SUFFIXES: .elf .bin .hex .srec .list .map .images
#.SECONDEXPANSION:
#.SECONDARY:
ELF := $(OBJDIR)/$(BINARY).elf
LIST := $(OBJDIR)/$(BINARY).list
BIN := $(BINARY).bin
HEX := $(BINARY).hex
all: bin list
elf: $(ELF)
bin: $(BIN)
hex: $(HEX)
list: $(LIST)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif
$(OBJDIR):
mkdir $(OBJDIR)
$(STARTUP): $(INC_DIR)/startup/vector.c
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
$(VERSION_FILE): *.[ch]
@echo " Generate version: $(NEXTVER) for date $(BUILDDATE)"
@sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE)
@sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE)
$(OBJDIR)/strfunct.o: strfunct.c $(VERSION_FILE)
$(OBJDIR)/%.o: %.c
@make $(VERSION_FILE)
@echo " CC $<"
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
%.s: %.c
@echo " ASM $<"
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -S -o $(OBJDIR)/$@ -c $<
$(BIN): $(ELF)
@echo " OBJCOPY $(BIN)"
$(OBJCOPY) -Obinary $(ELF) $(BIN)
$(HEX): $(ELF)
@echo " OBJCOPY $(HEX)"
$(OBJCOPY) -Oihex $(ELF) $(HEX)
$(LIST): $(ELF)
@echo " OBJDUMP $(LIST)"
$(OBJDUMP) -S $(ELF) > $(LIST)
$(ELF): $(OBJDIR) $(OBJS)
@echo " LD $(ELF)"
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
clean:
@echo " CLEAN"
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map $(OBJDIR)/*.d $(OBJDIR)/*.s
@rmdir $(OBJDIR) 2>/dev/null || true
dfuboot: $(BIN)
@echo " LOAD $(BIN) THROUGH DFU"
$(DFUUTIL) -a0 -R -D $(BIN) -s 0x08000000
flash: $(BIN)
@echo " FLASH $(BIN)"
$(STFLASH) write $(BIN) 0x8000000
boot: $(BIN)
@echo " LOAD $(BIN) through bootloader"
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
.PHONY: clean dfuboot flash boot

View File

@@ -0,0 +1,257 @@
Loopback control of three stepper motors
========================================
# Pinout
- **PA0** Enc2a (motor2 encoder)
- **PA1** Enc2b
- **PA2** CLK1 (motor1 clock)
- **PA3** ADC1 (ADC1 in, 0-3.3V)
- **PA4** CLK2 (motor2 clock)
- **PA5** ADC2 (ADC2 in, 0-3.3V)
- **PA6** CLK3 (motor3 clock)
- **PA7** PWM (opendrain PWM, up to 12V)
- **PA8** Enc1a (motor1 encoder)
- **PA9** Enc1b
- **PA10** BTN1 (user button 1)
- **PA11** USBDM
- **PA12** USBDP
- **PA13** BTN2 (user button 2)
- **PA14** BTN3 (user button 3)
- **PA15** BTN4 (user button 4)
- **PB0** ~EN1 (motor1 not enable)
- **PB1** DIR1 (motor1 direction)
- **PB2** ~EN2 (motor2 not enable)
- **PB3** Buzzer (external buzzer or other non-inductive opendrain load up to 12V)
- **PB4** Enc3a (motor3 encoder)
- **PB5** Enc3b
- **PB6** I2C SCL (external I2C bus, have internal pullups of 4.7kOhm to +3.3V)
- **PB7** I2C SDA
- **PB8** CAN Rx (external CAN bus, with local galvanic isolation
- **PB9** CAN Tx
- **PB10** DIR2 (motor2 direction)
- **PB11** ~EN3 (motor3 not enable)
- **PB12** DIR3 (motor3 direction)
- **PB13** Ext0 (3 external outputs: 5V, up to 20mA)
- **PB14** Ext1
- **PB15** Ext2
- **PC13** ESW1 (motor1 zero limit switch)
- **PC14** ESW2 (motor2 zero limit switch)
- **PC15** ESW3 (motor3 zero limit switch)
- **PF0** Relay (10A 250VAC, 10A 30VDC)
# Connectors
## ADC inputs connector, J1
1. ADC1 (up to 3.3V)
2. ADC2 (up to 3.3V)
3. GND
## Encoders connectors, J2-J4
1. GND
2. Encoder B phase
3. Encoder A phase
4. +5V (through resistor 22Ohm)
## I2C connector, J5
1. +3.3V
2. SCL
3. SDA
4. GND
## PWM connector, J6
1. +3.3V
2. +5V
3. PWM GND (opendrain)
## CAN bus connector, J7
1. CANL (low signal)
2. CANGND (common - not need for short lines)
3. CANH (high signal)
## External buttons connector (WARNING! NO ESD PROTECTION!), J8
1. Button 1
2. Button 2
3. Button 3
4. Button 4
5. GND
## External Hall sensors connector (zero limit switches), J9
1. +3.3V (through resistor 47Ohm)
2. Motor1 limit switch
3. Motor2 limit switch
4. Motor3 limit switch
5. GND
## Relay connector, J10
1. Normally opened
2. Common
3. Normally closed
## 24V input power connector, J12
1. GND
2. +24V DC
## 24V motors power connector, J13
1. GND
2. +24V DC to motors' coils (reverse protected)
## Stepper motors control signals connectors, J14-J16
1. CLK (step signal)
2. DIR (rotation direction)
3. ~EN (not enable)
4. GND
## External 5V logic outputs connector (up to 20mA per each channel), J17
1. Ext0
2. Ext1
3. Ext2
4. GND
## External buzzer (or other load) connector (opendrain, up to 12V), J18
1. power (depending on JP1 jumper): 3.3V or 5.0V
2. GND (opendrain)
# Control points
- **TP1** 5V
- **TP2** 3.3V
- **TP3** NRST
- **TP4** GND
# Firmware download
Activate "Jump to DFU" menu entry through USB protocol. Flash MCU by `dfu-util`.
# USB protocol
https://github.com/eddyem/stm32samples/tree/master/F0-nolib/3steppersLB build#138 @ 2021-12-02
Common commands format is cmd[ N[ = val]]
where N is command argument (0..127), val is its value
Different commands:
adc - get ADC values
button - get buttons state
buzzer - change buzzer state (1/0)
esw - get end switches state
ext - external outputs
mcut - get MCU T
mcuvdd - get MCU Vdd
ping - echo given command back
pwm - pwm value
relay - change relay state (1/0)
reset - reset MCU
time - get time from start
Confuguration:
accel - set/get accel/decel (steps/s^2)
encrev - set/get max encoder's pulses per revolution
encstepmax - maximal encoder ticks per step
encstepmin - minimal encoder ticks per step
eswreact - end-switches reaction
maxspeed - set/get max speed (steps per sec)
maxsteps - set/get max steps (from zero)
microsteps - set/get microsteps settings
minspeed - set/get min speed (steps per sec)
motflags - set/get motorN flags
saveconf - save current configuration
speedlimit - get limiting speed for current microsteps
Motors' commands:
abspos - set/get position (in steps)
emerg - emergency stop all motors
emstop - emergency stop motor (right now)
encpos - set/get encoder's position
gotoz - find zero position & refresh counters
motreinit - re-init motors after configuration changed
relpos - set relative steps, get remaining
relslow - set relative steps @ lowest speed
state - get motor state
stop - smooth motor stopping
USB-only commands:
canid - get/set CAN ID
canspeed - CAN bus speed
delignlist - delete ignore list
dfu - activate DFU mode
dumperr - dump error codes
dumpcmd - dump command codes
dumpconf - dump current configuration
filter - add/modify filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]
getctr - get TIM1/2/3 counters
ignbuf - print ignore buffer
ignore - add ID to ignore list (max 10 IDs)
listfilters - list all active filters
pause - pause IN packets displaying
resume - resume IN packets displaying
send - send data over CAN: send ID byte0 .. byteN
wd - check watchdog
# CAN bus protocol
bytes descr
0 Lcmd - command code
1 Hcmd
2 par - command paremeter (steper, ADC channel number etc)
3 err - error code (only in answer)
4 Ldata - optional data in int32_t
5
6
7 Hdata
dumperr
Find known command: dumperr
Error codes:
0 - all OK
1 - wrong parameter's value
2 - wrong setter of parameter
3 - bad message length
4 - unknown command
5 - temporary can't run given command
dumpcmd
Find known command: dumpcmd
Commands list:
0 - Different commands:
1 - change relay state (1/0)
2 - change buzzer state (1/0)
3 - get ADC values
4 - get buttons state
5 - get end switches state
6 - get MCU T
7 - get MCU Vdd
8 - reset MCU
9 - get time from start
10 - pwm value
11 - external outputs
12 - save current configuration
13 - minimal encoder ticks per step
14 - maximal encoder ticks per step
15 - set/get microsteps settings
16 - set/get accel/decel (steps/s^2)
17 - set/get max speed (steps per sec)
18 - set/get min speed (steps per sec)
19 - get limiting speed for current microsteps
20 - set/get max steps (from zero)
21 - set/get max encoder's pulses per revolution
22 - set/get motorN flags
23 - end-switches reaction
24 - re-init motors after configuration changed
25 - set/get position (in steps)
26 - set relative steps, get remaining
27 - set relative steps @ lowest speed
28 - emergency stop motor (right now)
29 - smooth motor stopping
30 - emergency stop all motors
31 - find zero position & refresh counters
32 - get motor state
33 - set/get encoder's position

View File

@@ -0,0 +1,104 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "adc.h"
/**
* @brief ADC_array - array for ADC channels with median filtering:
* 0 & 1 - external channels
* 2 - internal Tsens
* 3 - Vref
*/
static uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9];
void adc_setup(){
uint16_t ctr = 0; // 0xfff0 - more than 1.3ms
ADC1->CR &= ~ADC_CR_ADEN;
DMA1_Channel1->CCR &= ~DMA_CCR_EN;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // Enable the peripheral clock of the ADC
RCC->CR2 |= RCC_CR2_HSI14ON; // Start HSI14 RC oscillator
while ((RCC->CR2 & RCC_CR2_HSI14RDY) == 0 && ++ctr < 0xfff0){}; // Wait HSI14 is ready
// calibration
if(ADC1->CR & ADC_CR_ADEN){ // Ensure that ADEN = 0
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN); // Clear ADEN
}
ADC1->CR |= ADC_CR_ADCAL; // Launch the calibration by setting ADCAL
ctr = 0; // ADC calibration time is 5.9us
while(ADC1->CR & ADC_CR_ADCAL && ++ctr < 0xfff0); // Wait until ADCAL=0
// enable ADC
ctr = 0;
do{
ADC1->CR |= ADC_CR_ADEN;
}while((ADC1->ISR & ADC_ISR_ADRDY) == 0 && ++ctr < 0xfff0);
// configure ADC
ADC1->CFGR1 |= ADC_CFGR1_CONT; // Select the continuous mode
// channels 3,5,16 and 17
ADC1->CHSELR = ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17;
ADC1->SMPR |= ADC_SMPR_SMP; // Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us
ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; // Wake-up the VREFINT and Temperature sensor
// configure DMA for ADC
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Enable the peripheral clock on DMA
ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG; // Enable DMA transfer on ADC and circular mode
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR)); // Configure the peripheral data register address
DMA1_Channel1->CMAR = (uint32_t)(ADC_array); // Configure the memory address
DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS * 9; // Configure the number of DMA tranfer to be performs on DMA channel 1
DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC; // Configure increment, size, interrupts and circular mode
DMA1_Channel1->CCR |= DMA_CCR_EN; // Enable DMA Channel 1
ADC1->CR |= ADC_CR_ADSTART; // start the ADC conversions
}
/**
* @brief getADCval - calculate median value for `nch` channel
* @param nch - number of channel
* @return
*/
uint16_t getADCval(int nch){
int i, addr = nch;
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
#define PIX_SWAP(a,b) {register uint16_t temp=(a);(a)=(b);(b)=temp; }
uint16_t p[9];
for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed
p[i] = ADC_array[addr];
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ;
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ;
PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ;
PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ;
PIX_SORT(p[4], p[2]) ;
return p[4];
#undef PIX_SORT
#undef PIX_SWAP
}
// return MCU temperature (degrees of celsius * 10)
int32_t getMCUtemp(){
int32_t ADval = getADCval(2);
int32_t temperature = (int32_t) *TEMP30_CAL_ADDR - ADval;
temperature *= (int32_t)(1100 - 300);
temperature /= (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR);
temperature += 300;
return(temperature);
}
// return Vdd * 100 (V)
uint32_t getVdd(){
uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330; // 3.3V
vdd /= getADCval(3);
return vdd;
}

View File

@@ -0,0 +1,32 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ADC_H
#define ADC_H
#include "stm32f0.h"
// 2 external & 2 internal
#define NUMBER_OF_ADC_CHANNELS (4)
void adc_setup();
int32_t getMCUtemp();
uint32_t getVdd();
uint16_t getADCval(int nch);
int16_t getNTC(int nch);
#endif // ADC_H

View File

@@ -0,0 +1,90 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "buttons.h"
#include "hardware.h"
typedef struct{
keyevent event; // current key event
int16_t counter; // press/release counter
uint32_t lastTms; // time of last event change
} keybase;
static keybase allkeys[BTNSNO] = {0}; // array for buttons' states
uint32_t lastUnsleep = 0; // last keys activity time
void process_keys(){
static uint32_t lastT = 0;
if(Tms == lastT) return;
uint16_t d = (uint16_t)(Tms - lastT);
lastT = Tms;
for(int i = 0; i < BTNSNO; ++i){
keybase *k = &allkeys[i];
keyevent e = k->event;
if(BTN_state(i)){ // key is in pressed state
switch(e){
case EVT_NONE: // just pressed
case EVT_RELEASE:
if((k->counter += d) > PRESSTHRESHOLD){
k->event = EVT_PRESS;
}
break;
case EVT_PRESS: // hold
if((k->counter += d)> HOLDTHRESHOLD){
k->event = EVT_HOLD;
}
break;
default:
break;
}
}else{ // released
if(e == EVT_PRESS || e == EVT_HOLD){ // released
if(k->counter > PRESSTHRESHOLD) k->counter = PRESSTHRESHOLD;
else if((k->counter -= d) < 0){
k->event = EVT_RELEASE; // button released
}
}
}
if(e != k->event){
k->lastTms = Tms;
lastUnsleep = Tms;
}
}
}
/**
* @brief keystate - curent key state
* @param k - key number
* @param T - last event changing time
* @return key event
*/
keyevent keystate(uint8_t k, uint32_t *T){
if(k >= BTNSNO) return EVT_NONE;
keyevent evt = allkeys[k].event;
// change state `release` to `none` after 1st check
if(evt == EVT_RELEASE) allkeys[k].event = EVT_NONE;
if(T) *T = allkeys[k].lastTms;
return evt;
}
// getter of keyevent for allkeys[]
keyevent keyevt(uint8_t k){
if(k >= BTNSNO) return EVT_NONE;
return allkeys[k].event;
}

View File

@@ -0,0 +1,43 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef BUTTONS_H__
#include <stm32f0.h>
// threshold in ms for press/hold
#define PRESSTHRESHOLD (9)
#define HOLDTHRESHOLD (199)
// events
typedef enum{
EVT_NONE, // no events with given key
EVT_PRESS, // pressed (hold more than PRESSTHRESHOLD ms)
EVT_HOLD, // hold more than HOLDTHRESHOLD ms
EVT_RELEASE // released after press or hold state
} keyevent;
extern uint32_t lastUnsleep; // last keys activity time
void process_keys();
keyevent keystate(uint8_t k, uint32_t *T);
keyevent keyevt(uint8_t k);
#define BUTTONS_H__
#endif // BUTTONS_H__

View File

@@ -0,0 +1,381 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "can.h"
#include "commonproto.h"
#include "flash.h"
#include "hardware.h"
#include "strfunct.h"
#include <string.h> // memcpy
// circular buffer for received messages
static CAN_message messages[CAN_INMESSAGE_SIZE];
static uint8_t first_free_idx = 0; // index of first empty cell
static int8_t first_nonfree_idx = -1; // index of first data cell
static uint16_t oldspeed = DEFAULT_CAN_SPEED; // speed of last init
#ifdef EBUG
static uint32_t last_err_code = 0;
#endif
static CAN_status can_status = CAN_STOP;
static void can_process_fifo(uint8_t fifo_num);
static void parseCANcommand(CAN_message *msg);
CAN_status CAN_get_status(){
CAN_status st = can_status;
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY;
return st;
}
// push next message into buffer; return 1 if buffer overfull
static int CAN_messagebuf_push(CAN_message *msg){
//DBG("Try to push\n");
if(first_free_idx == first_nonfree_idx) return 1; // no free space
if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer
memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message));
// need to roll?
if(first_free_idx == CAN_INMESSAGE_SIZE) first_free_idx = 0;
return 0;
}
// pop message from buffer
CAN_message *CAN_messagebuf_pop(){
if(first_nonfree_idx < 0) return NULL;
#ifdef EBUG
//DBG("read from idx "); printu(first_nonfree_idx); NL();
#endif
CAN_message *msg = &messages[first_nonfree_idx++];
if(first_nonfree_idx == CAN_INMESSAGE_SIZE) first_nonfree_idx = 0;
if(first_nonfree_idx == first_free_idx){ // buffer is empty - refresh it
first_nonfree_idx = -1;
first_free_idx = 0;
}
return msg;
}
void CAN_reinit(uint16_t speed){
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
CAN_setup(speed);
}
/*
Can filtering: FSCx=0 (CAN->FS1R) -> 16-bit identifiers
MASK: FBMx=0 (CAN->FM1R), two filters (n in FR1 and n+1 in FR2)
ID: CAN->sFilterRegister[x].FRn[0..15]
MASK: CAN->sFilterRegister[x].FRn[16..31]
FR bits: STID[10:0] RTR IDE EXID[17:15]
LIST: FBMx=1, four filters (n&n+1 in FR1, n+2&n+3 in FR2)
IDn: CAN->sFilterRegister[x].FRn[0..15]
IDn+1: CAN->sFilterRegister[x].FRn[16..31]
*/
/*
Can timing: main freq - APB (PLL=48MHz)
segment = 1sync + TBS1 + TBS2, sample point is between TBS1 and TBS2,
so if TBS1=4 and TBS2=3, sum=8, bit sampling freq is 48/8 = 6MHz
-> to get 100kbps we need prescaler=60
250kbps - 24
500kbps - 12
1MBps - 6
*/
// speed - in kbps
void CAN_setup(uint16_t speed){
if(speed == 0) speed = oldspeed;
else if(speed < 50) speed = 50;
else if(speed > 3000) speed = 3000;
oldspeed = speed;
uint32_t tmout = 16000000;
// Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx
/* (1) Select AF mode (10) on PB8 and PB9 */
/* (2) AF4 for CAN signals */
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER8 | GPIO_MODER_MODER9))
| (GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF); /* (1) */
GPIOB->AFR[1] = (GPIOB->AFR[1] &~ (GPIO_AFRH_AFRH0 | GPIO_AFRH_AFRH1))\
| (4 << (0 * 4)) | (4 << (1 * 4)); /* (2) */
/* Enable the peripheral clock CAN */
RCC->APB1ENR |= RCC_APB1ENR_CANEN;
// Configure CAN
CAN->MCR |= CAN_MCR_INRQ; // Enter CAN init mode to write the configuration
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK){
if(--tmout == 0) break;
}
CAN->MCR &=~ CAN_MCR_SLEEP;
CAN->MCR |= CAN_MCR_ABOM; // allow automatically bus-off
CAN->BTR = 2 << 20 | 3 << 16 | (6000/speed - 1); // speed
CAN->MCR &=~ CAN_MCR_INRQ;
tmout = 16000000;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK){ // Wait the init mode leaving
if(--tmout == 0) break;
}
// accept self ID at filter 0, ALL other at filters 1 and 2
CAN->FMR = CAN_FMR_FINIT;
CAN->FA1R = CAN_FA1R_FACT0 | CAN_FA1R_FACT1 | CAN_FA1R_FACT2;
CAN->FM1R = CAN_FM1R_FBM0; // identifier mode for bank#0, mask mode for #1 and #2
// set to 1 all needed bits of CAN->FFA1R to switch given filters to FIFO1
CAN->sFilterRegister[0].FR1 = the_conf.CANID << 5; // self ID
CAN->sFilterRegister[1].FR1 = (1<<21)|(1<<5); // all odd IDs
CAN->sFilterRegister[2].FR1 = (1<<21); // all even IDs
CAN->FFA1R = 2; // filter 1 for FIFO1, filters 0&2 - for FIFO0
CAN->FMR &=~ CAN_FMR_FINIT; // end of filters init
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1;
/* Configure IT */
NVIC_SetPriority(CEC_CAN_IRQn, 0);
NVIC_EnableIRQ(CEC_CAN_IRQn);
can_status = CAN_READY;
}
void can_proc(){
#ifdef EBUG
if(last_err_code){
DBG("Error, ESR=");
printu(last_err_code);
NL();
last_err_code = 0;
}
#endif
// check for messages in FIFO0 & FIFO1
if(CAN->RF0R & CAN_RF0R_FMP0){
can_process_fifo(0);
}
if(CAN->RF1R & CAN_RF1R_FMP1){
can_process_fifo(1);
}
if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS
SEND("\nToo much errors, restarting CAN!\n");
SEND("Receive error counter: ");
printu((CAN->ESR & CAN_ESR_REC)>>24);
SEND("\nTransmit error counter: ");
printu((CAN->ESR & CAN_ESR_TEC)>>16);
SEND("\nLast error code: ");
int lec = (CAN->ESR & CAN_ESR_LEC) >> 4;
const char *errmsg = "No";
switch(lec){
case 1: errmsg = "Stuff"; break;
case 2: errmsg = "Form"; break;
case 3: errmsg = "Ack"; break;
case 4: errmsg = "Bit recessive"; break;
case 5: errmsg = "Bit dominant"; break;
case 6: errmsg = "CRC"; break;
case 7: errmsg = "(set by software)"; break;
}
SEND(errmsg); SEND(" error\n");
if(CAN->ESR & CAN_ESR_BOFF) SEND("Bus off");
if(CAN->ESR & CAN_ESR_EPVF) SEND("Passive error limit");
if(CAN->ESR & CAN_ESR_EWGF) SEND("Error counter limit");
NL();
// request abort for all mailboxes
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
// reset CAN bus
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
CAN_setup(0);
}
}
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){
uint8_t mailbox = 0;
// check first free mailbox
if(CAN->TSR & (CAN_TSR_TME)){
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
}else{ // no free mailboxes
//SEND("No free mailboxes"); NL();
return CAN_BUSY;
}
#ifdef EBUG
DBG("Send data"); SEND("Len="); printu(len);
SEND(", tagid="); printuhex(target_id);
SEND(", data=");
for(int i = 0; i < len; ++i){
SEND(" "); printuhex(msg[i]);
}
NL();
#endif
CAN_TxMailBox_TypeDef *box = &CAN->sTxMailBox[mailbox];
uint32_t lb = 0, hb = 0;
switch(len){
case 8:
hb |= (uint32_t)msg[7] << 24;
__attribute__((fallthrough));
case 7:
hb |= (uint32_t)msg[6] << 16;
__attribute__((fallthrough));
case 6:
hb |= (uint32_t)msg[5] << 8;
__attribute__((fallthrough));
case 5:
hb |= (uint32_t)msg[4];
__attribute__((fallthrough));
case 4:
lb |= (uint32_t)msg[3] << 24;
__attribute__((fallthrough));
case 3:
lb |= (uint32_t)msg[2] << 16;
__attribute__((fallthrough));
case 2:
lb |= (uint32_t)msg[1] << 8;
__attribute__((fallthrough));
default:
lb |= (uint32_t)msg[0];
}
box->TDLR = lb;
box->TDHR = hb;
box->TDTR = len;
box->TIR = (target_id & 0x7FF) << 21 | CAN_TI0R_TXRQ;
return CAN_OK;
}
static void can_process_fifo(uint8_t fifo_num){
if(fifo_num > 1) return;
CAN_FIFOMailBox_TypeDef *box = &CAN->sFIFOMailBox[fifo_num];
volatile uint32_t *RFxR = (fifo_num) ? &CAN->RF1R : &CAN->RF0R;
// read all
while(*RFxR & CAN_RF0R_FMP0){ // amount of messages pending
// CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length
CAN_message msg;
uint8_t *dat = msg.data;
{ // set all data to 0
uint32_t *dptr = (uint32_t*)msg.data;
dptr[0] = dptr[1] = 0;
}
uint8_t len = box->RDTR & 0x0f;
msg.length = len;
msg.ID = box->RIR >> 21;
//msg.filterNo = (box->RDTR >> 8) & 0xff;
//msg.fifoNum = fifo_num;
if(len){ // message can be without data
uint32_t hb = box->RDHR, lb = box->RDLR;
switch(len){
case 8:
dat[7] = hb>>24;
__attribute__((fallthrough));
case 7:
dat[6] = (hb>>16) & 0xff;
__attribute__((fallthrough));
case 6:
dat[5] = (hb>>8) & 0xff;
__attribute__((fallthrough));
case 5:
dat[4] = hb & 0xff;
__attribute__((fallthrough));
case 4:
dat[3] = lb>>24;
__attribute__((fallthrough));
case 3:
dat[2] = (lb>>16) & 0xff;
__attribute__((fallthrough));
case 2:
dat[1] = (lb>>8) & 0xff;
__attribute__((fallthrough));
case 1:
dat[0] = lb & 0xff;
}
}
if(msg.ID == the_conf.CANID) parseCANcommand(&msg);
if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
}
//if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0;
*RFxR = 0; // clear FOVR & FULL
}
static void formerr(CAN_message *msg, errcodes err){
if(msg->length < 4) msg->length = 4;
msg->data[3] = (uint8_t)err;
}
/**
* @brief parseCANcommand - parser
* @param msg - incoming message @ my CANID
* FORMAT:
* 0 1 2 3 4 5 6 7
* [CMD][PAR][errcode][VALUE]
* CMD - uint16_t, PAR - uint8_t, errcode - one of CAN_errcodes, VALUE - int32_t
* `errcode` of incoming message doesn't matter
*/
TRUE_INLINE void parseCANcommand(CAN_message *msg){
int N = 1000;
// we don't check msg here as it cannot be NULL
#ifdef EBUG
DBG("Get data");
for(int i = 0; i < msg->length; ++i){
printuhex(msg->data[i]); bufputchar(' ');
}
newline();
#endif
if(msg->length == 0) goto sendmessage; // PING
uint16_t Index = *(uint16_t*)msg->data;
#ifdef EBUG
SEND("Index = "); printu(Index); newline();
#endif
if(Index >= CMD_AMOUNT){
formerr(msg, ERR_BADCMD);
goto sendmessage;
}
msg->data[3] = ERR_OK;
uint8_t par = msg->data[2];
if(par & 0x80){
formerr(msg, ERR_BADPAR);
goto sendmessage;
}
int32_t *val = (int32_t *)(&msg->data[4]);
if(msg->length == 8) par |= 0x80;
else if(msg->length == 2) par = CANMESG_NOPAR; // no parameter
else if(msg->length != 3){ // wrong length
formerr(msg, ERR_WRONGLEN);
goto sendmessage;
}
#ifdef EBUG
SEND("Run command\n");
#endif
errcodes ec = cmdlist[Index](par, val);
if(ec != ERR_OK){
formerr(msg, ec);
}else{
msg->length = 8;
}
sendmessage:
while(CAN_BUSY == can_send(msg->data, msg->length, the_conf.CANID))
if(--N == 0) break;
}
void cec_can_isr(){
if(CAN->RF0R & CAN_RF0R_FOVR0){ // FIFO overrun
CAN->RF0R &= ~CAN_RF0R_FOVR0;
can_status = CAN_FIFO_OVERRUN;
}
if(CAN->RF1R & CAN_RF1R_FOVR1){
CAN->RF1R &= ~CAN_RF1R_FOVR1;
can_status = CAN_FIFO_OVERRUN;
}
if(CAN->MSR & CAN_MSR_ERRI){ // Error
CAN->MSR &= ~CAN_MSR_ERRI;
// request abort for problem mailbox
if(CAN->TSR & CAN_TSR_TERR0) CAN->TSR |= CAN_TSR_ABRQ0;
if(CAN->TSR & CAN_TSR_TERR1) CAN->TSR |= CAN_TSR_ABRQ1;
if(CAN->TSR & CAN_TSR_TERR2) CAN->TSR |= CAN_TSR_ABRQ2;
#ifdef EBUG
last_err_code = CAN->ESR;
#endif
}
}

View File

@@ -0,0 +1,60 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __CAN_H__
#define __CAN_H__
#include "flash.h"
#include "hardware.h"
// CAN ID mask (11 bits)
#define CANIDMASK (0x7ff)
// amount of filter banks in STM32F0
#define STM32F0FBANKNO (28)
// incoming message buffer size
#define CAN_INMESSAGE_SIZE (8)
// CAN message
typedef struct{
uint8_t data[8]; // up to 8 bytes of data
uint8_t length; // data length
uint16_t ID; // ID of receiver
} CAN_message;
typedef enum{
CAN_STOP,
CAN_READY,
CAN_BUSY,
CAN_OK,
CAN_FIFO_OVERRUN
} CAN_status;
CAN_status CAN_get_status();
void CAN_reinit(uint16_t speed);
void CAN_setup(uint16_t speed);
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id);
void can_proc();
CAN_message *CAN_messagebuf_pop();
#endif // __CAN_H__

View File

@@ -0,0 +1,425 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "adc.h"
#include "buttons.h"
#include "can.h"
#include "commonproto.h"
#include "flash.h"
#include "hardware.h"
#include "steppers.h"
#ifdef EBUG
#include "strfunct.h"
#endif
/******* All functions from cmdlist[i].function *******/
static errcodes pingparser(uint8_t _U_ par, int32_t _U_ *val){
return ERR_OK; // just echo all input data over CAN (or return OK to USB)
}
static errcodes relayparser(uint8_t par, int32_t *val){
if(ISSETTER(par)){
if(*val) ON(RELAY);
else OFF(RELAY);
}
*val = CHK(RELAY);
return ERR_OK;
}
static errcodes buzzerparser(uint8_t par, int32_t *val){
if(ISSETTER(par)){
if(*val) ON(BUZZER);
else OFF(BUZZER);
}
*val = CHK(BUZZER);
return ERR_OK;
}
static errcodes adcparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > NUMBER_OF_ADC_CHANNELS-1) return ERR_BADPAR;
*val = (int32_t) getADCval(n);
return ERR_OK;
}
// NON-STANDARD COMMAND!!!!!!!
// errcode == keystate, value = last time!!!!
static errcodes buttonsparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > BTNSNO-1){
par = CANMESG_NOPAR; // the only chance to understand error
return ERR_BADPAR;
}
return (uint8_t) keystate(n, (uint32_t*)val);
}
// if N > amount of esw, return all (by bytes)
static errcodes eswparser(uint8_t par, int32_t *val){
#if ESWNO > 4
#error "change the code!!!"
#endif
uint8_t n = PARBASE(par);
if(n > ESWNO-1){ // all
*val = 0;
uint8_t *arr = (uint8_t*)val;
for(int i = 0; i < ESWNO; ++i)
*arr++ = ESW_state(i);
return ERR_OK;
}
*val = (int32_t)ESW_state(n);
return ERR_OK;
}
static errcodes mcutparser(uint8_t _U_ par, int32_t *val){
*val = getMCUtemp();
return ERR_OK;
}
static errcodes mcuvddparser(uint8_t _U_ par, int32_t *val){
*val = getVdd();
return ERR_OK;
}
static errcodes resetparser(uint8_t _U_ par, int32_t _U_ *val){
NVIC_SystemReset();
return ERR_OK;
}
static errcodes timeparser(uint8_t _U_ par, int32_t *val){
*val = Tms;
return ERR_OK;
}
static errcodes pwmparser(uint8_t par, int32_t *val){
if(PARBASE(par) > PWMCHMAX && par != CANMESG_NOPAR) return ERR_BADPAR;
#if PWMCHMAX != 0
#error "change the code!!!"
#endif
if(ISSETTER(par)){
if(*val < 0 || *val > PWMMAX) return ERR_BADVAL;
PWMset((uint32_t)*val);
}
*val = (int32_t) PWMget();
return ERR_OK;
}
TRUE_INLINE void setextpar(uint8_t val, uint8_t i){
switch(val){
case 0:
EXT_CLEAR(i);
break;
case 1:
EXT_SET(i);
break;
default:
EXT_TOGGLE(i);
}
}
// if `par` is absent, set/get all values in subsequent bytes
// 1 - external signal high, 0 - low
// commands: 0 - reset, 1 - set, !!!!other - toggle!!!!
static errcodes extparser(uint8_t par, int32_t *val){
#if EXTNO > 4
#error "change the code!!!"
#endif
uint8_t n = PARBASE(par);
SEND("par="); printu(par);
SEND(", n="); bufputchar('0'+n); newline();
if(n > EXTNO-1){ // all
SEND("ALL\n");
uint8_t *arr = (uint8_t*)val;
if(ISSETTER(par)){
for(int i = 0; i < EXTNO; ++i)
setextpar(arr[i], i);
}
for(int i = 0; i < EXTNO; ++i){
arr[i] = EXT_CHK(i);
}
return ERR_OK;
}
if(ISSETTER(par))
setextpar((uint8_t)*val, n);
*val = (int32_t) EXT_CHK(n);
return ERR_OK;
}
/******************* START of config parsers *******************/
static errcodes ustepsparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
#if MICROSTEPSMAX > 512
#error "Change the code anywhere!"
#endif
uint16_t m = (uint16_t)*val;
if(m < 1 || m > MICROSTEPSMAX) return ERR_BADVAL;
// find most significant bit
if(m != 1<<MSB(m)) return ERR_BADVAL;
if(the_conf.maxspd[n] * m > PCLK/(MOTORTIM_PSC+1)/(MOTORTIM_ARRMIN+1)) return ERR_BADVAL;
the_conf.microsteps[n] = m;
}
*val = the_conf.microsteps[n];
return ERR_OK;
}
static errcodes encstepsminparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val < 1 || *val > MAXENCTICKSPERSTEP - 1) return ERR_BADVAL;
the_conf.encperstepmin[n] = *val;
}
*val = the_conf.encperstepmin[n];
return ERR_OK;
}
static errcodes encstepsmaxparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val < 1 || *val > MAXENCTICKSPERSTEP) return ERR_BADVAL;
the_conf.encperstepmax[n] = *val;
}
*val = the_conf.encperstepmax[n];
return ERR_OK;
}
static errcodes accparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val/the_conf.microsteps[n] > ACCELMAXSTEPS || *val < 1) return ERR_BADVAL;
the_conf.accel[n] = *val;
}
*val = the_conf.accel[n];
return ERR_OK;
}
// calculate ARR value for given speed, return nearest possible speed
static uint16_t getSPD(uint8_t n, int32_t speed){
uint32_t ARR = PCLK/(MOTORTIM_PSC+1) / the_conf.microsteps[n] / speed - 1;
if(ARR < MOTORTIM_ARRMIN) ARR = MOTORTIM_ARRMIN;
else if(ARR > 0xffff) ARR = 0xffff;
speed = PCLK/(MOTORTIM_PSC+1) / the_conf.microsteps[n] / (ARR + 1);
if(speed > 0xffff) speed = 0xffff;
return (uint16_t)speed;
}
static errcodes maxspdparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val <= the_conf.minspd[n]) return ERR_BADVAL;
the_conf.maxspd[n] = getSPD(n, *val);
}
*val = the_conf.maxspd[n];
return ERR_OK;
}
static errcodes minspdparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val >= the_conf.maxspd[n]) return ERR_BADVAL;
the_conf.minspd[n] = getSPD(n, *val);
}
*val = the_conf.minspd[n];
return ERR_OK;
}
static errcodes spdlimparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
*val = getSPD(n, 0xffff);
return ERR_OK;
}
static errcodes maxstepsparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val < 1) return ERR_BADVAL;
the_conf.maxsteps[n] = *val;
}
*val = the_conf.maxsteps[n];
return ERR_OK;
}
static errcodes encrevparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val < 1 || *val > MAXENCREV) return ERR_BADVAL;
the_conf.encrev[n] = *val;
enctimers[n]->ARR = *val;
}
*val = the_conf.encrev[n];
return ERR_OK;
}
static errcodes motflagsparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
the_conf.motflags[n] = *((motflags_t*)val);
}
*(motflags_t*)val = the_conf.motflags[n];
return ERR_OK;
}
// setter of GLOBAL reaction, getter of LOCAL!
static errcodes eswreactparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)){
if(*val < 0 || *val > ESW_AMOUNT-1) return ERR_BADVAL;
the_conf.ESW_reaction[n] = *val;
}
// *val = the_conf.ESW_reaction[n];
*val = geteswreact(n);
return ERR_OK;
}
static errcodes saveconfparser(uint8_t _U_ par, int32_t _U_ *val){
if(store_userconf()) return ERR_CANTRUN;
return ERR_OK;
}
/******************* END of config parsers *******************/
/******************* START of motors' parsers *******************/
static errcodes reinitmparser(uint8_t _U_ par, int32_t _U_ *val){
init_steppers();
return ERR_OK;
}
static errcodes emstopparser(uint8_t par, int32_t _U_ *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
emstopmotor(n);
return ERR_OK;
}
static errcodes emstopallparser(uint8_t _U_ par, int32_t _U_ *val){
for(int i = 0; i < MOTORSNO; ++i)
emstopmotor(i);
return ERR_OK;
}
static errcodes stopparser(uint8_t par, int32_t _U_ *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
stopmotor(n);
return ERR_OK;
}
static errcodes curposparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)) return motor_absmove(n, *val);
return getpos(n, val);
}
static errcodes relstepsparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)) return motor_relmove(n, *val);
return getremainsteps(n, val);
}
static errcodes relslowparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
if(ISSETTER(par)) return motor_relslow(n, *val);
return getremainsteps(n, val);
}
static errcodes motstateparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
*val = getmotstate(n);
return ERR_OK;
}
static errcodes encposparser(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
errcodes ret = ERR_OK;
if(ISSETTER(par)){
if(!setencpos(n, *val)) ret = ERR_CANTRUN;
}
*val = encoder_position(n);
return ret;
}
static errcodes gotozeroparser(uint8_t par, _U_ int32_t *val){
uint8_t n = PARBASE(par);
if(n > MOTORSNO-1) return ERR_BADPAR;
return motor_goto0(n);
}
/******************* END of motors' parsers *******************/
/*
static errcodes parser(uint8_t _U_ par, int32_t _U_ *val){
return ERR_OK;
}
*/
const fpointer cmdlist[CMD_AMOUNT] = {
// different commands
[CMD_PING] = pingparser,
[CMD_RELAY] = relayparser,
[CMD_BUZZER] = buzzerparser,
[CMD_ADC] = adcparser,
[CMD_BUTTONS] = buttonsparser,
[CMD_ESWSTATE] = eswparser,
[CMD_MCUT] = mcutparser,
[CMD_MCUVDD] = mcuvddparser,
[CMD_RESET] = resetparser,
[CMD_TIMEFROMSTART] = timeparser,
[CMD_PWM] = pwmparser,
[CMD_EXT] = extparser,
// configuration
[CMD_SAVECONF] = saveconfparser,
[CMD_ENCSTEPMIN] = encstepsminparser,
[CMD_ENCSTEPMAX] = encstepsmaxparser,
[CMD_MICROSTEPS] = ustepsparser,
[CMD_ACCEL] = accparser,
[CMD_MAXSPEED] = maxspdparser,
[CMD_MINSPEED] = minspdparser,
[CMD_SPEEDLIMIT] = spdlimparser,
[CMD_MAXSTEPS] = maxstepsparser,
[CMD_ENCREV] = encrevparser,
[CMD_MOTFLAGS] = motflagsparser,
[CMD_ESWREACT] = eswreactparser,
// motor's commands
[CMD_ABSPOS] = curposparser,
[CMD_RELPOS] = relstepsparser,
[CMD_RELSLOW] = relslowparser,
[CMD_EMERGSTOP] = emstopparser,
[CMD_EMERGSTOPALL] = emstopallparser,
[CMD_STOP] = stopparser,
[CMD_REINITMOTORS] = reinitmparser,
[CMD_MOTORSTATE] = motstateparser,
[CMD_ENCPOS] = encposparser,
[CMD_GOTOZERO] = gotozeroparser,
};

View File

@@ -0,0 +1,97 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef COMMONPROTO_H__
#define COMMONPROTO_H__
#include <stm32f0.h>
#include "can.h"
#ifndef _U_
#define _U_ __attribute__((unused))
#endif
// message have no parameter
#define CANMESG_NOPAR (127)
// message is setter (have value)
#define ISSETTER(x) ((x & 0x80) ? 1 : 0)
// base value of parameter (even if it is a setter)
#define PARBASE(x) (x & 0x7f)
// error codes for answer message
typedef enum{
ERR_OK, // 0 - all OK
ERR_BADPAR, // 1 - parameter's value is wrong
ERR_BADVAL, // 2 - wrong parameter's value
ERR_WRONGLEN, // 3 - wrong message length
ERR_BADCMD, // 4 - unknown command
ERR_CANTRUN, // 5 - can't run given command due to bad parameters or other
} errcodes;
// pointer to function for command execution, both should be non-NULL for common cases
// if(par &0x80) it is setter, if not - getter
// if par == 0x127 it means absense of parameter!!!
// @return CANERR_OK (0) if OK or error code
typedef errcodes (*fpointer)(uint8_t par, int32_t *val);
enum{
CMD_PING // ping device
,CMD_RELAY // relay on/off
,CMD_BUZZER // buzzer on/off
,CMD_ADC // ADC ch#
,CMD_BUTTONS // buttons
,CMD_ESWSTATE // end-switches state
,CMD_MCUT // MCU temperature
,CMD_MCUVDD // MCU Vdd
,CMD_RESET // software reset
,CMD_TIMEFROMSTART // get time from start
,CMD_PWM // PWM value
,CMD_EXT // value on EXTx outputs
,CMD_SAVECONF // save configuration
,CMD_ENCSTEPMIN // min ticks of encoder per one step
,CMD_ENCSTEPMAX // max ticks of encoder per one step
,CMD_MICROSTEPS // get/set microsteps
,CMD_ACCEL // set/get acceleration/deceleration
,CMD_MAXSPEED // set/get maximal speed
,CMD_MINSPEED // set/get minimal speed
,CMD_SPEEDLIMIT // get limit of speed for current microsteps settings
,CMD_MAXSTEPS // max steps (-max..+max)
,CMD_ENCREV // encoder's pulses per revolution
,CMD_MOTFLAGS // motor flags
,CMD_ESWREACT // ESW reaction flags
,CMD_REINITMOTORS // re-init motors after configuration changing
,CMD_ABSPOS // current position (set/get)
,CMD_RELPOS // set relative steps or get steps left
,CMD_RELSLOW // change relative position at lowest speed
,CMD_EMERGSTOP // stop moving NOW
,CMD_STOP // smooth motor stop
,CMD_EMERGSTOPALL // emergency stop for all motors
,CMD_GOTOZERO // go to zero's ESW
,CMD_MOTORSTATE // motor state
,CMD_ENCPOS // position of encoder (independing on settings)
//,CMD_STOPDECEL
//,CMD_FINDZERO
// should be the last:
,CMD_AMOUNT // amount of common commands
};
extern const fpointer cmdlist[CMD_AMOUNT];
#endif // COMMONPROTO_H__

View File

@@ -0,0 +1,67 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// custom standalone buttons reaction
#include <stm32f0.h>
#include "buttons.h"
#include "custom_buttons.h"
#include "hardware.h"
/*
* check buttons, on long press of button:
* 1 - switch relay
* 2 - switch buzzer
* 3 - work with PWM out 0 (when btn3 pressed, btn1 increased & btn2 decreased PWM width)
* press once btn2/3 to change PWM @1, hold to change @25 (repeat as many times as need)
*/
void custom_buttons_process(){
static uint32_t lastT = 0;
static uint8_t pwmval = 127;
static uint8_t trig = 0; // == 1 if given btn3 was off
if(lastUnsleep == lastT) return; // no buttons activity
lastT = lastUnsleep;
if(keyevt(3) == EVT_HOLD){ // PWM
if(keyevt(2) == EVT_HOLD){ // decrease PWM by 25
if(pwmval > 25) pwmval -= 25;
else pwmval = 0;
}else if(keyevt(2) == EVT_PRESS){ // decrease PWM by 1
if(pwmval > 0) --pwmval;
}else if(keyevt(1) == EVT_HOLD){ // increase PWM by 25
if(pwmval < 230) pwmval += 25;
else pwmval = 255;
}else if(keyevt(1) == EVT_PRESS){
if(pwmval < 254) ++pwmval;
}
if(trig == 0){ // first hold after release
if(TIM1->CCR1) TIM1->CCR1 = 0; // turn off if was ON
else{
TIM1->CCR1 = pwmval;
trig = 1;
}
}else TIM1->CCR1 = pwmval;
return;
}else trig = 0;
if(keyevt(1) == EVT_HOLD){ // relay
TGL(RELAY);
}
if(keyevt(2) == EVT_HOLD){ // buzzer
TGL(BUZZER);
}
}

View File

@@ -0,0 +1,25 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef CUSTOM_BUTTONS_H__
#define CUSTOM_BUTTONS_H__
void custom_buttons_process();
#endif // CUSTOM_BUTTONS_H__

View File

@@ -0,0 +1,243 @@
/*
* geany_encoding=koi8-r
* flash.c
*
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include <stm32f0.h>
#include <string.h> // memcpy
#include "flash.h"
#include "steppers.h"
#include "strfunct.h"
extern const uint32_t __varsstart, _BLOCKSIZE;
static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE;
// max amount of Config records stored (will be recalculate in flashstorage_init()
static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here
#define DEFMF {.haveencoder = 1, .donthold = 1, .eswinv = 1, .keeppos = 1}
#define USERCONF_INITIALIZER { \
.userconf_sz = sizeof(user_conf) \
,.CANspeed = 100 \
,.CANID = 0xaa \
,.microsteps = {32, 32, 32} \
,.accel = {500, 500, 500} \
,.maxspd = {2000, 2000, 2000} \
,.minspd = {20, 20, 20} \
,.maxsteps = {500000, 500000, 500000} \
,.encrev = {4000,4000,4000} \
,.encperstepmin = {17,17,17} \
,.encperstepmax = {23,23,23} \
,.motflags = {DEFMF,DEFMF,DEFMF} \
,.ESW_reaction = {ESW_IGNORE, ESW_IGNORE, ESW_IGNORE} \
}
static int erase_flash(const void*, const void*);
static int write2flash(const void*, const void*, uint32_t);
// don't write `static` here, or get error:
// 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t'
const user_conf *Flash_Data = (const user_conf *)(&__varsstart);
user_conf the_conf = USERCONF_INITIALIZER;
static int currentconfidx = -1; // index of current configuration
/**
* @brief binarySearch - binary search in flash for last non-empty cell
* any struct searched should have its sizeof() @ the first field!!!
* @param l - left index
* @param r - right index (should be @1 less than last index!)
* @param start - starting address
* @param stor_size - size of structure to search
* @return index of non-empty cell or -1
*/
static int binarySearch(int r, const uint8_t *start, int stor_size){
int l = 0;
while(r >= l){
int mid = l + (r - l) / 2;
const uint8_t *s = start + mid * stor_size;
if(*((const uint16_t*)s) == stor_size){
if(*((const uint16_t*)(s + stor_size)) == 0xffff){ // next is free
return mid;
}else{ // element is to the right
l = mid + 1;
}
}else{ // element is to the left
r = mid - 1;
}
}
return -1; // not found
}
/**
* @brief flashstorage_init - initialization of user conf storage
* run in once @ start
*/
void flashstorage_init(){
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
uint32_t flsz = FLASH_SIZE * blocksize; // size in bytes
flsz -= (uint32_t)(&__varsstart) - FLASH_BASE;
maxCnum = flsz / sizeof(user_conf);
}
// -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
currentconfidx = binarySearch((int)maxCnum-2, (const uint8_t*)Flash_Data, sizeof(user_conf));
if(currentconfidx > -1){
memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf));
}
}
// store new configuration
// @return 0 if all OK
int store_userconf(){
// maxnum - 3 means that there always should be at least one empty record after last data
// for binarySearch() checking that there's nothing more after it!
if(currentconfidx > (int)maxCnum - 3){ // there's no more place
currentconfidx = 0;
if(erase_flash(Flash_Data, (&__varsstart))) return 1;
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
}
static int write2flash(const void *start, const void *wrdata, uint32_t stor_size){
int ret = 0;
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
while (FLASH->SR & FLASH_SR_BSY);
if(FLASH->SR & FLASH_SR_WRPRTERR){
return 1; // write protection
}
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
FLASH->CR |= FLASH_CR_PG;
const uint16_t *data = (const uint16_t*) wrdata;
volatile uint16_t *address = (volatile uint16_t*) start;
uint32_t i, count = (stor_size + 1) / 2;
for (i = 0; i < count; ++i){
IWDG->KR = IWDG_REFRESH;
*(volatile uint16_t*)(address + i) = data[i];
while (FLASH->SR & FLASH_SR_BSY);
if(FLASH->SR & FLASH_SR_PGERR){
ret = 1; // program error - meet not 0xffff
break;
}else while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
}
FLASH->CR |= FLASH_CR_LOCK; // lock it back
FLASH->CR &= ~(FLASH_CR_PG);
return ret;
}
/**
* @brief erase_flash - erase N pages of flash memory
* @param start - first address
* @param end - last address (or NULL if need to erase all flash remaining)
* @return 0 if succeed
*/
static int erase_flash(const void *start, const void *end){
int ret = 0;
uint32_t nblocks = 1, flsz = 0;
if(!end){ // erase all remaining
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
flsz = FLASH_SIZE * blocksize; // size in bytes
flsz -= (uint32_t)start - FLASH_BASE;
}
}else{ // erase a part
flsz = (uint32_t)end - (uint32_t)start;
}
nblocks = flsz / blocksize;
if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1;
for(uint32_t i = 0; i < nblocks; ++i){
IWDG->KR = IWDG_REFRESH;
/* (1) Wait till no operation is on going */
/* (2) Clear error & EOP bits */
/* (3) Check that the Flash is unlocked */
/* (4) Perform unlock sequence */
while ((FLASH->SR & FLASH_SR_BSY) != 0){} /* (1) */
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; /* (2) */
/* if (FLASH->SR & FLASH_SR_EOP){
FLASH->SR |= FLASH_SR_EOP;
}*/
if ((FLASH->CR & FLASH_CR_LOCK) != 0){ /* (3) */
FLASH->KEYR = FLASH_KEY1; /* (4) */
FLASH->KEYR = FLASH_KEY2;
}
/* (1) Set the PER bit in the FLASH_CR register to enable page erasing */
/* (2) Program the FLASH_AR register to select a page to erase */
/* (3) Set the STRT bit in the FLASH_CR register to start the erasing */
/* (4) Wait until the EOP flag in the FLASH_SR register set */
/* (5) Clear EOP flag by software by writing EOP at 1 */
/* (6) Reset the PER Bit to disable the page erase */
FLASH->CR |= FLASH_CR_PER; /* (1) */
FLASH->AR = (uint32_t)Flash_Data + i*blocksize; /* (2) */
FLASH->CR |= FLASH_CR_STRT; /* (3) */
while(!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR |= FLASH_SR_EOP; /* (5)*/
if(FLASH->SR & FLASH_SR_WRPRTERR){ /* Check Write protection error */
ret = 1;
FLASH->SR |= FLASH_SR_WRPRTERR; /* Clear the flag by software by writing it at 1*/
break;
}
FLASH->CR &= ~FLASH_CR_PER; /* (6) */
}
return ret;
}
void dump_userconf(_U_ char *txt){
#ifdef EBUG
SEND("flashsize="); printu(FLASH_SIZE); bufputchar('*');
printu(blocksize); bufputchar('='); printu(FLASH_SIZE*blocksize);
newline();
#endif
SEND("userconf_addr="); printuhex((uint32_t)Flash_Data);
SEND("\nuserconf_idx="); printi(currentconfidx);
SEND("\nuserconf_sz="); printu(the_conf.userconf_sz);
SEND("\ncanspeed="); printu(the_conf.CANspeed);
SEND("\ncanid="); printu(the_conf.CANID);
// motors' data
for(int i = 0; i < MOTORSNO; ++i){
char cur = '0' + i;
#define PROPNAME(nm) do{newline(); SEND(nm); bufputchar(cur); bufputchar('=');}while(0)
PROPNAME("microsteps");
printu(the_conf.microsteps[i]);
PROPNAME("accel");
printu(the_conf.accel[i]);
PROPNAME("maxspeed");
printu(the_conf.maxspd[i]);
PROPNAME("minspeed");
printu(the_conf.minspd[i]);
PROPNAME("maxsteps");
printu(the_conf.maxsteps[i]);
PROPNAME("encperrev");
printu(the_conf.encrev[i]);
PROPNAME("encperstepmin");
printu(the_conf.encperstepmin[i]);
PROPNAME("encperstepmax");
printu(the_conf.encperstepmax[i]);
PROPNAME("motflags");
printuhex(*((uint8_t*)&the_conf.motflags[i]));
PROPNAME("eswreaction");
printu(the_conf.ESW_reaction[i]);
#undef PROPNAME
}
NL();
}

View File

@@ -0,0 +1,83 @@
/*
* flash.h
*
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#pragma once
#ifndef __FLASH_H__
#define __FLASH_H__
#include "hardware.h"
#ifndef _U_
#define _U_ __attribute__((unused))
#endif
// limiting values
#define MICROSTEPSMAX (512)
// (STEPS per second^2)
#define ACCELMAXSTEPS (1000)
// max encoder steps per rev
#define MAXENCREV (100000)
// register with flash size (in blocks)
#ifndef FLASH_SIZE_REG
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC)
#endif
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
// motor flags
typedef struct{
uint8_t reverse : 1; // bit0 - reversing motor rotation
uint8_t encreverse : 1; // bit1 - reversing encoder rotation TODO: configure encoder's timer to downcounting
uint8_t haveencoder : 1; // bit2 - have encoder
uint8_t donthold : 1; // bit3 - clear power @ stop (don't hold motor when stopped)
uint8_t eswinv : 1; // bit4 - inverse end-switches
uint8_t keeppos : 1; // bit5 - keep current position (as servo motor)
} motflags_t;
/*
* struct to save user configurations
*/
typedef struct __attribute__((packed, aligned(4))){
uint16_t userconf_sz; // "magick number"
uint16_t CANspeed; // default CAN speed
uint16_t CANID; // identifier
uint16_t microsteps[MOTORSNO]; // microsteps amount per step
uint16_t accel[MOTORSNO]; // acceleration/deceleration (steps/s^2)
uint16_t maxspd[MOTORSNO]; // max motor speed (steps per second)
uint16_t minspd[MOTORSNO]; // min motor speed (steps per second)
uint32_t maxsteps[MOTORSNO]; // maximal amount of steps
uint16_t encrev[MOTORSNO]; // encoders' counts per revolution
uint16_t encperstepmin[MOTORSNO]; // min amount of encoder ticks per one step
uint16_t encperstepmax[MOTORSNO]; // max amount of encoder ticks per one step
motflags_t motflags[MOTORSNO]; // motor's flags
uint8_t ESW_reaction[MOTORSNO]; // end-switches reaction (esw_react)
} user_conf;
extern user_conf the_conf; // global user config (read from FLASH to RAM)
// data from ld-file: start address of storage
void flashstorage_init();
int store_userconf();
void dump_userconf(_U_ char *txt);
#endif // __FLASH_H__

View File

@@ -0,0 +1,229 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hardware.h"
#include "can.h"
#include "steppers.h"
#include "strfunct.h"
// Buttons: PA10, PA13, PA14, PA15, pullup (0 active)
volatile GPIO_TypeDef *BTNports[BTNSNO] = {GPIOA, GPIOA, GPIOA, GPIOA};
const uint32_t BTNpins[BTNSNO] = {1<<10, 1<<13, 1<<14, 1<<15};
// Limit switches: PC13, PC14, PC15, pulldown (0 active)
volatile GPIO_TypeDef *ESWports[ESWNO] = {GPIOC, GPIOC, GPIOC};
const uint32_t ESWpins[ESWNO] = {1<<13, 1<<14, 1<<15};
// external GPIO
volatile GPIO_TypeDef *EXTports[EXTNO] = {GPIOB, GPIOB, GPIOB};
const uint32_t EXTpins[EXTNO] = {1<<13, 1<<14, 1<<15};
// motors: DIR/EN
volatile GPIO_TypeDef *ENports[MOTORSNO] = {GPIOB, GPIOB, GPIOB};
const uint32_t ENpins[MOTORSNO] = {1<<0, 1<<2, 1<<11};
volatile GPIO_TypeDef *DIRports[MOTORSNO] = {GPIOB, GPIOB, GPIOB};
const uint32_t DIRpins[MOTORSNO] = {1<<1, 1<<10, 1<<12};
// timers for motors
volatile TIM_TypeDef *mottimers[MOTORSNO] = {TIM15, TIM14, TIM16};
// timers for encoders
volatile TIM_TypeDef *enctimers[MOTORSNO] = {TIM1, TIM2, TIM3};
void gpio_setup(void){
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIOFEN;
GPIOA->MODER = GPIO_MODER_MODER0_AF | GPIO_MODER_MODER1_AF | GPIO_MODER_MODER2_AF | GPIO_MODER_MODER3_AI |
GPIO_MODER_MODER4_AF | GPIO_MODER_MODER5_AI | GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF |
GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF;
GPIOA->PUPDR = GPIO_PUPDR10_PU | GPIO_PUPDR13_PU | GPIO_PUPDR14_PU | GPIO_PUPDR15_PU;
GPIOA->AFR[0] = (2 << (0*4)) | (2 << (1*4)) | (0 << (2*4)) | (4 << (4*4)) | (5 << (6*4)) | (5 << (7*4));
GPIOA->AFR[1] = (2 << (0*4)) | (2 << (1*4));
pin_set(GPIOB, (1<<0) | (1<<2) | (1<<11)); // turn off motors @ start
GPIOB->MODER = GPIO_MODER_MODER0_O | GPIO_MODER_MODER1_O | GPIO_MODER_MODER2_O | GPIO_MODER_MODER3_O |
GPIO_MODER_MODER4_AF | GPIO_MODER_MODER5_AF | GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF |
GPIO_MODER_MODER10_O | GPIO_MODER_MODER11_O | GPIO_MODER_MODER12_O | GPIO_MODER_MODER13_O |
GPIO_MODER_MODER14_O | GPIO_MODER_MODER15_O ;
GPIOB->AFR[0] = (1 << (4*4)) | (1 << (5*4)) | (1 << (6*4)) | (1 << (7*4));
GPIOC->PUPDR = GPIO_PUPDR13_PD | GPIO_PUPDR14_PD | GPIO_PUPDR15_PD;
GPIOF->MODER = GPIO_MODER_MODER0_O;
}
void iwdg_setup(){
uint32_t tmout = 16000000;
/* Enable the peripheral clock RTC */
/* (1) Enable the LSI (40kHz) */
/* (2) Wait while it is not ready */
RCC->CSR |= RCC_CSR_LSION; /* (1) */
while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */
/* Configure IWDG */
/* (1) Activate IWDG (not needed if done in option bytes) */
/* (2) Enable write access to IWDG registers */
/* (3) Set prescaler by 64 (1.6ms for each tick) */
/* (4) Set reload value to have a rollover each 2s */
/* (5) Check if flags are reset */
/* (6) Refresh counter */
IWDG->KR = IWDG_START; /* (1) */
IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */
IWDG->PR = IWDG_PR_PR_1; /* (3) */
IWDG->RLR = 1250; /* (4) */
tmout = 16000000;
while(IWDG->SR){if(--tmout == 0) break;} /* (5) */
IWDG->KR = IWDG_REFRESH; /* (6) */
}
static IRQn_Type motirqs[MOTORSNO] = {TIM15_IRQn, TIM14_IRQn, TIM16_IRQn};
// motor's PWM
static void setup_mpwm(int i){
volatile TIM_TypeDef *TIM = mottimers[i];
TIM->CR1 = TIM_CR1_ARPE; // buffered ARR
TIM->PSC = MOTORTIM_PSC; // 16MHz
// PWM mode 1 (active -> inactive)
TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
#if MOTORTIM_ARRMIN < 5
#error "change the code!"
#endif
TIM->CCR1 = MOTORTIM_ARRMIN - 3; // ~10us for pulse duration
TIM->ARR = 0xffff;
// TIM->EGR = TIM_EGR_UG; // generate update to refresh ARR
TIM->BDTR |= TIM_BDTR_MOE; // enable main output
TIM->CCER = TIM_CCER_CC1E; // turn it on, active high
TIM->DIER = TIM_DIER_CC1IE; // allow CC interrupt (we should count steps)
NVIC_EnableIRQ(motirqs[i]);
}
static IRQn_Type encirqs[MOTORSNO] = {TIM1_BRK_UP_TRG_COM_IRQn, TIM2_IRQn, TIM3_IRQn};
static void setup_enc(int i){
volatile TIM_TypeDef *TIM = enctimers[i];
/* (1) Configure TI1FP1 on TI1 (CC1S = 01)
configure TI1FP2 on TI2 (CC2S = 01)
filters sampling = fDTS/8, N=6 */
/* (2) Configure TI1FP1 and TI1FP2 non inverted (CC1P = CC2P = 0, reset value) */
/* (3) Configure both inputs are active on both rising and falling edges
(SMS = 011), set external trigger filter to f_DTS/8, N=6 (ETF=1000) */
/* (4) Enable the counter by writing CEN=1 in the TIMx_CR1 register,
set tDTS=4*tCK_INT. */
TIM->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0 | TIM_CCMR1_IC1F_3 | TIM_CCMR1_IC2F_3; /* (1)*/
//TIMx->CCER &= (uint16_t)(~(TIM_CCER_CC21 | TIM_CCER_CC2P); /* (2) */
TIM->SMCR = TIM_SMCR_ETF_3 | TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1; /* (3) */
// enable update interrupt
TIM->DIER = TIM_DIER_UIE;
// generate interrupt each revolution
TIM->ARR = the_conf.encrev[i];
// enable timer
TIM->CR1 = TIM_CR1_CKD_1 | TIM_CR1_CEN; /* (4) */
NVIC_EnableIRQ(encirqs[i]);
}
// timers 14,15,16,17 - PWM@ch1, 1,2,3 - encoders @ ch1/2
void timers_setup(){
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN;
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM15EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_TIM17EN; // enable clocking
// setup PWM @ TIM17 - single PWM channel
// PWM mode 1 (active -> inactive)
TIM17->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
TIM17->PSC = 5; // 8MHz for 31kHz PWM
TIM17->ARR = 254; // ARR for 8-bit PWM
TIM17->CCR1 = 0; // level=0
TIM17->BDTR |= TIM_BDTR_MOE; // enable main output
TIM17->CCER = TIM_CCER_CC1E; // enable PWM output
TIM17->CR1 = TIM_CR1_CEN; // enable timer
for(int i = 0; i < MOTORSNO; ++i)
setup_mpwm(i);
for(int i = 0; i < MOTORSNO; ++i){
if(the_conf.motflags[i].haveencoder){ // motor have the encoder
setup_enc(i);
}
}
}
// pause in milliseconds for some purposes
void pause_ms(uint32_t pause){
uint32_t Tnxt = Tms + pause;
while(Tms < Tnxt) nop();
}
#ifndef STM32F072xB
#warning "Only F072 can jump to bootloader"
#endif
void Jump2Boot(){ // for STM32F072
void (*SysMemBootJump)(void);
volatile uint32_t addr = 0x1FFFC800;
// reset systick
SysTick->CTRL = 0;
// reset clocks
RCC->APB1RSTR = RCC_APB1RSTR_CECRST | RCC_APB1RSTR_DACRST | RCC_APB1RSTR_PWRRST | RCC_APB1RSTR_CRSRST |
RCC_APB1RSTR_CANRST | RCC_APB1RSTR_USBRST | RCC_APB1RSTR_I2C2RST | RCC_APB1RSTR_I2C1RST |
RCC_APB1RSTR_USART4RST | RCC_APB1RSTR_USART3RST | RCC_APB1RSTR_USART2RST | RCC_APB1RSTR_SPI2RST |
RCC_APB1RSTR_WWDGRST | RCC_APB1RSTR_TIM14RST | RCC_APB1RSTR_TIM7RST | RCC_APB1RSTR_TIM6RST |
RCC_APB1RSTR_TIM3RST | RCC_APB1RSTR_TIM2RST;
RCC->APB2RSTR = RCC_APB2RSTR_DBGMCURST | RCC_APB2RSTR_TIM17RST | RCC_APB2RSTR_TIM16RST | RCC_APB2RSTR_TIM15RST |
RCC_APB2RSTR_USART1RST | RCC_APB2RSTR_SPI1RST | RCC_APB2RSTR_TIM1RST | RCC_APB2RSTR_ADCRST | RCC_APB2RSTR_SYSCFGRST;
RCC->AHBRSTR = 0;
RCC->APB1RSTR = 0;
RCC->APB2RSTR = 0;
// Enable the SYSCFG peripheral.
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
// remap memory to 0 (only for STM32F0)
SYSCFG->CFGR1 = 0x01; __DSB(); __ISB();
SysMemBootJump = (void (*)(void)) (*((uint32_t *)(addr + 4)));
// set main stack pointer
__set_MSP(*((uint32_t *)addr));
// jump to bootloader
SysMemBootJump();
}
// calculate MSB position of value `val`
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
static const uint8_t bval[] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3};
uint8_t MSB(uint16_t val){
register uint8_t r = 0;
if(val & 0xff00){r += 8; val >>= 8;}
if(val & 0x00f0){r += 4; val >>= 4;}
return ((uint8_t)r + bval[val]);
}
// state 1 - pressed, 0 - released (pin active is zero)
uint8_t ESW_state(uint8_t x){
uint8_t val = ((ESWports[x]->IDR & ESWpins[x]) ? 0 : 1);
if(the_conf.motflags[x].eswinv) val = !val;
return val;
}
void tim14_isr(){
//TIM14->CR1 &= ~TIM_CR1_CEN;
addmicrostep(1);
TIM14->SR = 0;
}
void tim15_isr(){
//TIM15->CR1 &= ~TIM_CR1_CEN;
addmicrostep(0);
TIM15->SR = 0;
}
void tim16_isr(){
//TIM16->CR1 &= ~TIM_CR1_CEN;
addmicrostep(2);
TIM16->SR = 0;
}
void tim1_brk_up_trg_com_isr(){
encoders_UPD(0);
}
void tim2_isr(){
encoders_UPD(1);
}
void tim3_isr(){
encoders_UPD(2);
}

View File

@@ -0,0 +1,203 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __HARDWARE_H__
#define __HARDWARE_H__
#include <stm32f0.h>
// PCLK frequency
#ifndef PCLK
#define PCLK (48000000)
#endif
// motors' timer PSC = PCLK/Tfreq - 1, Tfreq=16MHz
#define MOTORTIM_PSC (2)
// minimal ARR value - 99 for 5000 steps per second @ 32 microsteps/step
#define MOTORTIM_ARRMIN (99)
// default CAN bus speed in kbaud
#define DEFAULT_CAN_SPEED (250)
#define CONCAT(a,b) a ## b
#define STR_HELPER(s) #s
#define STR(s) STR_HELPER(s)
/** Pinout:
---- Motors' encoders ---------------
PA0 Enc2a (motor2 encoder) - TIM2CH1/2 [AF2]
PA1 Enc2b [AF2]
PA8 Enc1a (motor1 encoder) - TIM1CH1/2 [AF2]
PA9 Enc1b [AF2]
PB4 Enc3a (motor3 encoder) - TIM3CH1/2 [AF1]
PB5 Enc3b [AF1]
---- Motors' clocks + PWM -----------
PA2 CLK1 (motor1 clock) - TIM15CH1 [AF0]
PA4 CLK2 (motor2 clock) - TIM14CH1 [AF4]
PA6 CLK3 (motor3 clock) - TIM16CH1 [AF5]
PA7 PWM (opendrain PWM, up to 12V) - TIM17CH1 [AF5]
---- GPIO out (push-pull) -----------
PB0 ~EN1 (motor1 not enable)
PB1 DIR1 (motor1 direction)
PB2 ~EN2 (motor2 not enable)
PB3 Buzzer (external buzzer or other non-inductive opendrain load up to 12V)
PB10 DIR2 (motor2 direction)
PB11 ~EN3 (motor3 not enable)
PB12 DIR3 (motor3 direction)
PB13 Ext0 (3 external outputs: 5V, up to 20mA)
PB14 Ext1
PB15 Ext2
PF0 Relay (10A 250VAC, 10A 30VDC)
---- GPIO in -----------------------
PA10 BTN1 (user button 1) - pullup
PA13 BTN2 (user button 2) - pullup
PA14 BTN3 (user button 3) - pullup
PA15 BTN4 (user button 4) - pullup
PC13 ESW1 (motor1 zero limit switch) - pulldown
PC14 ESW2 (motor2 zero limit switch) - pulldown
PC15 ESW3 (motor3 zero limit switch) - pulldown
---- ADC ----------------------------
PA3 ADC1 (ADC1 in, 0-3.3V) [ADC3]
PA5 ADC2 (ADC2 in, 0-3.3V) [ADC5]
---- USB ----------------------------
PA11 USBDM
PA12 USBDP
---- I2C ----------------------------
PB6 I2C SCL (external I2C bus, have internal pullups of 4.7kOhm to +3.3V) - I2C1 [AF1]
PB7 I2C SDA [AF1]
---- CAN ----------------------------
PB8 CAN Rx (external CAN bus, with local galvanic isolation) [AF4]
PB9 CAN Tx [AF4]
COMMON setup:
PORT FN AFR[1]idx
PA0 AF2
PA1 AF2
PA2 AF0
PA3 AI
PA4 AF4
PA5 AI
PA6 AF5
PA7 AF5
PA8 AF2 0
PA9 AF2 1
PA10 PU
PA11 USB
PA12 USB
PA13 PU
PA14 PU
PA15 PU
PB0 PP
PB1 PP
PB2 PP
PB3 PP
PB4 AF1
PB5 AF1
PB6 AF1
PB7 AF1
PB8 CAN
PB9 CAN
PB10 PP
PB11 PP
PB12 PP
PB13 PP
PB14 PP
PB15 PP
PC13 PD
PC14 PD
PC15 PD
PF0 PP
**/
// buzzer
#define BUZZERport (GPIOB)
#define BUZZERpin (1<<3)
// relay
#define RELAYport (GPIOF)
#define RELAYpin (1<<0)
// ON(RELAY), OFF(BUZZER) etc
#define ON(x) do{pin_set(CONCAT(x, port), CONCAT(x, pin));}while(0)
#define OFF(x) do{pin_clear(CONCAT(x, port), CONCAT(x, pin));}while(0)
#define TGL(x) do{pin_toggle(CONCAT(x, port), CONCAT(x, pin));}while(0)
#define CHK(x) (pin_read(CONCAT(x, port), CONCAT(x, pin)))
// max value of PWM
#define PWMMAX (255)
// max index of PWM channels
#define PWMCHMAX (0)
#define PWMset(val) do{TIM17->CCR1 = val;}while(0)
#define PWMget() (TIM17->CCR1)
// extpins amount
#define EXTNO (3)
extern volatile GPIO_TypeDef *EXTports[EXTNO];
extern const uint32_t EXTpins[EXTNO];
#define EXT_SET(x) do{ pin_set(EXTports[x], EXTpins[x]); }while(0)
#define EXT_CLEAR(x) do{ pin_clear(EXTports[x], EXTpins[x]); }while(0)
#define EXT_TOGGLE(x) do{ pin_toggle(EXTports[x], EXTpins[x]); }while(0)
#define EXT_CHK(x) (pin_read(EXTports[x], EXTpins[x]))
// Buttons amount
#define BTNSNO (4)
// Buttons ports & pins
extern volatile GPIO_TypeDef *BTNports[BTNSNO];
extern const uint32_t BTNpins[BTNSNO];
// state 1 - pressed, 0 - released (pin active is zero)
#define BTN_state(x) ((BTNports[x]->IDR & BTNpins[x]) ? 0 : 1)
// Limit switches
#define ESWNO (3)
// ESW ports & pins
extern volatile GPIO_TypeDef *ESWports[ESWNO];
extern const uint32_t ESWpins[ESWNO];
// motors
#define MOTORSNO (3)
extern volatile GPIO_TypeDef *ENports[MOTORSNO];
extern const uint32_t ENpins[MOTORSNO];
#define MOTOR_EN(x) do{ pin_clear(ENports[x], ENpins[x]); }while(0)
#define MOTOR_DIS(x) do{ pin_set(ENports[x], ENpins[x]); }while(0)
extern volatile GPIO_TypeDef *DIRports[MOTORSNO];
extern const uint32_t DIRpins[MOTORSNO];
#define MOTOR_CW(x) do{ pin_set(DIRports[x], DIRpins[x]); }while(0)
#define MOTOR_CCW(x) do{ pin_clear(DIRports[x], DIRpins[x]); }while(0)
// interval of velocity checking (10ms)
#define MOTCHKINTERVAL (10)
// maximal ticks of encoder per step
#define MAXENCTICKSPERSTEP (100)
// amount of full steps per revolution
#define STEPSPERREV (200)
extern volatile uint32_t Tms;
// timers of motors
extern volatile TIM_TypeDef *mottimers[];
// timers for encoders
extern volatile TIM_TypeDef *enctimers[];
uint8_t ESW_state(uint8_t x);
void gpio_setup();
void iwdg_setup();
void timers_setup();
void pause_ms(uint32_t pause);
void Jump2Boot();
uint8_t MSB(uint16_t val);
#endif // __HARDWARE_H__

View File

@@ -0,0 +1,273 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# 74HC4051
#
DEF 74HC4051 U 0 10 Y Y 1 F N
F0 "U" 0 0 50 H V C CNN
F1 "74HC4051" 0 -150 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
$FPLIST
SO16
TSSOP16
SSOP16
DHVQFN16
$ENDFPLIST
DRAW
S -400 450 400 -450 0 1 0 N
X Y4 1 700 -50 300 L 50 50 1 1 B
X S1 10 -700 250 300 R 50 50 1 1 I
X S0 11 -700 350 300 R 50 50 1 1 I
X Y3 12 700 50 300 L 50 50 1 1 B
X Y0 13 700 350 300 L 50 50 1 1 B
X Y1 14 700 250 300 L 50 50 1 1 B
X Y2 15 700 150 300 L 50 50 1 1 B
X VCC 16 -700 -100 300 R 50 50 1 1 W
X Y6 2 700 -250 300 L 50 50 1 1 B
X Z 3 0 -750 300 U 50 50 1 1 B
X Y7 4 700 -350 300 L 50 50 1 1 B
X Y5 5 700 -150 300 L 50 50 1 1 B
X ~E 6 -700 -350 300 R 50 50 1 1 I I
X VEE 7 -700 0 300 R 50 50 1 1 W
X GND 8 -700 -200 300 R 50 50 1 1 W
X S2 9 -700 150 300 R 50 50 1 1 I
ENDDRAW
ENDDEF
#
# B0x0xS-1W
#
DEF B0x0xS-1W Q? 0 40 Y Y 1 F N
F0 "Q?" 0 250 50 H V C CNN
F1 "B0x0xS-1W" 0 -250 50 H V C CNN
F2 "my_footprints:B0x0xS" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
ALIAS B0305S B0505S
$FPLIST
b0x0xs
$ENDFPLIST
DRAW
S -200 200 200 -200 0 1 0 N
X GND 1 -400 -100 200 R 50 50 1 1 W
X Vin 2 -400 100 200 R 50 50 1 1 W
X 0V 3 400 -100 200 L 50 50 1 1 w
X +Vo 4 400 100 200 L 50 50 1 1 w
ENDDRAW
ENDDEF
#
# CD4050
#
DEF CD4050 U 0 40 Y Y 1 F N
F0 "U" 0 -400 50 H V C CNN
F1 "CD4050" 0 400 50 H V C CNN
F2 "Package_SO:SOIC-16_3.9x9.9mm_P1.27mm" 0 -50 50 H I C CNN
F3 "" 0 -50 50 H I C CNN
DRAW
S -200 350 200 -350 0 1 0 N
X Vcc 1 400 -300 200 L 50 50 1 1 W
X O4 10 400 0 200 L 50 50 1 1 O
X I5 11 -400 -100 200 R 50 50 1 1 I
X O5 12 400 -100 200 L 50 50 1 1 O
X I6 14 -400 -200 200 R 50 50 1 1 I
X O6 15 400 -200 200 L 50 50 1 1 O
X O1 2 400 300 200 L 50 50 1 1 O
X I1 3 -400 300 200 R 50 50 1 1 I
X O2 4 400 200 200 L 50 50 1 1 O
X I2 5 -400 200 200 R 50 50 1 1 I
X O3 6 400 100 200 L 50 50 1 1 O
X I3 7 -400 100 200 R 50 50 1 1 I
X GND 8 -400 -300 200 R 50 50 1 1 W
X I4 9 -400 0 200 R 50 50 1 1 I
ENDDRAW
ENDDEF
#
# D_Schottky_x2_ACom_AKK
#
DEF D_Schottky_x2_ACom_AKK D 0 30 Y N 1 F N
F0 "D" 50 -100 50 H V C CNN
F1 "D_Schottky_x2_ACom_AKK" 0 100 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
DRAW
P 2 0 1 0 -140 0 150 0 N
P 2 0 1 0 0 0 0 -100 N
P 3 0 1 8 -150 50 -150 -50 -150 -50 N
P 3 0 1 8 150 50 150 -50 150 -50 N
P 4 0 1 8 -150 50 -170 50 -170 40 -170 40 N
P 4 0 1 8 150 -50 170 -50 170 -40 170 -40 N
P 4 0 1 8 150 50 130 50 130 40 130 40 N
P 5 0 1 8 -130 -40 -130 -50 -150 -50 -150 -50 -150 -50 N
P 6 0 1 8 -50 -50 -150 0 -50 50 -50 -50 -50 -50 -50 -50 N
P 6 0 1 8 50 50 150 0 50 -50 50 50 50 50 50 50 N
X A 1 0 -200 100 U 50 50 0 1 P
X K 2 -300 0 150 R 50 50 0 1 P
X K 3 300 0 150 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# IRF9310
#
DEF IRF9310 Q 0 0 Y N 1 F N
F0 "Q" 200 50 50 H V L CNN
F1 "IRF9310" 200 -50 50 H V L CNN
F2 "Package_SO:SO-8_3.9x4.9mm_P1.27mm" 200 100 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
C 65 0 111 0 1 10 N
C 100 -70 11 0 1 0 F
C 100 70 11 0 1 0 F
P 2 0 1 0 2 0 10 0 N
P 2 0 1 0 30 -70 100 -70 N
P 2 0 1 10 30 -50 30 -90 N
P 2 0 1 0 30 0 100 0 N
P 2 0 1 10 30 20 30 -20 N
P 2 0 1 0 30 70 100 70 N
P 2 0 1 10 30 90 30 50 N
P 2 0 1 0 100 -70 100 -100 N
P 2 0 1 0 100 -70 100 0 N
P 2 0 1 0 100 100 100 70 N
P 3 0 1 10 10 75 10 -75 10 -75 N
P 4 0 1 0 90 0 50 -15 50 15 90 0 F
P 4 0 1 0 100 -70 130 -70 130 70 100 70 N
P 4 0 1 0 110 -20 115 -15 145 -15 150 -10 N
P 4 0 1 0 130 -15 115 10 145 10 130 -15 N
X S 1 100 -200 100 U 50 50 1 1 P N
X S 2 100 -200 100 U 50 50 1 1 P N
X S 3 100 -200 100 U 50 50 1 1 P
X G 4 -200 0 200 R 50 50 1 1 I
X D 5 100 200 100 D 50 50 1 1 P
X D 6 100 200 100 D 50 50 1 1 P N
X D 7 100 200 100 D 50 50 1 1 P N
X D 8 100 200 100 D 50 50 1 1 P N
ENDDRAW
ENDDEF
#
# LM1117-ADJ
#
DEF LM1117-ADJ U 0 30 Y Y 1 F N
F0 "U" 100 -250 50 H V C CNN
F1 "LM1117-ADJ" 0 250 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
ALIAS LM1117-1.8 LM1117-2.5 LM1117-3.3 LM1117-5.0
$FPLIST
SOT-223*
TO-263*
TO-252*
$ENDFPLIST
DRAW
S -200 -200 200 200 0 1 10 f
X GND/ADJ 1 0 -300 100 U 50 50 1 1 W
X VO 2 300 0 100 L 50 50 1 1 w
X VI 3 -300 0 100 R 50 50 1 1 W
ENDDRAW
ENDDEF
#
# PESD1CAN
#
DEF PESD1CAN D 0 30 Y N 1 F N
F0 "D" 0 -350 50 H V C CNN
F1 "PESD1CAN" 50 150 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
$FPLIST
SOT23
$ENDFPLIST
DRAW
S -200 100 300 -300 0 1 0 N
P 2 0 1 0 -140 -200 150 -200 N
P 2 0 1 0 -140 0 150 0 N
P 3 0 1 8 -150 -150 -150 -250 -150 -250 N
P 3 0 1 8 -150 50 -150 -50 -150 -50 N
P 3 0 1 8 150 -150 150 -250 150 -250 N
P 3 0 1 8 150 50 150 -50 150 -50 N
P 4 0 1 8 -150 -150 -170 -150 -170 -160 -170 -160 N
P 4 0 1 8 -150 50 -170 50 -170 40 -170 40 N
P 4 0 1 8 150 -250 170 -250 170 -240 170 -240 N
P 4 0 1 8 150 -150 130 -150 130 -160 130 -160 N
P 4 0 1 8 150 -50 170 -50 170 -40 170 -40 N
P 4 0 1 0 150 0 250 0 250 -200 150 -200 N
P 4 0 1 8 150 50 130 50 130 40 130 40 N
P 5 0 1 8 -130 -240 -130 -250 -150 -250 -150 -250 -150 -250 N
P 5 0 1 8 -130 -40 -130 -50 -150 -50 -150 -50 -150 -50 N
P 6 0 1 8 -50 -250 -150 -200 -50 -150 -50 -250 -50 -250 -50 -250 N
P 6 0 1 8 -50 -50 -150 0 -50 50 -50 -50 -50 -50 -50 -50 N
P 6 0 1 8 50 -150 150 -200 50 -250 50 -150 50 -150 50 -150 N
P 6 0 1 8 50 50 150 0 50 -50 50 50 50 50 50 50 N
X K 1 -300 0 150 R 50 50 0 1 P
X K 2 -300 -200 150 R 50 50 0 1 P
X O 3 400 -100 150 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# TPS2051
#
DEF TPS2051 U 0 40 Y Y 1 F N
F0 "U" 0 -300 60 H V C CNN
F1 "TPS2051" 0 300 60 H V C CNN
F2 "" 0 0 60 H I C CNN
F3 "" 0 0 60 H I C CNN
DRAW
S -250 250 250 -250 0 1 0 N
X GND 1 -450 150 200 R 50 50 1 1 W
X IN 2 -450 50 200 R 50 50 1 1 W
X IN 3 -450 -50 200 R 50 50 1 1 P
X EN 4 -450 -150 200 R 50 50 1 1 I
X ~OC 5 450 -150 200 L 50 50 1 1 O
X OUT 6 450 -50 200 L 50 50 1 1 P
X OUT 7 450 50 200 L 50 50 1 1 P
X OUT 8 450 150 200 L 50 50 1 1 w
ENDDRAW
ENDDEF
#
# USB6B1
#
DEF USB6B1 D 0 30 Y N 1 F N
F0 "D" 0 -450 50 H V C CNN
F1 "USB6B1" 0 400 50 H V C CNN
F2 "" 200 -100 50 V V C CNN
F3 "" 200 -100 50 V V C CNN
$FPLIST
SO8
$ENDFPLIST
DRAW
C -150 -300 7 0 1 0 N
C -150 100 7 0 1 0 N
C -150 300 7 0 1 0 N
C 0 -300 7 0 1 0 N
C 0 -100 7 0 1 0 N
C 0 300 7 0 1 0 N
C 200 -300 7 0 1 0 N
C 200 300 7 0 1 0 N
S -300 -100 300 -100 0 1 0 N
S -300 300 300 300 0 1 0 N
S -200 -150 -100 -150 0 1 0 N
S -200 250 -100 250 0 1 0 N
S -150 300 -150 -300 0 1 0 N
S -50 -150 50 -150 0 1 0 N
S -50 250 50 250 0 1 0 N
S 0 300 0 -300 0 1 0 N
S 200 300 200 -300 0 1 0 N
S 300 -300 -300 -300 0 1 0 N
S 300 100 -300 100 0 1 0 N
P 3 0 1 8 150 50 250 50 250 50 N
P 4 0 1 8 150 50 150 30 160 30 160 30 N
P 4 0 1 8 250 50 250 70 240 70 240 70 N
P 5 0 1 0 -250 350 300 350 300 -350 -250 -350 -250 350 N
P 6 0 1 8 -200 -250 -150 -150 -100 -250 -200 -250 -200 -250 -200 -250 N
P 6 0 1 8 -200 150 -150 250 -100 150 -200 150 -200 150 -200 150 N
P 6 0 1 8 -50 -250 0 -150 50 -250 -50 -250 -50 -250 -50 -250 N
P 6 0 1 8 -50 150 0 250 50 150 -50 150 -50 150 -50 150 N
P 6 0 1 8 150 -50 200 50 250 -50 150 -50 150 -50 150 -50 N
X VCC 1 -500 300 200 R 50 50 1 1 P
X I/O1 2 -500 100 200 R 50 50 1 1 P
X I/O2 3 -500 -100 200 R 50 50 1 1 P
X GND 4 -500 -300 200 R 50 50 1 1 P
X GND 5 500 -300 200 L 50 50 1 1 P
X I/O2 6 500 -100 200 L 50 50 1 1 P
X I/O1 7 500 100 200 L 50 50 1 1 P
X VCC 8 500 300 200 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
#End Library

View File

@@ -0,0 +1,148 @@
32493563391627
Jumper
SolderJumper-2_P1.3mm_Bridged2Bar_Pad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm Pads, 0.3mm gap, bridged with 2 copper strips
solder jumper open
0
2
2
Jumper
SolderJumper-2_P1.3mm_Bridged2Bar_RoundedPad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 2 copper strips
solder jumper open
0
2
2
Jumper
SolderJumper-2_P1.3mm_Bridged_Pad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm Pads, 0.3mm gap, bridged with 1 copper strip
solder jumper open
0
2
2
Jumper
SolderJumper-2_P1.3mm_Bridged_RoundedPad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip
solder jumper open
0
2
2
Jumper
SolderJumper-2_P1.3mm_Open_Pad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm Pads, 0.3mm gap, open
solder jumper open
0
2
2
Jumper
SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, open
solder jumper open
0
2
2
Jumper
SolderJumper-2_P1.3mm_Open_TrianglePad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm Triangular Pads, 0.3mm gap, open
solder jumper open
0
2
2
Jumper
SolderJumper-3_P1.3mm_Bridged2Bar12_Pad1.0x1.5mm
SMD Solder 3-pad Jumper, 1x1.5mm Pads, 0.3mm gap, pads 1-2 Bridged2Bar with 2 copper strip
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged2Bar12_Pad1.0x1.5mm_NumberLabels
SMD Solder Jumper, 1x1.5mm Pads, 0.3mm gap, pads 1-2 Bridged2Bar with 2 copper strip, labeled with numbers
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged2Bar12_RoundedPad1.0x1.5mm
SMD Solder 3-pad Jumper, 1x1.5mm rounded Pads, 0.3mm gap, pads 1-2 Bridged2Bar with 2 copper strip
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged2Bar12_RoundedPad1.0x1.5mm_NumberLabels
SMD Solder 3-pad Jumper, 1x1.5mm rounded Pads, 0.3mm gap, pads 1-2 Bridged2Bar with 2 copper strip, labeled with numbers
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged12_Pad1.0x1.5mm
SMD Solder 3-pad Jumper, 1x1.5mm Pads, 0.3mm gap, pads 1-2 bridged with 1 copper strip
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged12_Pad1.0x1.5mm_NumberLabels
SMD Solder Jumper, 1x1.5mm Pads, 0.3mm gap, pads 1-2 bridged with 1 copper strip, labeled with numbers
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged12_RoundedPad1.0x1.5mm
SMD Solder 3-pad Jumper, 1x1.5mm rounded Pads, 0.3mm gap, pads 1-2 bridged with 1 copper strip
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Bridged12_RoundedPad1.0x1.5mm_NumberLabels
SMD Solder 3-pad Jumper, 1x1.5mm rounded Pads, 0.3mm gap, pads 1-2 bridged with 1 copper strip, labeled with numbers
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Open_Pad1.0x1.5mm
SMD Solder 3-pad Jumper, 1x1.5mm Pads, 0.3mm gap, open
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Open_Pad1.0x1.5mm_NumberLabels
SMD Solder Jumper, 1x1.5mm Pads, 0.3mm gap, open, labeled with numbers
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Open_RoundedPad1.0x1.5mm
SMD Solder 3-pad Jumper, 1x1.5mm rounded Pads, 0.3mm gap, open
solder jumper open
0
3
3
Jumper
SolderJumper-3_P1.3mm_Open_RoundedPad1.0x1.5mm_NumberLabels
SMD Solder 3-pad Jumper, 1x1.5mm rounded Pads, 0.3mm gap, open, labeled with numbers
solder jumper open
0
3
3
Jumper
SolderJumper-3_P2.0mm_Open_TrianglePad1.0x1.5mm
SMD Solder Jumper, 1x1.5mm Triangular Pads, 0.3mm gap, open
solder jumper open
0
5
3
Jumper
SolderJumper-3_P2.0mm_Open_TrianglePad1.0x1.5mm_NumberLabels
SMD Solder Jumper, 1x1.5mm Triangular Pads, 0.3mm gap, open, labeled with numbers
solder jumper open
0
5
3

View File

@@ -0,0 +1,3 @@
(fp_lib_table
(lib (name my_footprints)(type KiCad)(uri ${KIPRJMOD}/my_footprints.pretty)(options "")(descr ""))
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,709 @@
%TF.GenerationSoftware,KiCad,Pcbnew,5.1.10*%
%TF.CreationDate,2021-10-03T18:13:03+03:00*%
%TF.ProjectId,stm32,73746d33-322e-46b6-9963-61645f706362,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Paste,Bot*%
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.1.10) date 2021-10-03 18:13:03*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 APERTURE END LIST*
%TO.C,C2*%
G36*
G01*
X94549800Y-116556800D02*
X94549800Y-116081800D01*
G75*
G02*
X94787300Y-115844300I237500J0D01*
G01*
X95362300Y-115844300D01*
G75*
G02*
X95599800Y-116081800I0J-237500D01*
G01*
X95599800Y-116556800D01*
G75*
G02*
X95362300Y-116794300I-237500J0D01*
G01*
X94787300Y-116794300D01*
G75*
G02*
X94549800Y-116556800I0J237500D01*
G01*
G37*
G36*
G01*
X96299800Y-116556800D02*
X96299800Y-116081800D01*
G75*
G02*
X96537300Y-115844300I237500J0D01*
G01*
X97112300Y-115844300D01*
G75*
G02*
X97349800Y-116081800I0J-237500D01*
G01*
X97349800Y-116556800D01*
G75*
G02*
X97112300Y-116794300I-237500J0D01*
G01*
X96537300Y-116794300D01*
G75*
G02*
X96299800Y-116556800I0J237500D01*
G01*
G37*
%TD*%
%TO.C,C3*%
G36*
G01*
X90570600Y-116081800D02*
X90570600Y-116556800D01*
G75*
G02*
X90333100Y-116794300I-237500J0D01*
G01*
X89758100Y-116794300D01*
G75*
G02*
X89520600Y-116556800I0J237500D01*
G01*
X89520600Y-116081800D01*
G75*
G02*
X89758100Y-115844300I237500J0D01*
G01*
X90333100Y-115844300D01*
G75*
G02*
X90570600Y-116081800I0J-237500D01*
G01*
G37*
G36*
G01*
X92320600Y-116081800D02*
X92320600Y-116556800D01*
G75*
G02*
X92083100Y-116794300I-237500J0D01*
G01*
X91508100Y-116794300D01*
G75*
G02*
X91270600Y-116556800I0J237500D01*
G01*
X91270600Y-116081800D01*
G75*
G02*
X91508100Y-115844300I237500J0D01*
G01*
X92083100Y-115844300D01*
G75*
G02*
X92320600Y-116081800I0J-237500D01*
G01*
G37*
%TD*%
%TO.C,C13*%
G36*
G01*
X84414801Y-108348400D02*
X82564799Y-108348400D01*
G75*
G02*
X82314800Y-108098401I0J249999D01*
G01*
X82314800Y-106348399D01*
G75*
G02*
X82564799Y-106098400I249999J0D01*
G01*
X84414801Y-106098400D01*
G75*
G02*
X84664800Y-106348399I0J-249999D01*
G01*
X84664800Y-108098401D01*
G75*
G02*
X84414801Y-108348400I-249999J0D01*
G01*
G37*
G36*
G01*
X84414801Y-103248400D02*
X82564799Y-103248400D01*
G75*
G02*
X82314800Y-102998401I0J249999D01*
G01*
X82314800Y-101248399D01*
G75*
G02*
X82564799Y-100998400I249999J0D01*
G01*
X84414801Y-100998400D01*
G75*
G02*
X84664800Y-101248399I0J-249999D01*
G01*
X84664800Y-102998401D01*
G75*
G02*
X84414801Y-103248400I-249999J0D01*
G01*
G37*
%TD*%
%TO.C,D1*%
G36*
G01*
X103819000Y-78529601D02*
X103819000Y-77629599D01*
G75*
G02*
X104068999Y-77379600I249999J0D01*
G01*
X104719001Y-77379600D01*
G75*
G02*
X104969000Y-77629599I0J-249999D01*
G01*
X104969000Y-78529601D01*
G75*
G02*
X104719001Y-78779600I-249999J0D01*
G01*
X104068999Y-78779600D01*
G75*
G02*
X103819000Y-78529601I0J249999D01*
G01*
G37*
G36*
G01*
X105869000Y-78529601D02*
X105869000Y-77629599D01*
G75*
G02*
X106118999Y-77379600I249999J0D01*
G01*
X106769001Y-77379600D01*
G75*
G02*
X107019000Y-77629599I0J-249999D01*
G01*
X107019000Y-78529601D01*
G75*
G02*
X106769001Y-78779600I-249999J0D01*
G01*
X106118999Y-78779600D01*
G75*
G02*
X105869000Y-78529601I0J249999D01*
G01*
G37*
%TD*%
%TO.C,D3*%
G36*
G01*
X103819000Y-82263401D02*
X103819000Y-81363399D01*
G75*
G02*
X104068999Y-81113400I249999J0D01*
G01*
X104719001Y-81113400D01*
G75*
G02*
X104969000Y-81363399I0J-249999D01*
G01*
X104969000Y-82263401D01*
G75*
G02*
X104719001Y-82513400I-249999J0D01*
G01*
X104068999Y-82513400D01*
G75*
G02*
X103819000Y-82263401I0J249999D01*
G01*
G37*
G36*
G01*
X105869000Y-82263401D02*
X105869000Y-81363399D01*
G75*
G02*
X106118999Y-81113400I249999J0D01*
G01*
X106769001Y-81113400D01*
G75*
G02*
X107019000Y-81363399I0J-249999D01*
G01*
X107019000Y-82263401D01*
G75*
G02*
X106769001Y-82513400I-249999J0D01*
G01*
X106118999Y-82513400D01*
G75*
G02*
X105869000Y-82263401I0J249999D01*
G01*
G37*
%TD*%
%TO.C,D4*%
G36*
G01*
X96554600Y-114800801D02*
X96554600Y-113900799D01*
G75*
G02*
X96804599Y-113650800I249999J0D01*
G01*
X97454601Y-113650800D01*
G75*
G02*
X97704600Y-113900799I0J-249999D01*
G01*
X97704600Y-114800801D01*
G75*
G02*
X97454601Y-115050800I-249999J0D01*
G01*
X96804599Y-115050800D01*
G75*
G02*
X96554600Y-114800801I0J249999D01*
G01*
G37*
G36*
G01*
X94504600Y-114800801D02*
X94504600Y-113900799D01*
G75*
G02*
X94754599Y-113650800I249999J0D01*
G01*
X95404601Y-113650800D01*
G75*
G02*
X95654600Y-113900799I0J-249999D01*
G01*
X95654600Y-114800801D01*
G75*
G02*
X95404601Y-115050800I-249999J0D01*
G01*
X94754599Y-115050800D01*
G75*
G02*
X94504600Y-114800801I0J249999D01*
G01*
G37*
%TD*%
%TO.C,D6*%
G36*
G01*
X90338600Y-113900799D02*
X90338600Y-114800801D01*
G75*
G02*
X90088601Y-115050800I-249999J0D01*
G01*
X89438599Y-115050800D01*
G75*
G02*
X89188600Y-114800801I0J249999D01*
G01*
X89188600Y-113900799D01*
G75*
G02*
X89438599Y-113650800I249999J0D01*
G01*
X90088601Y-113650800D01*
G75*
G02*
X90338600Y-113900799I0J-249999D01*
G01*
G37*
G36*
G01*
X92388600Y-113900799D02*
X92388600Y-114800801D01*
G75*
G02*
X92138601Y-115050800I-249999J0D01*
G01*
X91488599Y-115050800D01*
G75*
G02*
X91238600Y-114800801I0J249999D01*
G01*
X91238600Y-113900799D01*
G75*
G02*
X91488599Y-113650800I249999J0D01*
G01*
X92138601Y-113650800D01*
G75*
G02*
X92388600Y-113900799I0J-249999D01*
G01*
G37*
%TD*%
%TO.C,R17*%
G36*
G01*
X108525300Y-96071200D02*
X109000300Y-96071200D01*
G75*
G02*
X109237800Y-96308700I0J-237500D01*
G01*
X109237800Y-96883700D01*
G75*
G02*
X109000300Y-97121200I-237500J0D01*
G01*
X108525300Y-97121200D01*
G75*
G02*
X108287800Y-96883700I0J237500D01*
G01*
X108287800Y-96308700D01*
G75*
G02*
X108525300Y-96071200I237500J0D01*
G01*
G37*
G36*
G01*
X108525300Y-97821200D02*
X109000300Y-97821200D01*
G75*
G02*
X109237800Y-98058700I0J-237500D01*
G01*
X109237800Y-98633700D01*
G75*
G02*
X109000300Y-98871200I-237500J0D01*
G01*
X108525300Y-98871200D01*
G75*
G02*
X108287800Y-98633700I0J237500D01*
G01*
X108287800Y-98058700D01*
G75*
G02*
X108525300Y-97821200I237500J0D01*
G01*
G37*
%TD*%
%TO.C,R3*%
G36*
G01*
X100908400Y-77842100D02*
X100908400Y-78317100D01*
G75*
G02*
X100670900Y-78554600I-237500J0D01*
G01*
X100095900Y-78554600D01*
G75*
G02*
X99858400Y-78317100I0J237500D01*
G01*
X99858400Y-77842100D01*
G75*
G02*
X100095900Y-77604600I237500J0D01*
G01*
X100670900Y-77604600D01*
G75*
G02*
X100908400Y-77842100I0J-237500D01*
G01*
G37*
G36*
G01*
X102658400Y-77842100D02*
X102658400Y-78317100D01*
G75*
G02*
X102420900Y-78554600I-237500J0D01*
G01*
X101845900Y-78554600D01*
G75*
G02*
X101608400Y-78317100I0J237500D01*
G01*
X101608400Y-77842100D01*
G75*
G02*
X101845900Y-77604600I237500J0D01*
G01*
X102420900Y-77604600D01*
G75*
G02*
X102658400Y-77842100I0J-237500D01*
G01*
G37*
%TD*%
%TO.C,R13*%
G36*
G01*
X102658400Y-81296500D02*
X102658400Y-81771500D01*
G75*
G02*
X102420900Y-82009000I-237500J0D01*
G01*
X101845900Y-82009000D01*
G75*
G02*
X101608400Y-81771500I0J237500D01*
G01*
X101608400Y-81296500D01*
G75*
G02*
X101845900Y-81059000I237500J0D01*
G01*
X102420900Y-81059000D01*
G75*
G02*
X102658400Y-81296500I0J-237500D01*
G01*
G37*
G36*
G01*
X100908400Y-81296500D02*
X100908400Y-81771500D01*
G75*
G02*
X100670900Y-82009000I-237500J0D01*
G01*
X100095900Y-82009000D01*
G75*
G02*
X99858400Y-81771500I0J237500D01*
G01*
X99858400Y-81296500D01*
G75*
G02*
X100095900Y-81059000I237500J0D01*
G01*
X100670900Y-81059000D01*
G75*
G02*
X100908400Y-81296500I0J-237500D01*
G01*
G37*
%TD*%
%TO.C,U1*%
G36*
G01*
X97444800Y-78780700D02*
X97444800Y-79105700D01*
G75*
G02*
X97282300Y-79268200I-162500J0D01*
G01*
X95257300Y-79268200D01*
G75*
G02*
X95094800Y-79105700I0J162500D01*
G01*
X95094800Y-78780700D01*
G75*
G02*
X95257300Y-78618200I162500J0D01*
G01*
X97282300Y-78618200D01*
G75*
G02*
X97444800Y-78780700I0J-162500D01*
G01*
G37*
G36*
G01*
X97444800Y-81320700D02*
X97444800Y-81645700D01*
G75*
G02*
X97282300Y-81808200I-162500J0D01*
G01*
X95257300Y-81808200D01*
G75*
G02*
X95094800Y-81645700I0J162500D01*
G01*
X95094800Y-81320700D01*
G75*
G02*
X95257300Y-81158200I162500J0D01*
G01*
X97282300Y-81158200D01*
G75*
G02*
X97444800Y-81320700I0J-162500D01*
G01*
G37*
G36*
G01*
X97444800Y-83860700D02*
X97444800Y-84185700D01*
G75*
G02*
X97282300Y-84348200I-162500J0D01*
G01*
X95257300Y-84348200D01*
G75*
G02*
X95094800Y-84185700I0J162500D01*
G01*
X95094800Y-83860700D01*
G75*
G02*
X95257300Y-83698200I162500J0D01*
G01*
X97282300Y-83698200D01*
G75*
G02*
X97444800Y-83860700I0J-162500D01*
G01*
G37*
G36*
G01*
X97444800Y-86400700D02*
X97444800Y-86725700D01*
G75*
G02*
X97282300Y-86888200I-162500J0D01*
G01*
X95257300Y-86888200D01*
G75*
G02*
X95094800Y-86725700I0J162500D01*
G01*
X95094800Y-86400700D01*
G75*
G02*
X95257300Y-86238200I162500J0D01*
G01*
X97282300Y-86238200D01*
G75*
G02*
X97444800Y-86400700I0J-162500D01*
G01*
G37*
G36*
G01*
X88394800Y-86400700D02*
X88394800Y-86725700D01*
G75*
G02*
X88232300Y-86888200I-162500J0D01*
G01*
X86207300Y-86888200D01*
G75*
G02*
X86044800Y-86725700I0J162500D01*
G01*
X86044800Y-86400700D01*
G75*
G02*
X86207300Y-86238200I162500J0D01*
G01*
X88232300Y-86238200D01*
G75*
G02*
X88394800Y-86400700I0J-162500D01*
G01*
G37*
G36*
G01*
X88394800Y-83860700D02*
X88394800Y-84185700D01*
G75*
G02*
X88232300Y-84348200I-162500J0D01*
G01*
X86207300Y-84348200D01*
G75*
G02*
X86044800Y-84185700I0J162500D01*
G01*
X86044800Y-83860700D01*
G75*
G02*
X86207300Y-83698200I162500J0D01*
G01*
X88232300Y-83698200D01*
G75*
G02*
X88394800Y-83860700I0J-162500D01*
G01*
G37*
G36*
G01*
X88394800Y-81320700D02*
X88394800Y-81645700D01*
G75*
G02*
X88232300Y-81808200I-162500J0D01*
G01*
X86207300Y-81808200D01*
G75*
G02*
X86044800Y-81645700I0J162500D01*
G01*
X86044800Y-81320700D01*
G75*
G02*
X86207300Y-81158200I162500J0D01*
G01*
X88232300Y-81158200D01*
G75*
G02*
X88394800Y-81320700I0J-162500D01*
G01*
G37*
G36*
G01*
X88394800Y-78780700D02*
X88394800Y-79105700D01*
G75*
G02*
X88232300Y-79268200I-162500J0D01*
G01*
X86207300Y-79268200D01*
G75*
G02*
X86044800Y-79105700I0J162500D01*
G01*
X86044800Y-78780700D01*
G75*
G02*
X86207300Y-78618200I162500J0D01*
G01*
X88232300Y-78618200D01*
G75*
G02*
X88394800Y-78780700I0J-162500D01*
G01*
G37*
%TD*%
M02*

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
%TF.GenerationSoftware,KiCad,Pcbnew,5.1.10*%
%TF.CreationDate,2021-10-03T18:13:03+03:00*%
%TF.ProjectId,stm32,73746d33-322e-46b6-9963-61645f706362,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Profile,NP*%
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.1.10) date 2021-10-03 18:13:03*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%TA.AperFunction,Profile*%
%ADD10C,0.150000*%
%TD*%
G04 APERTURE END LIST*
D10*
X92000000Y-88000000D02*
X92000000Y-71000000D01*
X91250000Y-88000000D02*
X92000000Y-88000000D01*
X91250000Y-71000000D02*
X91250000Y-88000000D01*
X92000000Y-71000000D02*
X91250000Y-71000000D01*
X83500000Y-136750000D02*
X82750000Y-136750000D01*
X83500000Y-126500000D02*
X83500000Y-136750000D01*
X79500000Y-122500000D02*
X83500000Y-126500000D01*
X79500000Y-115250000D02*
X79500000Y-122500000D01*
X78750000Y-115250000D02*
X79500000Y-115250000D01*
X78750000Y-123000000D02*
X78750000Y-115250000D01*
X82750000Y-127000000D02*
X78750000Y-123000000D01*
X82750000Y-136750000D02*
X82750000Y-127000000D01*
X73750000Y-111500000D02*
X73000000Y-111500000D01*
X73750000Y-105500000D02*
X73750000Y-111500000D01*
X71500000Y-103250000D02*
X73750000Y-105500000D01*
X69500000Y-103250000D02*
X71500000Y-103250000D01*
X67250000Y-105500000D02*
X69500000Y-103250000D01*
X67250000Y-105750000D02*
X67250000Y-105500000D01*
X67250000Y-111500000D02*
X67250000Y-105750000D01*
X68000000Y-111500000D02*
X67250000Y-111500000D01*
X71250000Y-104000000D02*
X69750000Y-104000000D01*
X73000000Y-105750000D02*
X71250000Y-104000000D01*
X73000000Y-111500000D02*
X73000000Y-105750000D01*
X68000000Y-105750000D02*
X69750000Y-104000000D01*
X68000000Y-111500000D02*
X68000000Y-105750000D01*
X61500000Y-69000000D02*
X61500000Y-138500000D01*
X158500000Y-69000000D02*
X61500000Y-69000000D01*
X158500000Y-138500000D02*
X158500000Y-69000000D01*
X61500000Y-138500000D02*
X158500000Y-138500000D01*
M02*

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,158 @@
%FSLAX45Y45*%
G04 Gerber Fmt 4.5, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.1.10) date 2021-10-03 17:53:52*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%TA.AperFunction,Profile*%
%ADD10C,0.150000*%
%TD*%
%ADD11C,0.200000*%
%ADD12C,0.300000*%
G04 APERTURE END LIST*
D10*
X9200000Y-8800000D02*
X9200000Y-7100000D01*
X9125000Y-8800000D02*
X9200000Y-8800000D01*
X9125000Y-7100000D02*
X9125000Y-8800000D01*
X9200000Y-7100000D02*
X9125000Y-7100000D01*
X8350000Y-13675000D02*
X8275000Y-13675000D01*
X8350000Y-12650000D02*
X8350000Y-13675000D01*
X7950000Y-12250000D02*
X8350000Y-12650000D01*
X7950000Y-11525000D02*
X7950000Y-12250000D01*
X7875000Y-11525000D02*
X7950000Y-11525000D01*
X7875000Y-12300000D02*
X7875000Y-11525000D01*
X8275000Y-12700000D02*
X7875000Y-12300000D01*
X8275000Y-13675000D02*
X8275000Y-12700000D01*
X7375000Y-11150000D02*
X7300000Y-11150000D01*
X7375000Y-10550000D02*
X7375000Y-11150000D01*
X7150000Y-10325000D02*
X7375000Y-10550000D01*
X6950000Y-10325000D02*
X7150000Y-10325000D01*
X6725000Y-10550000D02*
X6950000Y-10325000D01*
X6725000Y-10575000D02*
X6725000Y-10550000D01*
X6725000Y-11150000D02*
X6725000Y-10575000D01*
X6800000Y-11150000D02*
X6725000Y-11150000D01*
X7125000Y-10400000D02*
X6975000Y-10400000D01*
X7300000Y-10575000D02*
X7125000Y-10400000D01*
X7300000Y-11150000D02*
X7300000Y-10575000D01*
X6800000Y-10575000D02*
X6975000Y-10400000D01*
X6800000Y-11150000D02*
X6800000Y-10575000D01*
X6150000Y-6900000D02*
X6150000Y-13850000D01*
X15850000Y-6900000D02*
X6150000Y-6900000D01*
X15850000Y-13850000D02*
X15850000Y-6900000D01*
X6150000Y-13850000D02*
X15850000Y-13850000D01*
D11*
D12*
X6428928Y-14323214D02*
X6428928Y-14023214D01*
X6500357Y-14023214D01*
X6543214Y-14037500D01*
X6571786Y-14066071D01*
X6586071Y-14094643D01*
X6600357Y-14151786D01*
X6600357Y-14194643D01*
X6586071Y-14251786D01*
X6571786Y-14280357D01*
X6543214Y-14308929D01*
X6500357Y-14323214D01*
X6428928Y-14323214D01*
X6728928Y-14323214D02*
X6728928Y-14123214D01*
X6728928Y-14180357D02*
X6743214Y-14151786D01*
X6757500Y-14137500D01*
X6786071Y-14123214D01*
X6814643Y-14123214D01*
X6914643Y-14323214D02*
X6914643Y-14123214D01*
X6914643Y-14023214D02*
X6900357Y-14037500D01*
X6914643Y-14051786D01*
X6928928Y-14037500D01*
X6914643Y-14023214D01*
X6914643Y-14051786D01*
X7100357Y-14323214D02*
X7071786Y-14308929D01*
X7057500Y-14280357D01*
X7057500Y-14023214D01*
X7257500Y-14323214D02*
X7228928Y-14308929D01*
X7214643Y-14280357D01*
X7214643Y-14023214D01*
X7600357Y-14323214D02*
X7600357Y-14023214D01*
X7700357Y-14237500D01*
X7800357Y-14023214D01*
X7800357Y-14323214D01*
X8071786Y-14323214D02*
X8071786Y-14166071D01*
X8057500Y-14137500D01*
X8028928Y-14123214D01*
X7971786Y-14123214D01*
X7943214Y-14137500D01*
X8071786Y-14308929D02*
X8043214Y-14323214D01*
X7971786Y-14323214D01*
X7943214Y-14308929D01*
X7928928Y-14280357D01*
X7928928Y-14251786D01*
X7943214Y-14223214D01*
X7971786Y-14208929D01*
X8043214Y-14208929D01*
X8071786Y-14194643D01*
X8214643Y-14123214D02*
X8214643Y-14423214D01*
X8214643Y-14137500D02*
X8243214Y-14123214D01*
X8300357Y-14123214D01*
X8328928Y-14137500D01*
X8343214Y-14151786D01*
X8357500Y-14180357D01*
X8357500Y-14266071D01*
X8343214Y-14294643D01*
X8328928Y-14308929D01*
X8300357Y-14323214D01*
X8243214Y-14323214D01*
X8214643Y-14308929D01*
X8486071Y-14294643D02*
X8500357Y-14308929D01*
X8486071Y-14323214D01*
X8471786Y-14308929D01*
X8486071Y-14294643D01*
X8486071Y-14323214D01*
X8486071Y-14137500D02*
X8500357Y-14151786D01*
X8486071Y-14166071D01*
X8471786Y-14151786D01*
X8486071Y-14137500D01*
X8486071Y-14166071D01*
M02*

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
Drill report for /home/eddy/Yandex.Disk/Projects/stm32samples/F0-nolib/3steppersLB/kicad/stm32.kicad_pcb
Created on Пн 09 авг 2021 17:28:16
Copper Layer Stackup:
=============================================================
L1 : F.Cu front
L2 : B.Cu back
Drill file 'stm32.drl' contains
plated through holes:
=============================================================
T1 0.400mm 0.0157" (68 holes)
T2 0.600mm 0.0236" (29 holes)
T3 0.750mm 0.0295" (50 holes)
T4 0.800mm 0.0315" (12 holes)
T5 0.920mm 0.0362" (4 holes)
T6 1.000mm 0.0394" (8 holes)
T7 1.100mm 0.0433" (5 holes)
T8 1.300mm 0.0512" (15 holes)
T9 2.330mm 0.0917" (2 holes)
T10 3.000mm 0.1181" (4 holes)
Total plated holes count 197
Not plated through holes are merged with plated holes
unplated through holes:
=============================================================
Total unplated holes count 0

View File

@@ -0,0 +1,128 @@
{
"Header":
{
"GenerationSoftware":
{
"Vendor": "KiCad",
"Application": "Pcbnew",
"Version": "5.1.10"
},
"CreationDate": "2021-10-03T18:13:03+03:00"
},
"GeneralSpecs":
{
"ProjectId":
{
"Name": "stm32",
"GUID": "73746d33-322e-46b6-9963-61645f706362",
"Revision": "rev?"
},
"Size":
{
"X": 97.150,
"Y": 69.650
},
"LayerNumber": 2,
"BoardThickness": 2.500
},
"DesignRules":
[
{
"Layers": "Outer",
"PadToPad": 0.200,
"PadToTrack": 0.200,
"TrackToTrack": 0.200,
"MinLineWidth": 0.200,
"TrackToRegion": 0.508,
"RegionToRegion": 0.508
}
],
"FilesAttributes":
[
{
"Path": "stm32-F_Cu.gbr",
"FileFunction": "Copper,L1,Top",
"FilePolarity": "Positive"
},
{
"Path": "stm32-B_Cu.gbr",
"FileFunction": "Copper,L2,Bot",
"FilePolarity": "Positive"
},
{
"Path": "stm32-F_Paste.gbr",
"FileFunction": "SolderPaste,Top",
"FilePolarity": "Positive"
},
{
"Path": "stm32-B_Paste.gbr",
"FileFunction": "SolderPaste,Bot",
"FilePolarity": "Positive"
},
{
"Path": "stm32-F_SilkS.gbr",
"FileFunction": "Legend,Top",
"FilePolarity": "Positive"
},
{
"Path": "stm32-B_SilkS.gbr",
"FileFunction": "Legend,Bot",
"FilePolarity": "Positive"
},
{
"Path": "stm32-F_Mask.gbr",
"FileFunction": "SolderMask,Top",
"FilePolarity": "Negative"
},
{
"Path": "stm32-B_Mask.gbr",
"FileFunction": "SolderMask,Bot",
"FilePolarity": "Negative"
},
{
"Path": "stm32-Edge_Cuts.gbr",
"FileFunction": "Profile",
"FilePolarity": "Positive"
}
],
"MaterialStackup":
[
{
"Type": "Legend",
"Notes": "Layer F.SilkS"
},
{
"Type": "SolderPaste",
"Notes": "Layer F.Paste"
},
{
"Type": "SolderMask",
"Notes": "Layer F.Mask"
},
{
"Type": "Copper",
"Notes": "Layer F.Cu"
},
{
"Type": "Dielectric",
"Material": "FR4",
"Notes": "Layers L1/L2"
},
{
"Type": "Copper",
"Notes": "Layer B.Cu"
},
{
"Type": "SolderMask",
"Notes": "Layer B.Mask"
},
{
"Type": "SolderPaste",
"Notes": "Layer B.Paste"
},
{
"Type": "Legend",
"Notes": "Layer B.SilkS"
}
]
}

View File

@@ -0,0 +1,18 @@
(module B0x0xS (layer F.Cu) (tedit 5EC4EFC6)
(fp_text reference REF** (at 0.127 2.286) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value B0x0xS (at 0 -3.048) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -5.8 0.9) (end 5.8 0.9) (layer F.SilkS) (width 0.12))
(fp_line (start -5.8 -5.1) (end 5.8 -5.1) (layer F.SilkS) (width 0.12))
(fp_line (start -5.8 -5.1) (end -5.8 0.9) (layer F.SilkS) (width 0.12))
(fp_line (start 5.8 -5.1) (end 5.8 0.9) (layer F.SilkS) (width 0.12))
(fp_line (start -0.381 -5.334) (end -0.381 1.27) (layer F.SilkS) (width 0.15))
(fp_line (start 0.381 1.27) (end 0.381 -5.334) (layer F.SilkS) (width 0.15))
(pad 1 thru_hole circle (at -3.81 0) (size 1.5 1.5) (drill 0.8) (layers *.Cu *.Mask))
(pad 2 thru_hole circle (at -1.27 0) (size 1.5 1.5) (drill 0.8) (layers *.Cu *.Mask))
(pad 3 thru_hole circle (at 1.27 0) (size 1.5 1.5) (drill 0.8) (layers *.Cu *.Mask))
(pad 4 thru_hole circle (at 3.81 0) (size 1.5 1.5) (drill 0.8) (layers *.Cu *.Mask))
)

View File

@@ -0,0 +1,9 @@
(module Hole_3mm (layer F.Cu) (tedit 5913F6E4)
(fp_text reference REF** (at 0 3.81) (layer F.SilkS) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value Hole_3mm (at 0 -7.62) (layer F.Fab) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 thru_hole circle (at 0 0) (size 5 5) (drill 3) (layers *.Cu *.Mask))
)

View File

@@ -0,0 +1,801 @@
EESchema-LIBRARY Version 2.4
#encoding utf-8
#
# +3.3V
#
DEF +3.3V #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "+3.3V" 0 140 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 2 0 1 0 -30 50 0 100 N
P 2 0 1 0 0 0 0 100 N
P 2 0 1 0 0 100 30 50 N
X +3V3 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# +5V
#
DEF +5V #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -150 50 H I C CNN
F1 "+5V" 0 140 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 2 0 1 0 -30 50 0 100 N
P 2 0 1 0 0 0 0 100 N
P 2 0 1 0 0 100 30 50 N
X +5V 1 0 0 0 U 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# B0505S-elements
#
DEF B0505S-elements Q? 0 40 Y Y 1 F N
F0 "Q?" 0 250 50 H V C CNN
F1 "B0505S-elements" 0 -250 50 H V C CNN
F2 "my_footprints:B0x0xS" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
b0x0xs
$ENDFPLIST
DRAW
S -200 200 200 -200 0 1 0 N
X GND 1 -400 -100 200 R 50 50 1 1 W
X Vin 2 -400 100 200 R 50 50 1 1 W
X 0V 3 400 -100 200 L 50 50 1 1 w
X +Vo 4 400 100 200 L 50 50 1 1 w
ENDDRAW
ENDDEF
#
# C
#
DEF C C 0 10 N Y 1 F N
F0 "C" 25 100 50 H V L CNN
F1 "C" 25 -100 50 H V L CNN
F2 "" 38 -150 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
C_*
$ENDFPLIST
DRAW
P 2 0 1 20 -80 -30 80 -30 N
P 2 0 1 20 -80 30 80 30 N
X ~ 1 0 150 110 D 50 50 1 1 P
X ~ 2 0 -150 110 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# CONN_01X01
#
DEF CONN_01X01 J 0 40 Y N 1 F N
F0 "J" 0 100 50 H V C CNN
F1 "CONN_01X01" 100 0 50 V V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Pin_Header_Straight_1X*
Pin_Header_Angled_1X*
Socket_Strip_Straight_1X*
Socket_Strip_Angled_1X*
$ENDFPLIST
DRAW
S -50 5 10 -5 0 1 0 N
S -50 50 50 -50 0 1 0 N
X P1 1 -200 0 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# CONN_01X03
#
DEF CONN_01X03 J 0 40 Y N 1 F N
F0 "J" 0 200 50 H V C CNN
F1 "CONN_01X03" 100 0 50 V V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Pin_Header_Straight_1X*
Pin_Header_Angled_1X*
Socket_Strip_Straight_1X*
Socket_Strip_Angled_1X*
$ENDFPLIST
DRAW
S -50 -95 10 -105 0 1 0 N
S -50 5 10 -5 0 1 0 N
S -50 105 10 95 0 1 0 N
S -50 150 50 -150 0 1 0 N
X P1 1 -200 100 150 R 50 50 1 1 P
X P2 2 -200 0 150 R 50 50 1 1 P
X P3 3 -200 -100 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# CONN_02X03
#
DEF CONN_02X03 J 0 1 Y N 1 F N
F0 "J" 0 200 50 H V C CNN
F1 "CONN_02X03" 0 -200 50 H V C CNN
F2 "" 0 -1200 50 H I C CNN
F3 "" 0 -1200 50 H I C CNN
$FPLIST
Pin_Header_Straight_2X*
Pin_Header_Angled_2X*
Socket_Strip_Straight_2X*
Socket_Strip_Angled_2X*
IDC_Header_Straight_*
$ENDFPLIST
DRAW
S -100 -95 -50 -105 0 1 0 N
S -100 5 -50 -5 0 1 0 N
S -100 105 -50 95 0 1 0 N
S -100 150 100 -150 0 1 0 N
S 50 -95 100 -105 0 1 0 N
S 50 5 100 -5 0 1 0 N
S 50 105 100 95 0 1 0 N
X P1 1 -250 100 150 R 50 50 1 1 P
X P2 2 250 100 150 L 50 50 1 1 P
X P3 3 -250 0 150 R 50 50 1 1 P
X P4 4 250 0 150 L 50 50 1 1 P
X P5 5 -250 -100 150 R 50 50 1 1 P
X P6 6 250 -100 150 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# CP
#
DEF CP C 0 10 N Y 1 F N
F0 "C" 25 100 50 H V L CNN
F1 "CP" 25 -100 50 H V L CNN
F2 "" 38 -150 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
CP_*
$ENDFPLIST
DRAW
S -90 20 -90 40 0 1 0 N
S -90 20 90 20 0 1 0 N
S 90 -20 -90 -40 0 1 0 F
S 90 40 -90 40 0 1 0 N
S 90 40 90 20 0 1 0 N
P 2 0 1 0 -70 90 -30 90 N
P 2 0 1 0 -50 110 -50 70 N
X ~ 1 0 150 110 D 50 50 1 1 P
X ~ 2 0 -150 110 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Conn_01x01
#
DEF Conn_01x01 J 0 40 Y N 1 F N
F0 "J" 0 100 50 H V C CNN
F1 "Conn_01x01" 0 -100 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Connector*:*_??x*mm*
Connector*:*1x??x*mm*
Pin?Header?Straight?1X*
Pin?Header?Angled?1X*
Socket?Strip?Straight?1X*
Socket?Strip?Angled?1X*
$ENDFPLIST
DRAW
S -50 5 0 -5 1 1 6 N
S -50 50 50 -50 1 1 10 f
X Pin_1 1 -200 0 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Conn_01x02
#
DEF Conn_01x02 J 0 40 Y N 1 F N
F0 "J" 0 100 50 H V C CNN
F1 "Conn_01x02" 0 -200 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Connector*:*_??x*mm*
Connector*:*1x??x*mm*
Pin?Header?Straight?1X*
Pin?Header?Angled?1X*
Socket?Strip?Straight?1X*
Socket?Strip?Angled?1X*
$ENDFPLIST
DRAW
S -50 -95 0 -105 1 1 6 N
S -50 5 0 -5 1 1 6 N
S -50 50 50 -150 1 1 10 f
X Pin_1 1 -200 0 150 R 50 50 1 1 P
X Pin_2 2 -200 -100 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Conn_01x07
#
DEF Conn_01x07 J 0 40 Y N 1 F N
F0 "J" 0 400 50 H V C CNN
F1 "Conn_01x07" 0 -400 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
Connector*:*_??x*mm*
Connector*:*1x??x*mm*
Pin?Header?Straight?1X*
Pin?Header?Angled?1X*
Socket?Strip?Straight?1X*
Socket?Strip?Angled?1X*
$ENDFPLIST
DRAW
S -50 -295 0 -305 1 1 6 N
S -50 -195 0 -205 1 1 6 N
S -50 -95 0 -105 1 1 6 N
S -50 5 0 -5 1 1 6 N
S -50 105 0 95 1 1 6 N
S -50 205 0 195 1 1 6 N
S -50 305 0 295 1 1 6 N
S -50 350 50 -350 1 1 10 f
X Pin_1 1 -200 300 150 R 50 50 1 1 P
X Pin_2 2 -200 200 150 R 50 50 1 1 P
X Pin_3 3 -200 100 150 R 50 50 1 1 P
X Pin_4 4 -200 0 150 R 50 50 1 1 P
X Pin_5 5 -200 -100 150 R 50 50 1 1 P
X Pin_6 6 -200 -200 150 R 50 50 1 1 P
X Pin_7 7 -200 -300 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# DB9_Female
#
DEF DB9_Female J 0 40 Y N 1 F N
F0 "J" 0 550 50 H V C CNN
F1 "DB9_Female" 0 -575 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
DB*F*
$ENDFPLIST
DRAW
C -70 -400 30 0 1 0 N
C -70 -200 30 0 1 0 N
C -70 0 30 0 1 0 N
C -70 200 30 0 1 0 N
C -70 400 30 0 1 0 N
C 50 -300 30 0 1 0 N
C 50 -100 30 0 1 0 N
C 50 100 30 0 1 0 N
C 50 300 30 0 1 0 N
P 2 0 1 0 -150 -400 -100 -400 N
P 2 0 1 0 -150 -300 20 -300 N
P 2 0 1 0 -150 -200 -100 -200 N
P 2 0 1 0 -150 -100 20 -100 N
P 2 0 1 0 -150 0 -100 0 N
P 2 0 1 0 -150 100 20 100 N
P 2 0 1 0 -150 200 -100 200 N
P 2 0 1 0 -150 300 20 300 N
P 2 0 1 0 -150 400 -100 400 N
P 5 0 1 10 -150 525 -150 -525 150 -375 150 375 -150 525 f
X 1 1 -300 400 150 R 50 50 1 1 P
X 2 2 -300 200 150 R 50 50 1 1 P
X 3 3 -300 0 150 R 50 50 1 1 P
X 4 4 -300 -200 150 R 50 50 1 1 P
X 5 5 -300 -400 150 R 50 50 1 1 P
X 6 6 -300 300 150 R 50 50 1 1 P
X 7 7 -300 100 150 R 50 50 1 1 P
X 8 8 -300 -100 150 R 50 50 1 1 P
X 9 9 -300 -300 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# DB9_Male
#
DEF DB9_Male J 0 40 Y N 1 F N
F0 "J" 0 550 50 H V C CNN
F1 "DB9_Male" 0 -575 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
DB*M*
$ENDFPLIST
DRAW
C -70 -400 30 0 1 0 F
C -70 -200 30 0 1 0 F
C -70 0 30 0 1 0 F
C -70 200 30 0 1 0 F
C -70 400 30 0 1 0 F
C 50 -300 30 0 1 0 F
C 50 -100 30 0 1 0 F
C 50 100 30 0 1 0 F
C 50 300 30 0 1 0 F
P 2 0 1 0 -150 -400 -100 -400 N
P 2 0 1 0 -150 -300 20 -300 N
P 2 0 1 0 -150 -200 -100 -200 N
P 2 0 1 0 -150 -100 20 -100 N
P 2 0 1 0 -150 0 -100 0 N
P 2 0 1 0 -150 100 20 100 N
P 2 0 1 0 -150 200 -100 200 N
P 2 0 1 0 -150 300 20 300 N
P 2 0 1 0 -150 400 -100 400 N
P 5 0 1 10 -150 -525 -150 525 150 375 150 -375 -150 -525 f
X 1 1 -300 -400 150 R 50 50 1 1 P
X 2 2 -300 -200 150 R 50 50 1 1 P
X 3 3 -300 0 150 R 50 50 1 1 P
X 4 4 -300 200 150 R 50 50 1 1 P
X 5 5 -300 400 150 R 50 50 1 1 P
X 6 6 -300 -300 150 R 50 50 1 1 P
X 7 7 -300 -100 150 R 50 50 1 1 P
X 8 8 -300 100 150 R 50 50 1 1 P
X 9 9 -300 300 150 R 50 50 1 1 P
ENDDRAW
ENDDEF
#
# D_Schottky
#
DEF D_Schottky D 0 40 N N 1 F N
F0 "D" 0 100 50 H V C CNN
F1 "D_Schottky" 0 -100 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
TO-???*
*SingleDiode
*_Diode_*
*SingleDiode*
D_*
$ENDFPLIST
DRAW
P 2 0 1 0 50 0 -50 0 N
P 4 0 1 8 50 50 50 -50 -50 0 50 50 N
P 6 0 1 8 -75 25 -75 50 -50 50 -50 -50 -25 -50 -25 -25 N
X K 1 -150 0 100 R 50 50 1 1 P
X A 2 150 0 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# D_Zener
#
DEF D_Zener D 0 40 N N 1 F N
F0 "D" 0 100 50 H V C CNN
F1 "D_Zener" 0 -100 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
TO-???*
*SingleDiode
*_Diode_*
*SingleDiode*
D_*
$ENDFPLIST
DRAW
P 2 0 1 0 50 0 -50 0 N
P 3 0 1 8 -50 -50 -50 50 -30 50 N
P 4 0 1 8 50 -50 50 50 -50 0 50 -50 N
X K 1 -150 0 100 R 50 50 1 1 P
X A 2 150 0 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# GND
#
DEF GND #PWR 0 0 Y Y 1 F P
F0 "#PWR" 0 -250 50 H I C CNN
F1 "GND" 0 -150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
X GND 1 0 0 0 D 50 50 1 1 W N
ENDDRAW
ENDDEF
#
# Jumper_NO_Small
#
DEF Jumper_NO_Small JP 0 30 N N 1 F N
F0 "JP" 0 80 50 H V C CNN
F1 "Jumper_NO_Small" 10 -60 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
C -40 0 20 0 1 0 N
C 40 0 20 0 1 0 N
X 1 1 -100 0 40 R 50 50 0 1 P
X 2 2 100 0 40 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# LED-RESCUE-stm32
#
DEF LED-RESCUE-stm32 D 0 40 Y N 1 F N
F0 "D" 0 100 50 H V C CNN
F1 "LED-RESCUE-stm32" 0 -100 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
$FPLIST
LED*
$ENDFPLIST
DRAW
P 2 0 1 8 -50 -50 -50 50 N
P 2 0 1 0 -50 0 50 0 N
P 4 0 1 8 50 -50 50 50 -50 0 50 -50 N
P 5 0 1 0 -120 -30 -180 -90 -150 -90 -180 -90 -180 -60 N
P 5 0 1 0 -70 -30 -130 -90 -100 -90 -130 -90 -130 -60 N
X K 1 -150 0 100 R 50 50 1 1 P
X A 2 150 0 100 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# LM1117-3.3-RESCUE-stm32
#
DEF LM1117-3.3-RESCUE-stm32 U 0 30 Y Y 1 F N
F0 "U" 100 -250 50 H V C CNN
F1 "LM1117-3.3-RESCUE-stm32" 0 250 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
SOT-223*
TO-263*
TO-252*
$ENDFPLIST
DRAW
S -200 -200 200 200 0 1 10 f
X GND/ADJ 1 0 -300 100 U 50 50 1 1 W
X VO 2 300 50 100 L 50 50 1 1 P
X VI 3 -300 0 100 R 50 50 1 1 W
X VO 4 300 -50 100 L 50 50 1 1 w
ENDDRAW
ENDDEF
#
# MAX471-RESCUE-stm32
#
DEF MAX471-RESCUE-stm32 U 0 40 Y Y 1 F N
F0 "U" -300 350 50 H V L CNN
F1 "MAX471-RESCUE-stm32" -300 -350 50 H V L CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
S -300 300 300 -300 0 1 10 f
X SHDN 1 -400 -100 100 R 50 50 1 1 I
X RS+ 2 -400 200 100 R 50 50 1 1 W
X RS+ 3 -400 100 100 R 50 50 1 1 P
X GND 4 -400 -200 100 R 50 50 1 1 W
X SIGN 5 400 -100 100 L 50 50 1 1 C
X RS- 6 400 200 100 L 50 50 1 1 w
X RS- 7 400 100 100 L 50 50 1 1 P
X OUT 8 400 -200 100 L 50 50 1 1 O
ENDDRAW
ENDDEF
#
# MCP2551-I_SN
#
DEF MCP2551-I_SN U 0 40 Y Y 1 F N
F0 "U" -400 350 50 H V L CNN
F1 "MCP2551-I_SN" 100 350 50 H V L CNN
F2 "Housings_SOIC:SOIC-8_3.9x4.9mm_Pitch1.27mm" 0 -500 50 H I C CIN
F3 "" 0 0 50 H I C CNN
$FPLIST
SOIC*Pitch1.27mm*
$ENDFPLIST
DRAW
S -400 300 400 -300 0 1 10 f
X TXD 1 -500 200 100 R 50 50 1 1 I
X VSS 2 0 -400 100 U 50 50 1 1 W
X VDD 3 0 400 100 D 50 50 1 1 W
X RXD 4 -500 100 100 R 50 50 1 1 O
X Vref 5 -500 -100 100 R 50 50 1 1 w
X CANL 6 500 -100 100 L 50 50 1 1 B
X CANH 7 500 100 100 L 50 50 1 1 B
X Rs 8 -500 -200 100 R 50 50 1 1 I
ENDDRAW
ENDDEF
#
# PESD1CAN-elements
#
DEF PESD1CAN-elements D 0 30 Y N 1 F N
F0 "D" 0 -350 50 H V C CNN
F1 "PESD1CAN-elements" 50 150 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
$FPLIST
SOT23
$ENDFPLIST
DRAW
S -200 100 300 -300 0 1 0 N
P 2 0 1 0 -140 -200 150 -200 N
P 2 0 1 0 -140 0 150 0 N
P 3 0 1 8 -150 -150 -150 -250 -150 -250 N
P 3 0 1 8 -150 50 -150 -50 -150 -50 N
P 3 0 1 8 150 -150 150 -250 150 -250 N
P 3 0 1 8 150 50 150 -50 150 -50 N
P 4 0 1 8 -150 -150 -170 -150 -170 -160 -170 -160 N
P 4 0 1 8 -150 50 -170 50 -170 40 -170 40 N
P 4 0 1 8 150 -250 170 -250 170 -240 170 -240 N
P 4 0 1 8 150 -150 130 -150 130 -160 130 -160 N
P 4 0 1 8 150 -50 170 -50 170 -40 170 -40 N
P 4 0 1 0 150 0 250 0 250 -200 150 -200 N
P 4 0 1 8 150 50 130 50 130 40 130 40 N
P 5 0 1 8 -130 -240 -130 -250 -150 -250 -150 -250 -150 -250 N
P 5 0 1 8 -130 -40 -130 -50 -150 -50 -150 -50 -150 -50 N
P 6 0 1 8 -50 -250 -150 -200 -50 -150 -50 -250 -50 -250 -50 -250 N
P 6 0 1 8 -50 -50 -150 0 -50 50 -50 -50 -50 -50 -50 -50 N
P 6 0 1 8 50 -150 150 -200 50 -250 50 -150 50 -150 50 -150 N
P 6 0 1 8 50 50 150 0 50 -50 50 50 50 50 50 50 N
X K 1 -300 0 150 R 50 50 0 1 P
X K 2 -300 -200 150 R 50 50 0 1 P
X O 3 400 -100 150 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# PWR_FLAG
#
DEF PWR_FLAG #FLG 0 0 N N 1 F P
F0 "#FLG" 0 75 50 H I C CNN
F1 "PWR_FLAG" 0 150 50 H V C CNN
F2 "" 0 0 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
P 6 0 1 0 0 0 0 50 -40 75 0 100 40 75 0 50 N
X pwr 1 0 0 0 U 50 50 0 0 w
ENDDRAW
ENDDEF
#
# Q_NMOS_GSD
#
DEF Q_NMOS_GSD Q 0 0 Y N 1 F N
F0 "Q" 200 50 50 H V L CNN
F1 "Q_NMOS_GSD" 200 -50 50 H V L CNN
F2 "" 200 100 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
C 65 0 111 0 1 10 N
C 100 -70 11 0 1 0 F
C 100 70 11 0 1 0 F
P 2 0 1 0 2 0 10 0 N
P 2 0 1 0 30 -70 100 -70 N
P 2 0 1 10 30 -50 30 -90 N
P 2 0 1 0 30 0 100 0 N
P 2 0 1 10 30 20 30 -20 N
P 2 0 1 0 30 70 100 70 N
P 2 0 1 10 30 90 30 50 N
P 2 0 1 0 100 -70 100 -100 N
P 2 0 1 0 100 -70 100 0 N
P 2 0 1 0 100 100 100 70 N
P 3 0 1 10 10 75 10 -75 10 -75 N
P 4 0 1 0 40 0 80 15 80 -15 40 0 F
P 4 0 1 0 100 -70 130 -70 130 70 100 70 N
P 4 0 1 0 110 20 115 15 145 15 150 10 N
P 4 0 1 0 130 15 115 -10 145 -10 130 15 N
X G 1 -200 0 200 R 50 50 1 1 I
X S 2 100 -200 100 U 50 50 1 1 P
X D 3 100 200 100 D 50 50 1 1 P
ENDDRAW
ENDDEF
#
# Q_PMOS_GSD
#
DEF Q_PMOS_GSD Q 0 0 Y N 1 F N
F0 "Q" 200 50 50 H V L CNN
F1 "Q_PMOS_GSD" 200 -50 50 H V L CNN
F2 "" 200 100 50 H I C CNN
F3 "" 0 0 50 H I C CNN
DRAW
C 65 0 111 0 1 10 N
C 100 -70 11 0 1 0 F
C 100 70 11 0 1 0 F
P 2 0 1 0 2 0 10 0 N
P 2 0 1 0 30 -70 100 -70 N
P 2 0 1 10 30 -50 30 -90 N
P 2 0 1 0 30 0 100 0 N
P 2 0 1 10 30 20 30 -20 N
P 2 0 1 0 30 70 100 70 N
P 2 0 1 10 30 90 30 50 N
P 2 0 1 0 100 -70 100 -100 N
P 2 0 1 0 100 -70 100 0 N
P 2 0 1 0 100 100 100 70 N
P 3 0 1 10 10 75 10 -75 10 -75 N
P 4 0 1 0 90 0 50 -15 50 15 90 0 F
P 4 0 1 0 100 -70 130 -70 130 70 100 70 N
P 4 0 1 0 110 -20 115 -15 145 -15 150 -10 N
P 4 0 1 0 130 -15 115 10 145 10 130 -15 N
X G 1 -200 0 200 R 50 50 1 1 I
X S 2 100 -200 100 U 50 50 1 1 P
X D 3 100 200 100 D 50 50 1 1 P
ENDDRAW
ENDDEF
#
# R
#
DEF R R 0 0 N Y 1 F N
F0 "R" 80 0 50 V V C CNN
F1 "R" 0 0 50 V V C CNN
F2 "" -70 0 50 V I C CNN
F3 "" 0 0 50 H I C CNN
$FPLIST
R_*
R_*
$ENDFPLIST
DRAW
S -40 -100 40 100 0 1 10 N
X ~ 1 0 150 50 D 50 50 1 1 P
X ~ 2 0 -150 50 U 50 50 1 1 P
ENDDRAW
ENDDEF
#
# SP0502BAHT
#
DEF SP0502BAHT D 0 40 Y N 1 F N
F0 "D" 225 100 50 H V L CNN
F1 "SP0502BAHT" 225 25 50 H V L CNN
F2 "TO_SOT_Packages_SMD:SOT-23" 225 -50 50 H I L CNN
F3 "" 125 125 50 H I C CNN
$FPLIST
SOT?23*
$ENDFPLIST
DRAW
S -175 100 175 -100 0 1 10 f
P 2 0 1 0 -100 100 -100 50 N
P 2 0 1 0 0 -50 0 -100 N
P 2 0 1 0 100 100 100 50 N
P 4 0 1 0 -150 75 -125 50 -75 50 -50 25 N
P 4 0 1 0 -100 0 -100 -50 100 -50 100 0 N
P 4 0 1 0 -100 50 -75 0 -125 0 -100 50 F
P 4 0 1 0 50 75 75 50 125 50 150 25 N
P 4 0 1 0 100 50 75 0 125 0 100 50 F
X A 3 0 -200 100 U 50 50 0 0 I
X K 1 -100 200 100 D 50 50 1 1 I
X K 2 100 200 100 D 50 50 1 1 I
ENDDRAW
ENDDEF
#
# STM32F042C6Tx
#
DEF STM32F042C6Tx U 0 40 Y Y 1 L N
F0 "U" -3000 1725 50 H V L BNN
F1 "STM32F042C6Tx" 3000 1725 50 H V R BNN
F2 "LQFP48" 3000 1675 50 H V R TNN
F3 "" 0 0 50 H V C CNN
DRAW
S -3000 -1700 3000 1700 0 1 10 f
X VBAT 1 -3100 1100 100 R 50 50 1 1 W
X ADC_IN0/RTC_TAMP2/SYS_WKUP1/TIM2_CH1/TIM2_ETR/TSC_G1_IO1/USART2_CTS/PA0 10 3100 100 100 L 50 50 1 1 B
X ADC_IN1/TIM2_CH2/TSC_G1_IO2/USART2_DE/USART2_RTS/PA1 11 3100 0 100 L 50 50 1 1 B
X ADC_IN2/SYS_WKUP4/TIM2_CH3/TSC_G1_IO3/USART2_TX/PA2 12 3100 -100 100 L 50 50 1 1 B
X ADC_IN3/TIM2_CH4/TSC_G1_IO4/USART2_RX/PA3 13 3100 -200 100 L 50 50 1 1 B
X ADC_IN4/I2S1_WS/SPI1_NSS/TIM14_CH1/TSC_G2_IO1/USART2_CK/USB_OE/PA4 14 3100 -300 100 L 50 50 1 1 B
X ADC_IN5/CEC/I2S1_CK/SPI1_SCK/TIM2_CH1/TIM2_ETR/TSC_G2_IO2/PA5 15 3100 -400 100 L 50 50 1 1 B
X ADC_IN6/I2S1_MCK/SPI1_MISO/TIM16_CH1/TIM1_BKIN/TIM3_CH1/TSC_G2_IO3/PA6 16 3100 -500 100 L 50 50 1 1 B
X ADC_IN7/I2S1_SD/SPI1_MOSI/TIM14_CH1/TIM17_CH1/TIM1_CH1N/TIM3_CH2/TSC_G2_IO4/PA7 17 3100 -600 100 L 50 50 1 1 B
X PB0/ADC_IN8/TIM1_CH2N/TIM3_CH3/TSC_G3_IO2 18 -3100 100 100 R 50 50 1 1 B
X PB1/ADC_IN9/TIM14_CH1/TIM1_CH3N/TIM3_CH4/TSC_G3_IO3 19 -3100 0 100 R 50 50 1 1 B
X PC13/RTC_OUT_ALARM/RTC_OUT_CALIB/RTC_TAMP1/RTC_TS/SYS_WKUP2 2 -3100 500 100 R 50 50 1 1 B
X PB2/TSC_G3_IO4 20 -3100 -100 100 R 50 50 1 1 B
X PB10/CEC/I2C1_SCL/SPI2_SCK/TIM2_CH3/TSC_SYNC 21 -3100 -900 100 R 50 50 1 1 B
X PB11/I2C1_SDA/TIM2_CH4 22 -3100 -1000 100 R 50 50 1 1 B
X VSS 23 -200 -1800 100 U 50 50 1 1 W
X VDD 24 -200 1800 100 D 50 50 1 1 W
X PB12/SPI2_NSS/TIM1_BKIN 25 -3100 -1100 100 R 50 50 1 1 B
X PB13/I2C1_SCL/SPI2_SCK/TIM1_CH1N 26 -3100 -1200 100 R 50 50 1 1 B
X PB14/I2C1_SDA/SPI2_MISO/TIM1_CH2N 27 -3100 -1300 100 R 50 50 1 1 B
X PB15/RTC_REFIN/SPI2_MOSI/SYS_WKUP7/TIM1_CH3N 28 -3100 -1400 100 R 50 50 1 1 B
X CRS_SYNC/RCC_MCO/TIM1_CH1/USART1_CK/PA8 29 3100 -700 100 L 50 50 1 1 B
X PC14/RCC_OSC32_IN 3 -3100 400 100 R 50 50 1 1 B
X I2C1_SCL/TIM1_CH2/TSC_G4_IO1/USART1_TX/PA9 30 3100 -800 100 L 50 50 1 1 B
X I2C1_SDA/TIM17_BKIN/TIM1_CH3/TSC_G4_IO2/USART1_RX/PA10 31 3100 -900 100 L 50 50 1 1 B
X CAN_RX/I2C1_SCL/TIM1_CH4/TSC_G4_IO3/USART1_CTS/USB_DM/PA11 32 3100 -1000 100 L 50 50 1 1 B
X CAN_TX/I2C1_SDA/TIM1_ETR/TSC_G4_IO4/USART1_DE/USART1_RTS/USB_DP/PA12 33 3100 -1100 100 L 50 50 1 1 B
X IR_OUT/SYS_SWDIO/USB_OE/PA13 34 3100 -1200 100 L 50 50 1 1 B
X VSS 35 -100 -1800 100 U 50 50 1 1 W
X VDDIO2 36 100 1800 100 D 50 50 1 1 W
X SYS_SWCLK/USART2_TX/PA14 37 3100 -1300 100 L 50 50 1 1 B
X I2S1_WS/SPI1_NSS/TIM2_CH1/TIM2_ETR/USART2_RX/USB_OE/PA15 38 3100 -1400 100 L 50 50 1 1 B
X PB3/I2S1_CK/SPI1_SCK/TIM2_CH2/TSC_G5_IO1 39 -3100 -200 100 R 50 50 1 1 B
X PC15/RCC_OSC32_OUT 4 -3100 300 100 R 50 50 1 1 B
X PB4/I2S1_MCK/SPI1_MISO/TIM17_BKIN/TIM3_CH1/TSC_G5_IO2 40 -3100 -300 100 R 50 50 1 1 B
X PB5/I2C1_SMBA/I2S1_SD/SPI1_MOSI/SYS_WKUP6/TIM16_BKIN/TIM3_CH2 41 -3100 -400 100 R 50 50 1 1 B
X PB6/I2C1_SCL/TIM16_CH1N/TSC_G5_IO3/USART1_TX 42 -3100 -500 100 R 50 50 1 1 B
X PB7/I2C1_SDA/TIM17_CH1N/TSC_G5_IO4/USART1_RX 43 -3100 -600 100 R 50 50 1 1 B
X PF11 44 -3100 700 100 R 50 50 1 1 B
X PB8/CAN_RX/CEC/I2C1_SCL/TIM16_CH1/TSC_SYNC 45 -3100 -700 100 R 50 50 1 1 B
X PB9/CAN_TX/I2C1_SDA/IR_OUT/SPI2_NSS/TIM17_CH1 46 -3100 -800 100 R 50 50 1 1 B
X VSS 47 0 -1800 100 U 50 50 1 1 W
X VDD 48 -100 1800 100 D 50 50 1 1 W
X PF0/CRS_SYNC/I2C1_SDA/RCC_OSC_IN 5 -3100 900 100 R 50 50 1 1 I
X PF1/I2C1_SCL/RCC_OSC_OUT 6 -3100 800 100 R 50 50 1 1 I
X NRST 7 -3100 1300 100 R 50 50 1 1 I
X VSSA 8 100 -1800 100 U 50 50 1 1 W
X VDDA 9 0 1800 100 D 50 50 1 1 W
ENDDRAW
ENDDEF
#
# SW_Push
#
DEF SW_Push SW 0 40 N N 1 F N
F0 "SW" 50 100 50 H V L CNN
F1 "SW_Push" 0 -60 50 H V C CNN
F2 "" 0 200 50 H I C CNN
F3 "" 0 200 50 H I C CNN
DRAW
C -80 0 20 0 1 0 N
C 80 0 20 0 1 0 N
P 2 0 1 0 0 50 0 120 N
P 2 0 1 0 100 50 -100 50 N
X 1 1 -200 0 100 R 50 50 0 1 P
X 2 2 200 0 100 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# USB6B1-elements
#
DEF USB6B1-elements D 0 30 Y N 1 F N
F0 "D" 0 -450 50 H V C CNN
F1 "USB6B1-elements" 0 400 50 H V C CNN
F2 "" 200 -100 50 V V C CNN
F3 "" 200 -100 50 V V C CNN
$FPLIST
SO8
$ENDFPLIST
DRAW
C -150 -300 7 0 1 0 N
C -150 100 7 0 1 0 N
C -150 300 7 0 1 0 N
C 0 -300 7 0 1 0 N
C 0 -100 7 0 1 0 N
C 0 300 7 0 1 0 N
C 200 -300 7 0 1 0 N
C 200 300 7 0 1 0 N
S -300 -100 300 -100 0 1 0 N
S -300 300 300 300 0 1 0 N
S -200 -150 -100 -150 0 1 0 N
S -200 250 -100 250 0 1 0 N
S -150 300 -150 -300 0 1 0 N
S -50 -150 50 -150 0 1 0 N
S -50 250 50 250 0 1 0 N
S 0 300 0 -300 0 1 0 N
S 200 300 200 -300 0 1 0 N
S 300 -300 -300 -300 0 1 0 N
S 300 100 -300 100 0 1 0 N
P 3 0 1 8 150 50 250 50 250 50 N
P 4 0 1 8 150 50 150 30 160 30 160 30 N
P 4 0 1 8 250 50 250 70 240 70 240 70 N
P 5 0 1 0 -250 350 300 350 300 -350 -250 -350 -250 350 N
P 6 0 1 8 -200 -250 -150 -150 -100 -250 -200 -250 -200 -250 -200 -250 N
P 6 0 1 8 -200 150 -150 250 -100 150 -200 150 -200 150 -200 150 N
P 6 0 1 8 -50 -250 0 -150 50 -250 -50 -250 -50 -250 -50 -250 N
P 6 0 1 8 -50 150 0 250 50 150 -50 150 -50 150 -50 150 N
P 6 0 1 8 150 -50 200 50 250 -50 150 -50 150 -50 150 -50 N
X VCC 1 -500 300 200 R 50 50 1 1 P
X I/O1 2 -500 100 200 R 50 50 1 1 P
X I/O2 3 -500 -100 200 R 50 50 1 1 P
X GND 4 -500 -300 200 R 50 50 1 1 P
X GND 5 500 -300 200 L 50 50 1 1 P
X I/O2 6 500 -100 200 L 50 50 1 1 P
X I/O1 7 500 100 200 L 50 50 1 1 P
X VCC 8 500 300 200 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
# USB_A-RESCUE-stm32
#
DEF USB_A-RESCUE-stm32 P 0 40 Y Y 1 F N
F0 "P" 200 -200 50 H V C CNN
F1 "USB_A-RESCUE-stm32" -50 200 50 H V C CNN
F2 "" -50 -100 50 V V C CNN
F3 "" -50 -100 50 V V C CNN
$FPLIST
USB*
$ENDFPLIST
DRAW
S -250 -150 150 150 0 1 0 N
S -205 -150 -195 -120 0 1 0 N
S -105 -150 -95 -120 0 1 0 N
S -5 -150 5 -120 0 1 0 N
S 95 -150 105 -120 0 1 0 N
X VBUS 1 -200 -300 150 U 50 50 1 1 W
X D- 2 -100 -300 150 U 50 50 1 1 P
X D+ 3 0 -300 150 U 50 50 1 1 P
X GND 4 100 -300 150 U 50 50 1 1 W
X shield 5 300 100 150 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
#End Library

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
update=Ср 16 июн 2021 12:32:18
version=1
last_client=kicad
[cvpcb]
version=1
NetIExt=net
[general]
version=1
[eeschema]
version=1
LibDir=
[schematic_editor]
version=1
PageLayoutDescrFile=
PlotDirectoryName=
SubpartIdSeparator=0
SubpartFirstId=65
NetFmtName=Pcbnew
SpiceAjustPassiveValues=0
LabSize=50
ERC_TestSimilarLabels=1
[pcbnew]
version=1
PageLayoutDescrFile=
LastNetListRead=stm32.net
CopperLayerCount=2
BoardThickness=2.5
AllowMicroVias=0
AllowBlindVias=0
RequireCourtyardDefinitions=0
ProhibitOverlappingCourtyards=1
MinTrackWidth=0.2
MinViaDiameter=0.7999999999999999
MinViaDrill=0.4
MinMicroViaDiameter=0.2
MinMicroViaDrill=0.09999999999999999
MinHoleToHole=0.25
TrackWidth1=0.2
TrackWidth2=0.2
TrackWidth3=0.3
TrackWidth4=0.5
TrackWidth5=1
TrackWidth6=2
ViaDiameter1=0.8
ViaDrill1=0.4
ViaDiameter2=0.8
ViaDrill2=0.4
ViaDiameter3=1.2
ViaDrill3=0.6
dPairWidth1=0.2
dPairGap1=0.25
dPairViaGap1=0.25
SilkLineWidth=0.15
SilkTextSizeV=1
SilkTextSizeH=1
SilkTextSizeThickness=0.15
SilkTextItalic=0
SilkTextUpright=1
CopperLineWidth=0.2
CopperTextSizeV=1.5
CopperTextSizeH=1.5
CopperTextThickness=0.3
CopperTextItalic=0
CopperTextUpright=1
EdgeCutLineWidth=0.15
CourtyardLineWidth=0.05
OthersLineWidth=0.15
OthersTextSizeV=1
OthersTextSizeH=1
OthersTextSizeThickness=0.15
OthersTextItalic=0
OthersTextUpright=1
SolderMaskClearance=0.2
SolderMaskMinWidth=0
SolderPasteClearance=0
SolderPasteRatio=-0
[pcbnew/Layer.F.Cu]
Name=F.Cu
Type=0
Enabled=1
[pcbnew/Layer.In1.Cu]
Name=In1.Cu
Type=0
Enabled=0
[pcbnew/Layer.In2.Cu]
Name=In2.Cu
Type=0
Enabled=0
[pcbnew/Layer.In3.Cu]
Name=In3.Cu
Type=0
Enabled=0
[pcbnew/Layer.In4.Cu]
Name=In4.Cu
Type=0
Enabled=0
[pcbnew/Layer.In5.Cu]
Name=In5.Cu
Type=0
Enabled=0
[pcbnew/Layer.In6.Cu]
Name=In6.Cu
Type=0
Enabled=0
[pcbnew/Layer.In7.Cu]
Name=In7.Cu
Type=0
Enabled=0
[pcbnew/Layer.In8.Cu]
Name=In8.Cu
Type=0
Enabled=0
[pcbnew/Layer.In9.Cu]
Name=In9.Cu
Type=0
Enabled=0
[pcbnew/Layer.In10.Cu]
Name=In10.Cu
Type=0
Enabled=0
[pcbnew/Layer.In11.Cu]
Name=In11.Cu
Type=0
Enabled=0
[pcbnew/Layer.In12.Cu]
Name=In12.Cu
Type=0
Enabled=0
[pcbnew/Layer.In13.Cu]
Name=In13.Cu
Type=0
Enabled=0
[pcbnew/Layer.In14.Cu]
Name=In14.Cu
Type=0
Enabled=0
[pcbnew/Layer.In15.Cu]
Name=In15.Cu
Type=0
Enabled=0
[pcbnew/Layer.In16.Cu]
Name=In16.Cu
Type=0
Enabled=0
[pcbnew/Layer.In17.Cu]
Name=In17.Cu
Type=0
Enabled=0
[pcbnew/Layer.In18.Cu]
Name=In18.Cu
Type=0
Enabled=0
[pcbnew/Layer.In19.Cu]
Name=In19.Cu
Type=0
Enabled=0
[pcbnew/Layer.In20.Cu]
Name=In20.Cu
Type=0
Enabled=0
[pcbnew/Layer.In21.Cu]
Name=In21.Cu
Type=0
Enabled=0
[pcbnew/Layer.In22.Cu]
Name=In22.Cu
Type=0
Enabled=0
[pcbnew/Layer.In23.Cu]
Name=In23.Cu
Type=0
Enabled=0
[pcbnew/Layer.In24.Cu]
Name=In24.Cu
Type=0
Enabled=0
[pcbnew/Layer.In25.Cu]
Name=In25.Cu
Type=0
Enabled=0
[pcbnew/Layer.In26.Cu]
Name=In26.Cu
Type=0
Enabled=0
[pcbnew/Layer.In27.Cu]
Name=In27.Cu
Type=0
Enabled=0
[pcbnew/Layer.In28.Cu]
Name=In28.Cu
Type=0
Enabled=0
[pcbnew/Layer.In29.Cu]
Name=In29.Cu
Type=0
Enabled=0
[pcbnew/Layer.In30.Cu]
Name=In30.Cu
Type=0
Enabled=0
[pcbnew/Layer.B.Cu]
Name=B.Cu
Type=0
Enabled=1
[pcbnew/Layer.B.Adhes]
Enabled=1
[pcbnew/Layer.F.Adhes]
Enabled=1
[pcbnew/Layer.B.Paste]
Enabled=1
[pcbnew/Layer.F.Paste]
Enabled=1
[pcbnew/Layer.B.SilkS]
Enabled=1
[pcbnew/Layer.F.SilkS]
Enabled=1
[pcbnew/Layer.B.Mask]
Enabled=1
[pcbnew/Layer.F.Mask]
Enabled=1
[pcbnew/Layer.Dwgs.User]
Enabled=1
[pcbnew/Layer.Cmts.User]
Enabled=1
[pcbnew/Layer.Eco1.User]
Enabled=1
[pcbnew/Layer.Eco2.User]
Enabled=1
[pcbnew/Layer.Edge.Cuts]
Enabled=1
[pcbnew/Layer.Margin]
Enabled=1
[pcbnew/Layer.B.CrtYd]
Enabled=1
[pcbnew/Layer.F.CrtYd]
Enabled=1
[pcbnew/Layer.B.Fab]
Enabled=1
[pcbnew/Layer.F.Fab]
Enabled=1
[pcbnew/Layer.Rescue]
Enabled=0
[pcbnew/Netclasses]
[pcbnew/Netclasses/Default]
Name=Default
Clearance=0.2
TrackWidth=0.2
ViaDiameter=0.8
ViaDrill=0.4
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/1]
Name=0.5
Clearance=0.3
TrackWidth=0.5
ViaDiameter=1.2
ViaDrill=0.6
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/2]
Name=1
Clearance=0.5
TrackWidth=1
ViaDiameter=1.2
ViaDrill=0.6
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
(sym_lib_table
(lib (name stm32-rescue)(type Legacy)(uri ${KIPRJMOD}/stm32-rescue.lib)(options "")(descr ""))
(lib (name stm32)(type Legacy)(uri /home/eddy/kicad/Kicad-Libraries/library/stm32.lib)(options "")(descr ""))
(lib (name vreg)(type Legacy)(uri /home/eddy/kicad/Kicad-Libraries/library/vreg.lib)(options "")(descr ""))
(lib (name elements)(type Legacy)(uri ${KIPRJMOD}/elements.lib)(options "")(descr ""))
)

View File

@@ -0,0 +1,126 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "adc.h"
#include "buttons.h"
#include "can.h"
#include "custom_buttons.h"
#include "flash.h"
#include "hardware.h"
#include "steppers.h"
#include "strfunct.h"
#include "usb.h"
#include "usb_lib.h"
volatile uint32_t Tms = 0;
/* Called when systick fires */
void sys_tick_handler(void){
++Tms;
}
#define USBBUF 63
// usb getline
static char *get_USB(){
static char tmpbuf[USBBUF+1], *curptr = tmpbuf;
static int rest = USBBUF;
uint8_t x = USB_receive((uint8_t*)curptr);
if(!x) return NULL;
curptr[x] = 0;
if(x == 1 && *curptr == 0x7f){ // backspace
if(curptr > tmpbuf){
--curptr;
USND("\b \b");
}
return NULL;
}
USB_sendstr(curptr); // echo
if(curptr[x-1] == '\n'){ // || curptr[x-1] == '\r'){
curptr = tmpbuf;
rest = USBBUF;
// omit empty lines
if(tmpbuf[0] == '\n') return NULL;
// and wrong empty lines
if(tmpbuf[0] == '\r' && tmpbuf[1] == '\n') return NULL;
return tmpbuf;
}
curptr += x; rest -= x;
if(rest <= 0){ // buffer overflow
curptr = tmpbuf;
rest = USBBUF;
}
return NULL;
}
int main(void){
uint8_t ctr, len;
CAN_message *can_mesg;
//uint32_t oS = 0;
char *txt;
sysreset();
SysTick_Config(6000, 1);
flashstorage_init(); // should be called before any other functions
gpio_setup();
USB_setup();
CAN_setup(the_conf.CANspeed);
adc_setup();
init_steppers();
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
iwdg_setup();
while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog
/* if(Tms - oS > 1999){
oS = Tms;
SEND("2s"); NL();
}*/
process_keys();
custom_buttons_process();
IWDG->KR = IWDG_REFRESH;
can_proc();
if(CAN_get_status() == CAN_FIFO_OVERRUN){
SEND("CAN bus fifo overrun occured!\n");
sendbuf();
}
IWDG->KR = IWDG_REFRESH;
usb_proc();
process_steppers();
IWDG->KR = IWDG_REFRESH;
while((can_mesg = CAN_messagebuf_pop())){
if(can_mesg && ShowMsgs && isgood(can_mesg->ID)){
IWDG->KR = IWDG_REFRESH;
len = can_mesg->length;
printu(Tms);
SEND(" #");
printuhex(can_mesg->ID);
for(ctr = 0; ctr < len; ++ctr){
SEND(" ");
printuhex(can_mesg->data[ctr]);
}
newline(); sendbuf();
}
}
IWDG->KR = IWDG_REFRESH;
if((txt = get_USB())){
IWDG->KR = IWDG_REFRESH;
cmd_parser(txt);
}
}
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

View File

@@ -0,0 +1,507 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "flash.h"
#include "hardware.h"
#include "steppers.h"
#include "strfunct.h"
// goto zero stages
typedef enum{
M0RELAX, // normal moving
M0FAST, // fast move to zero
M0SLOW // slowest move from ESW
} mvto0state;
typedef enum{
STALL_NO, // moving OK
STALL_ONCE, // Nstalled < limit
STALL_STOP // Nstalled >= limit
} t_stalled;
static t_stalled stallflags[MOTORSNO];
// motors' direction: 1 for positive, -1 for negative (we need it as could be reverse)
static int8_t motdir[MOTORSNO];
// current position (in steps) by STP counter
static volatile int32_t stppos[MOTORSNO] = {0};
// previous position when check (set to current in start of moving)
static int32_t prevstppos[MOTORSNO];
// target stepper position
static int32_t targstppos[MOTORSNO] = {0};
// position to start deceleration
static int32_t decelstartpos[MOTORSNO];
// current encoder position (4 per ticks) (without TIM->CNT)
static volatile int32_t encpos[MOTORSNO] = {0};
// previous encoder position
static int32_t prevencpos[MOTORSNO] = {0};
// encoders' ticks per step (calculates @ init)
static int32_t encperstep[MOTORSNO];
// ESW reaction - local copy
static uint8_t ESW_reaction[MOTORSNO];
// current speed
static uint16_t curspeed[MOTORSNO];
static uint16_t startspeed[MOTORSNO]; // speed when deceleration starts
// ==1 to stop @ nearest step
static uint8_t stopflag[MOTORSNO];
// motor state
static stp_state state[MOTORSNO];
// move to zero state
static mvto0state mvzerostate[MOTORSNO];
static int8_t Nstalled[MOTORSNO] = {0}; // counter of STALL
// lowest ARR value (highest speed), highest (lowest speed)
//static uint16_t stphighARR[MOTORSNO];
// microsteps=1<<ustepsshift
static uint16_t ustepsshift[MOTORSNO];
// amount of steps for full acceleration/deceleration
static uint32_t accdecsteps[MOTORSNO];
// time when acceleration or deceleration starts
static uint32_t Taccel[MOTORSNO] = {0};
// recalculate ARR according to new speed
TRUE_INLINE void recalcARR(int i){
uint32_t ARR = (((PCLK/(MOTORTIM_PSC+1)) / curspeed[i]) >> ustepsshift[i]) - 1;
if(ARR < MOTORTIM_ARRMIN) ARR = MOTORTIM_ARRMIN;
else if(ARR > 0xffff) ARR = 0xffff;
mottimers[i]->ARR = ARR;
curspeed[i] = (((PCLK/(MOTORTIM_PSC+1)) / (ARR+1)) >> ustepsshift[i]); // recalculate speed due to new val
}
// run this function after each steppers parameters changing
void init_steppers(){
timers_setup(); // reinit timers & stop them
// init variables
for(int i = 0; i < MOTORSNO; ++i){
stopflag[i] = 0;
motdir[i] = 1;
curspeed[i] = 0;
accdecsteps[i] = (the_conf.maxspd[i] * the_conf.maxspd[i]) / the_conf.accel[i] / 2;
state[i] = STP_RELAX;
ustepsshift[i] = MSB(the_conf.microsteps[i]);
encperstep[i] = the_conf.encrev[i] / STEPSPERREV;
if(!the_conf.motflags[i].donthold) MOTOR_EN(i);
else MOTOR_DIS(i);
ESW_reaction[i] = the_conf.ESW_reaction[i];
}
}
// get absolute position by encoder
int32_t encoder_position(uint8_t i){
int32_t pos = encpos[i];
if(the_conf.motflags[i].encreverse) pos -= enctimers[i]->CNT;
else pos += enctimers[i]->CNT;
return pos;
}
// set encoder's position, return 0 if false (motor's state != relax)
int setencpos(uint8_t i, int32_t position){
if(state[i] != STP_RELAX) return FALSE;
int32_t remain = position % the_conf.encrev[i];
if(remain < 0) remain += the_conf.encrev[i];
enctimers[i]->CNT = remain;
prevencpos[i] = encpos[i] = position - remain;
SEND("MOTOR"); bufputchar('0'+i); SEND(", position="); printi(position); SEND(", remain=");
printi(remain); SEND(", CNT="); printu(enctimers[i]->CNT); SEND(", pos="); printi(encpos[i]); NL();
return TRUE;
}
// get current position
errcodes getpos(uint8_t i, int32_t *position){
if(the_conf.motflags[i].haveencoder){
int32_t p = encoder_position(i);
if(p < 0) p -= encperstep[i]>>1;
else p += encperstep[i]>>1;
p /= encperstep[i];
*position = p;
}else
*position = stppos[i];
return ERR_OK;
}
errcodes getremainsteps(uint8_t i, int32_t *position){
*position = targstppos[i] - stppos[i];
return ERR_OK;
}
// calculate acceleration/deceleration parameters for motor i
static void calcacceleration(uint8_t i){
int32_t delta = targstppos[i] - stppos[i];
if(delta > 0){ // positive direction
if(delta > 2*(int32_t)accdecsteps[i]){ // can move by trapezoid
decelstartpos[i] = targstppos[i] - accdecsteps[i];
}else{ // triangle speed profile
decelstartpos[i] = stppos[i] + delta/2;
}
motdir[i] = 1;
if(the_conf.motflags[i].reverse) MOTOR_CCW(i);
else MOTOR_CW(i);
}else{ // negative direction
delta = -delta;
if(delta > 2*(int32_t)accdecsteps[i]){ // can move by trapezoid
decelstartpos[i] = targstppos[i] + accdecsteps[i];
}else{ // triangle speed profile
decelstartpos[i] = stppos[i] - delta/2;
}
motdir[i] = -1;
if(the_conf.motflags[i].reverse) MOTOR_CW(i);
else MOTOR_CCW(i);
}
if(state[i] != STP_MVSLOW) state[i] = STP_ACCEL;
startspeed[i] = curspeed[i];
Taccel[i] = Tms;
recalcARR(i);
}
// move to absolute position
errcodes motor_absmove(uint8_t i, int32_t newpos){
//if(i >= MOTORSNO) return ERR_BADPAR; // bad motor number
switch(state[i]){
case STP_ERR:
case STP_STALL:
case STP_RELAX:
break;
default: // moving state
return ERR_CANTRUN;
}
if(newpos > (int32_t)the_conf.maxsteps[i] || newpos < -(int32_t)the_conf.maxsteps[i] || newpos == stppos[i])
return ERR_BADVAL; // too big position or zero
Nstalled[i] = (state[i] == STP_STALL) ? -(NSTALLEDMAX*5) : 0; // give some more chances to go out of stall state
stopflag[i] = 0;
targstppos[i] = newpos;
prevencpos[i] = encoder_position(i);
prevstppos[i] = stppos[i];
curspeed[i] = the_conf.minspd[i];
calcacceleration(i);
SEND("MOTOR"); bufputchar('0'+i);
SEND(" targstppos="); printi(targstppos[i]);
SEND(", decelstart="); printi(decelstartpos[i]);
SEND(", accdecsteps="); printu(accdecsteps[i]); NL();
MOTOR_EN(i);
mottimers[i]->CR1 |= TIM_CR1_CEN; // start timer
return ERR_OK;
}
// move i'th motor for relsteps
errcodes motor_relmove(uint8_t i, int32_t relsteps){
return motor_absmove(i, stppos[i] + relsteps);
}
errcodes motor_relslow(uint8_t i, int32_t relsteps){
errcodes e = motor_absmove(i, stppos[i] + relsteps);
if(ERR_OK == e){
state[i] = STP_MVSLOW;
}
return e;
}
// emergency stop and clear errors
void emstopmotor(uint8_t i){
switch(state[i]){
case STP_ERR: // clear error state
case STP_STALL:
state[i] = STP_RELAX;
// fallthrough
case STP_RELAX: // do nothing in stopping state
return;
default:
break;
}
stopflag[i] = 1;
}
stp_state getmotstate(uint8_t i){
return state[i];
}
// count steps @tim 14/15/16
void addmicrostep(uint8_t i){
static volatile uint16_t microsteps[MOTORSNO] = {0}; // current microsteps position
if(ESW_state(i)){ // ESW active
switch(ESW_reaction[i]){
case ESW_ANYSTOP: // stop motor in any direction
stopflag[i] = 1;
break;
case ESW_STOPMINUS: // stop only @ minus
if(motdir[i] == -1) stopflag[i] = 1;
break;
default: // ESW_IGNORE
break;
}
}
if(++microsteps[i] == the_conf.microsteps[i]){
microsteps[i] = 0;
stppos[i] += motdir[i];
uint8_t stop_at_pos = 0;
if(motdir[i] > 0){
if(stppos[i] >= targstppos[i]){ // reached start of deceleration
stop_at_pos = 1;
}
}else{
if(stppos[i] <= targstppos[i]){
stop_at_pos = 1;
}
}
if(stopflag[i] || stop_at_pos){ // stop NOW
if(stopflag[i]) targstppos[i] = stppos[i]; // keep position (for keep flag)
stopflag[i] = 0;
mottimers[i]->CR1 &= ~TIM_CR1_CEN; // stop timer
if(the_conf.motflags[i].donthold)
MOTOR_DIS(i); // turn off power
if(stallflags[i] == STALL_STOP){
stallflags[i] = STALL_NO;
state[i] = STP_STALL;
}else
state[i] = STP_RELAX;
SEND("MOTOR"); bufputchar('0'+i); SEND(" stop @"); printi(stppos[i]); newline();
}
}
}
void encoders_UPD(uint8_t i){
if(enctimers[i]->SR & TIM_SR_UIF){
int8_t d = 1; // positive (-1 - negative)
if(enctimers[i]->CR1 & TIM_CR1_DIR) d = -d; // negative
if(the_conf.motflags[i].encreverse) d = -d;
if(d == 1) encpos[i] += the_conf.encrev[i];
else encpos[i] -= the_conf.encrev[i];
}
enctimers[i]->SR = 0;
}
// check if motor is stalled
// @return 0 if moving OK,
static t_stalled chkSTALL(uint8_t i){
if(!the_conf.motflags[i].haveencoder) return STALL_NO;
int32_t curencpos = encoder_position(i), Denc = curencpos - prevencpos[i];
int32_t curstppos = stppos[i], Dstp = curstppos - prevstppos[i];
int difsign = 1;
if(Dstp < 0){
Dstp = -Dstp;
difsign = -difsign;
}
if(Dstp < 10){ // didn't move even @ 10 steps
stallflags[i] = STALL_NO;
return STALL_NO;
}
if(Denc < 0){
Denc = -Denc;
difsign = -difsign;
}
if(difsign == -1){ // motor and encÏder moves to different sides!!!
Denc = -Denc; // init STALL state
}
prevencpos[i] = curencpos;
// TODO: check if it should be here
getpos(i, &curstppos); // recalculate current position
stppos[i] = curstppos;
prevstppos[i] = curstppos;
if(Denc < the_conf.encperstepmin[i]*Dstp || the_conf.encperstepmax[i]*Dstp < Denc){ // stall?
SEND("MOTOR"); bufputchar('0'+i); SEND(" Denc="); printi(Denc); SEND(", Dstp="); printu(Dstp);
SEND(", speed="); printu(curspeed[i]);
if(++Nstalled[i] > NSTALLEDMAX){
stopflag[i] = 1;
Nstalled[i] = 0;
SEND(" --- STALL!"); NL();
stallflags[i] = STALL_STOP;
return STALL_STOP;
}else{
uint16_t spd = curspeed[i] >> 1; // speed / 2
curspeed[i] = (spd > the_conf.minspd[i]) ? spd : the_conf.minspd[i];
// now recalculate acc/dec parameters
calcacceleration(i);
SEND(" --- pre-stall, newspeed="); printu(curspeed[i]); NL();
stallflags[i] = STALL_ONCE;
return STALL_ONCE;
}
}
Nstalled[i] = 0;
return STALL_NO;
}
#define TODECEL() do{state[i] = STP_DECEL; \
startspeed[i] = curspeed[i]; \
Taccel[i] = Tms; \
SEND("MOTOR"); bufputchar('0'+i); \
SEND(" -> DECEL@"); printi(stppos[i]); SEND(", V="); printu(curspeed[i]); NL(); \
}while(0)
// check state of i`th stepper
static void chkstepper(int i){
int32_t newspeed;
switch(state[i]){
case STP_RELAX: // check if need to keep current position
if(the_conf.motflags[i].haveencoder){
getpos(i, &newspeed);
int32_t diff = stppos[i] - newspeed; // correct `curpos` counter by encoder
if(diff){ // correct current stppos by encoder
SEND("MOTOR"); bufputchar('0'+i);
SEND(" diff="); printi(diff);
SEND(", change stppos from "); printi(stppos[i]); SEND(" to "); printi(newspeed); NL();
stppos[i] = newspeed;
}
if(the_conf.motflags[i].keeppos){ // keep old position
diff = targstppos[i] - newspeed; // check whether we need to change position
if(diff){ // try to correct position
SEND("MOTOR"); bufputchar('0'+i);
SEND(" curpos="); printi(newspeed); SEND(", need="); printi(targstppos[i]); NL();
motor_absmove(i, targstppos[i]);
}
}
}
break;
case STP_ACCEL: // acceleration to max speed
if(STALL_NO == chkSTALL(i)){
//newspeed = curspeed[i] + dV[i];
newspeed = the_conf.minspd[i] + (the_conf.accel[i] * (Tms - Taccel[i])) / 1000;
if(newspeed >= the_conf.maxspd[i]){ // max speed reached -> move with it
curspeed[i] = the_conf.maxspd[i];
state[i] = STP_MOVE;
SEND("MOTOR"); bufputchar('0'+i);
SEND(" -> MOVE@"); printi(stppos[i]); SEND(", V="); printu(curspeed[i]); NL();
}else{ // increase speed
curspeed[i] = newspeed;
}
recalcARR(i);
}
// check position for triangle profile
if(motdir[i] > 0){
if(stppos[i] >= decelstartpos[i]){ // reached end of acceleration
TODECEL();
}
}else{
if(stppos[i] <= decelstartpos[i]){
TODECEL();
}
}
break;
case STP_MOVE: // move @ constant speed until need to decelerate
if(STALL_NO == chkSTALL(i)){
// check position
if(motdir[i] > 0){
if(stppos[i] >= decelstartpos[i]){ // reached start of deceleration
TODECEL();
}
}else{
if(stppos[i] <= decelstartpos[i]){
TODECEL();
}
}
}
break;
case STP_DECEL:
if(STALL_NO == chkSTALL(i)){
//newspeed = curspeed[i] - dV[i];
newspeed = startspeed[i] - (the_conf.accel[i] * (Tms - Taccel[i])) / 1000;
if(newspeed > the_conf.minspd[i]){
curspeed[i] = newspeed;
}else{
curspeed[i] = the_conf.minspd[i];
state[i] = STP_MVSLOW;
SEND("MOTOR"); bufputchar('0'+i);
SEND(" -> MVSLOW@"); printi(stppos[i]); NL();
}
recalcARR(i);
//SEND("spd="); printu(curspeed[i]); SEND(", pos="); printi(stppos[i]); newline();
}
break;
case STP_MVSLOW:
chkSTALL(i);
break;
default: // STALL, ERR -> do nothing, check mvzerostate
break;
}
switch(mvzerostate[i]){
case M0FAST:
if(state[i] == STP_RELAX || state[i] == STP_STALL){ // stopped -> move to +
SEND("M0FAST: motor stopped\n");
if(ERR_OK != motor_relslow(i, 1000)){
SEND("Can't move\n");
state[i] = STP_ERR;
mvzerostate[i] = M0RELAX;
ESW_reaction[i] = the_conf.ESW_reaction[i];
}else
mvzerostate[i] = M0SLOW;
}
break;
case M0SLOW:
if(0 == ESW_state(i)){ // moved out of limit switch - can stop
emstopmotor(i);
}
if(state[i] == STP_RELAX || state[i] == STP_STALL){
SEND("M0SLOW: motor stopped @ 0\n"); NL();
ESW_reaction[i] = the_conf.ESW_reaction[i];
prevencpos[i] = encpos[i] = 0;
stppos[i] = 0;
enctimers[i]->CNT = 0; // set encoder counter to zero
mvzerostate[i] = M0RELAX;
}
break;
default: // RELAX, STALL: do nothing
break;
}
}
errcodes motor_goto0(uint8_t i){
errcodes e = motor_absmove(i, -the_conf.maxsteps[i]);
if(ERR_OK != e) return e;
ESW_reaction[i] = ESW_STOPMINUS;
mvzerostate[i] = M0FAST;
return e;
}
// smooth motor stopping
void stopmotor(uint8_t i){
switch(state[i]){
case STP_MVSLOW: // immeditially stop on slowest speed
stopflag[i] = 1;
return;
break;
case STP_MOVE: // stop only in moving states
case STP_ACCEL:
break;
default: // do nothing in other states
return;
}
int32_t newstoppos = stppos[i]; // calculate steps need for stop (we can be @acceleration phase!)
int32_t add = (curspeed[i] * curspeed[i]) / the_conf.accel[i] / 2;
if(motdir[i] > 0){
newstoppos += add;
if(newstoppos < (int32_t)the_conf.maxsteps[i]) targstppos[i] = newstoppos;
}else{
newstoppos -= add;
if(newstoppos > -((int32_t)the_conf.maxsteps[i])) targstppos[i] = newstoppos;
}
TODECEL();
}
void process_steppers(){
static uint32_t Tlast = 0;
if(Tms - Tlast < MOTCHKINTERVAL) return; // hit every 10ms
Tlast = Tms;
for(int i = 0; i < MOTORSNO; ++i){
chkstepper(i);
}
}
uint8_t geteswreact(uint8_t i){
return ESW_reaction[i];
}

View File

@@ -0,0 +1,71 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef STEPPERS_H__
#define STEPPERS_H__
#include <stm32f0.h>
#include "commonproto.h"
// amount of tries to detect motor stall
#define NSTALLEDMAX (5)
// stepper states
typedef enum{
STP_RELAX, // no moving
STP_ACCEL, // start moving with acceleration
STP_MOVE, // moving with constant speed
STP_MVSLOW, // moving with slowest constant speed (end of moving)
STP_DECEL, // moving with deceleration
STP_STALL, // stalled
STP_ERR // wrong/error state
} stp_state;
// end-switches reaction
enum{
ESW_IGNORE, // don't stop @ end-switch
ESW_ANYSTOP, // stop @ esw in any moving direction
ESW_STOPMINUS, // stop only in negative moving
ESW_AMOUNT // number of records
};
// find zero stages: fast -> 0, slow -> +, slow -> 0
void addmicrostep(uint8_t i);
void encoders_UPD(uint8_t i);
void init_steppers();
int32_t encoder_position(uint8_t i);
int setencpos(uint8_t i, int32_t position);
errcodes getpos(uint8_t i, int32_t *position);
errcodes getremainsteps(uint8_t i, int32_t *position);
errcodes motor_absmove(uint8_t i, int32_t abssteps);
errcodes motor_relmove(uint8_t i, int32_t relsteps);
errcodes motor_relslow(uint8_t i, int32_t relsteps);
errcodes motor_goto0(uint8_t i);
uint8_t geteswreact(uint8_t i);
void emstopmotor(uint8_t i);
void stopmotor(uint8_t i);
stp_state getmotstate(uint8_t i);
void process_steppers();
#endif // STEPPERS_H__

View File

@@ -0,0 +1,810 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "adc.h"
#include "buttons.h"
#include "can.h"
#include "commonproto.h"
#include "flash.h"
#include "hardware.h"
#include "strfunct.h"
#include "usb.h"
#include "version.inc"
#include <string.h> // strlen
extern volatile uint8_t canerror;
uint8_t ShowMsgs = 0;
uint16_t Ignore_IDs[IGN_SIZE];
uint8_t IgnSz = 0;
static char buff[BUFSZ+1], *bptr = buff;
static uint8_t blen = 0;
void sendbuf(){
if(blen == 0) return;
*bptr = 0;
USB_sendstr(buff);
bptr = buff;
blen = 0;
}
void bufputchar(char ch){
if(blen > BUFSZ-1){
sendbuf();
}
*bptr++ = ch;
++blen;
}
void addtobuf(const char *txt){
while(*txt) bufputchar(*txt++);
}
/**
* @brief cmpstr - the same as strncmp
* @param s1,s2 - strings to compare
* @return 0 if strings equal or 1/-1
*/
int cmpstr(const char *s1, const char *s2){
int ret = 0;
do{
ret = *s1 - *s2;
if(ret == 0 && *s1 && *s2){
++s1; ++s2;
continue;
}
break;
}while(1);
return ret;
}
/**
* @brief getchr - analog of strchr
* @param str - string to search
* @param symbol - searching symbol
* @return pointer to symbol found or NULL
*/
char *getchr(const char *str, char symbol){
do{
if(*str == symbol) return (char*)str;
}while(*(++str));
return NULL;
}
// parse `txt` to CAN_message
static CAN_message *parseCANmsg(char *txt){
static CAN_message canmsg;
//SEND("CAN command with arguments:\n");
int32_t N;
char *n;
int ctr = -1;
canmsg.ID = 0xffff;
do{
txt = omit_spaces(txt);
n = getnum(txt, &N);
if(txt == n) break;
txt = n;
if(ctr == -1){
if(N > 0x7ff){
SEND("ID should be 11-bit number!\n");
return NULL;
}
canmsg.ID = (uint16_t)(N&0x7ff);
//SEND("ID="); printuhex(canmsg.ID); newline();
ctr = 0;
continue;
}
if(ctr > 7){
SEND("ONLY 8 data bytes allowed!\n");
return NULL;
}
if(N > 0xff){
SEND("Every data portion is a byte!\n");
return NULL;
}
canmsg.data[ctr++] = (uint8_t)(N&0xff);
}while(1);
if(canmsg.ID == 0xffff){
SEND("NO ID given, send nothing!\n");
return NULL;
}
SEND("Message parsed OK\n");
sendbuf();
canmsg.length = (uint8_t) ctr;
return &canmsg;
}
// send command, format: ID (hex/bin/dec) data bytes (up to 8 bytes, space-delimeted)
static void sendCANcommand(char *txt){
CAN_message *msg = parseCANmsg(txt);
if(!msg) return;
uint32_t N = 1000;
while(CAN_BUSY == can_send(msg->data, msg->length, msg->ID)){
if(--N == 0) break;
}
}
static void CANini(char *txt){
txt = omit_spaces(txt);
int32_t N;
if(!txt) goto eofunc;
char *n = getnum(txt, &N);
if(txt == n) goto eofunc;
if(N < 50){
SEND("Lowest speed is 50kbps");
return;
}else if(N > 3000){
SEND("Highest speed is 3000kbps");
return;
}
the_conf.CANspeed = (uint16_t)N;
CAN_reinit((uint16_t)N);
eofunc:
SEND("canspeed="); printu(the_conf.CANspeed); NL();
}
static void addIGN(char *txt){
if(IgnSz == IGN_SIZE){
DBG("Ignore buffer is full");
return;
}
txt = omit_spaces(txt);
int32_t N;
char *n = getnum(txt, &N);
if(txt == n){
SEND("No ID given");
return;
}
if(N == the_conf.CANID){
SEND("You can't ignore self ID!");
return;
}
if(N > 0x7ff){
SEND("ID should be 11-bit number!");
return;
}
Ignore_IDs[IgnSz++] = (uint16_t)(N & 0x7ff);
SEND("Added ID "); printu(N);
SEND("\nIgn buffer size: "); printu(IgnSz);
}
static void print_ign_buf(_U_ char *txt){
if(IgnSz == 0){
SEND("Ignore buffer is empty");
return;
}
SEND("Ignored IDs:\n");
for(int i = 0; i < IgnSz; ++i){
if(i) newline();
printu(i);
SEND(": ");
printuhex(Ignore_IDs[i]);
}
}
// print ID/mask of CAN->sFilterRegister[x] half
static void printID(uint16_t FRn){
if(FRn & 0x1f) return; // trash
printuhex(FRn >> 5);
}
/*
Can filtering: FSCx=0 (CAN->FS1R) -> 16-bit identifiers
CAN->FMR = (sb)<<8 | FINIT - init filter in starting bank sb
CAN->FFA1R FFAx = 1 -> FIFO1, 0 -> FIFO0
CAN->FA1R FACTx=1 - filter active
MASK: FBMx=0 (CAN->FM1R), two filters (n in FR1 and n+1 in FR2)
ID: CAN->sFilterRegister[x].FRn[0..15]
MASK: CAN->sFilterRegister[x].FRn[16..31]
FR bits: STID[10:0] RTR IDE EXID[17:15]
LIST: FBMx=1, four filters (n&n+1 in FR1, n+2&n+3 in FR2)
IDn: CAN->sFilterRegister[x].FRn[0..15]
IDn+1: CAN->sFilterRegister[x].FRn[16..31]
*/
static void list_filters(_U_ char *txt){
uint32_t fa = CAN->FA1R, ctr = 0, mask = 1;
while(fa){
if(fa & 1){
SEND("Filter "); printu(ctr); SEND(", FIFO");
if(CAN->FFA1R & mask) SEND("1");
else SEND("0");
SEND(" in ");
if(CAN->FM1R & mask){ // up to 4 filters in LIST mode
SEND("LIST mode, IDs: ");
printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
SEND(" ");
printID(CAN->sFilterRegister[ctr].FR1 >> 16);
SEND(" ");
printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
SEND(" ");
printID(CAN->sFilterRegister[ctr].FR2 >> 16);
}else{ // up to 2 filters in MASK mode
SEND("MASK mode: ");
if(!(CAN->sFilterRegister[ctr].FR1&0x1f)){
SEND("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16);
SEND(" ");
}
if(!(CAN->sFilterRegister[ctr].FR2&0x1f)){
SEND("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16);
}
}
newline();
}
fa >>= 1;
++ctr;
mask <<= 1;
}
}
/**
* @brief add_filter - add/modify filter
* @param str - string in format "bank# FIFO# mode num0 .. num3"
* where bank# - 0..27
* if there's nothing after bank# - delete filter
* FIFO# - 0,1
* mode - 'I' for ID, 'M' for mask
* num0..num3 - IDs in ID mode, ID/MASK for mask mode
*/
static void add_filter(char *str){
int32_t N;
str = omit_spaces(str);
char *n = getnum(str, &N);
if(n == str){
SEND("No bank# given");
return;
}
if(N == 0 || N > STM32F0FBANKNO-1){
SEND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!");
return;
}
uint8_t bankno = (uint8_t)N;
str = omit_spaces(n);
if(!*str){ // deactivate filter
SEND("Deactivate filters in bank ");
printu(bankno);
CAN->FMR = CAN_FMR_FINIT;
CAN->FA1R &= ~(1<<bankno);
CAN->FMR &=~ CAN_FMR_FINIT;
return;
}
uint8_t fifono = 0;
if(*str == '1') fifono = 1;
else if(*str != '0'){
SEND("FIFO# is 0 or 1");
return;
}
str = omit_spaces(str + 1);
char c = *str;
uint8_t mode = 0; // ID
if(c == 'M' || c == 'm') mode = 1;
else if(c != 'I' && c != 'i'){
SEND("mode is 'M/m' for MASK and 'I/i' for IDLIST");
return;
}
str = omit_spaces(str + 1);
uint32_t filters[4];
uint32_t nfilt;
for(nfilt = 0; nfilt < 4; ++nfilt){
n = getnum(str, &N);
if(n == str) break;
filters[nfilt] = N;
str = omit_spaces(n);
}
if(nfilt == 0){
SEND("You should add at least one filter!");
return;
}
if(mode && (nfilt&1)){
SEND("In MASK mode you should point pairs of ID/MASK");
return;
}
CAN->FMR = CAN_FMR_FINIT;
uint32_t mask = 1<<bankno;
CAN->FA1R |= mask; // activate given filter
if(fifono) CAN->FFA1R |= mask; // set FIFO number
else CAN->FFA1R &= ~mask;
if(mode) CAN->FM1R &= ~mask; // MASK
else CAN->FM1R |= mask; // LIST
uint32_t F1 = (0x8f<<16);
uint32_t F2 = (0x8f<<16);
// reset filter registers to wrong value
CAN->sFilterRegister[bankno].FR1 = (0x8f<<16) | 0x8f;
CAN->sFilterRegister[bankno].FR2 = (0x8f<<16) | 0x8f;
switch(nfilt){
case 4:
F2 = filters[3] << 21;
// fallthrough
case 3:
CAN->sFilterRegister[bankno].FR2 = (F2 & 0xffff0000) | (filters[2] << 5);
// fallthrough
case 2:
F1 = filters[1] << 21;
// fallthrough
case 1:
CAN->sFilterRegister[bankno].FR1 = (F1 & 0xffff0000) | (filters[0] << 5);
}
CAN->FMR &=~ CAN_FMR_FINIT;
SEND("Added filter with ");
printu(nfilt); SEND(" parameters");
}
void canid(char *txt){
if(txt && *txt){
int good = FALSE;
char *eq = getchr(txt, '=');
if(eq){
eq = omit_spaces(eq+1);
if(eq){
int32_t N;
if(eq != getnum(eq, &N) && N > -1 && N < 0xfff){
the_conf.CANID = (uint16_t)N;
CAN_reinit(the_conf.CANspeed);
good = TRUE;
}
}
}
if(!good) SEND("CANID setter format: `canid=ID`, ID is 11bit\n");
}
SEND("canid="); printuhex(the_conf.CANID);
}
void inpause(_U_ char *txt){
ShowMsgs = FALSE;
}
void inresume(_U_ char *txt){
ShowMsgs = TRUE;
}
void delignlist(_U_ char *txt){
IgnSz = 0;
}
void bootldr(_U_ char *txt){
SEND("Go into DFU mode\n");
sendbuf();
Jump2Boot();
}
void getcounter(_U_ char *txt){
SEND("CR1="); printu(TIM1->CR1);
SEND("\nCR2="); printu(TIM2->CR1);
SEND("\nCR3="); printu(TIM3->CR1);
SEND("\nCNT1="); printu(TIM1->CNT);
SEND("\nCNT2="); printu(TIM2->CNT);
SEND("\nCNT3="); printu(TIM3->CNT);
NL();
}
void wdcheck(_U_ char *txt){
while(1){nop();}
}
typedef struct{
errcodes code;
const char *descr;
} codetext;
static const codetext errtxt[] = {
{ERR_OK, "all OK"},
{ERR_BADPAR, "wrong parameter's value"},
{ERR_BADVAL, "wrong setter of parameter"},
{ERR_WRONGLEN, "bad message length"},
{ERR_BADCMD, "unknown command"},
{ERR_CANTRUN, "temporary can't run given command"},
{-1, NULL}
};
void dumperrcodes(_U_ char *txt){
const codetext *c = errtxt;
SEND("Error codes:\n");
while(c->descr){
printu(c->code);
SEND(" - ");
SEND(c->descr);
newline();
++c;
}
sendbuf();
}
typedef void(*specfpointer)(char *arg);
enum{
SCMD_NONE, // omit zero
SCMD_IGNORE,
SCMD_DELIGNLIST,
SCMD_DFU,
SCMD_FILTER,
SCMD_CANSPEED,
SCMD_CANID,
SCMD_LISTFILTERS,
SCMD_IGNBUF,
SCMD_PAUSE,
SCMD_RESUME,
SCMD_SEND,
SCMD_DUMPCONF,
SCMD_GETCTR,
SCMD_WD,
SCMD_DUMPERR,
SCMD_DUMPCMD,
//SCMD_ST,
SCMD_AMOUNT
};
void dumpcmdcodes(_U_ char *txt);
static specfpointer speccmdlist[SCMD_AMOUNT] = {
[SCMD_IGNORE] = addIGN,
[SCMD_DELIGNLIST] = delignlist,
[SCMD_DFU] = bootldr,
[SCMD_FILTER] = add_filter,
[SCMD_CANSPEED] = CANini,
[SCMD_CANID] = canid,
[SCMD_LISTFILTERS] = list_filters,
[SCMD_IGNBUF] = print_ign_buf,
[SCMD_PAUSE] = inpause,
[SCMD_RESUME] = inresume,
[SCMD_SEND] = sendCANcommand,
[SCMD_DUMPCONF] = dump_userconf,
[SCMD_GETCTR] = getcounter,
[SCMD_WD] = wdcheck,
[SCMD_DUMPCMD] = dumpcmdcodes,
[SCMD_DUMPERR] = dumperrcodes,
//[SCMD_ST] = stp_check,
};
typedef struct{
int cmd_code; // CMD_... or <0 for usb-only commands
const char *command; // text command (up to 65536 commands)
const char *help; // help message for text protocol
} commands;
// the main commands list, index is CAN command code
static const commands textcommands[] = {
// different commands
{0, "", "Different commands:"}, // DELIMETERS
{CMD_ADC, "adc", "get ADC values"},
{CMD_BUTTONS, "button", "get buttons state"},
{CMD_BUZZER, "buzzer", "change buzzer state (1/0)"},
{CMD_ESWSTATE, "esw", "get end switches state"},
{CMD_EXT, "ext", "external outputs"},
{CMD_MCUT, "mcut", "get MCU T"},
{CMD_MCUVDD, "mcuvdd", "get MCU Vdd"},
{CMD_PING, "ping", "echo given command back"},
{CMD_PWM, "pwm", "pwm value"},
{CMD_RELAY, "relay", "change relay state (1/0)"},
{CMD_RESET, "reset", "reset MCU"},
{CMD_TIMEFROMSTART, "time", "get time from start"},
// configuration
{0, "", "Confuguration:"},
{CMD_ACCEL, "accel", "set/get accel/decel (steps/s^2)"},
{CMD_ENCREV, "encrev", "set/get max encoder's pulses per revolution"},
{CMD_ENCSTEPMAX, "encstepmax", "maximal encoder ticks per step"},
{CMD_ENCSTEPMIN, "encstepmin", "minimal encoder ticks per step"},
{CMD_ESWREACT, "eswreact", "end-switches reaction"},
{CMD_MAXSPEED, "maxspeed", "set/get max speed (steps per sec)"},
{CMD_MAXSTEPS, "maxsteps", "set/get max steps (from zero)"},
{CMD_MICROSTEPS, "microsteps", "set/get microsteps settings"},
{CMD_MINSPEED, "minspeed", "set/get min speed (steps per sec)"},
{CMD_MOTFLAGS, "motflags", "set/get motorN flags"},
{CMD_SAVECONF, "saveconf", "save current configuration"},
{CMD_SPEEDLIMIT, "speedlimit", "get limiting speed for current microsteps"},
// motors' commands
{0, "", "Motors' commands:"},
{CMD_ABSPOS, "abspos", "set/get position (in steps)"},
{CMD_EMERGSTOPALL, "emerg", "emergency stop all motors"},
{CMD_EMERGSTOP, "emstop", "emergency stop motor (right now)"},
{CMD_ENCPOS, "encpos", "set/get encoder's position"},
{CMD_GOTOZERO, "gotoz", "find zero position & refresh counters"},
{CMD_REINITMOTORS, "motreinit", "re-init motors after configuration changed"},
{CMD_RELPOS, "relpos", "set relative steps, get remaining"},
{CMD_RELSLOW, "relslow", "set relative steps @ lowest speed"},
{CMD_MOTORSTATE, "state", "get motor state"},
{CMD_STOP, "stop", "smooth motor stopping"},
// USB-only commands
{0, "", "USB-only commands:"},
{-SCMD_CANID, "canid", "get/set CAN ID"},
{-SCMD_CANSPEED, "canspeed", "CAN bus speed"},
{-SCMD_DELIGNLIST, "delignlist", "delete ignore list"},
{-SCMD_DFU, "dfu", "activate DFU mode"},
{-SCMD_DUMPERR, "dumperr", "dump error codes"},
{-SCMD_DUMPCMD, "dumpcmd", "dump command codes"},
{-SCMD_DUMPCONF, "dumpconf", "dump current configuration"},
{-SCMD_FILTER, "filter", "add/modify filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]"},
{-SCMD_GETCTR, "getctr", "get TIM1/2/3 counters"},
{-SCMD_IGNBUF, "ignbuf", "print ignore buffer"},
{-SCMD_IGNORE, "ignore", "add ID to ignore list (max 10 IDs)"},
{-SCMD_LISTFILTERS, "listfilters", "list all active filters"},
{-SCMD_PAUSE, "pause", "pause IN packets displaying"},
{-SCMD_RESUME, "resume", "resume IN packets displaying"},
{-SCMD_SEND, "send", "send data over CAN: send ID byte0 .. byteN"},
//{-SCMD_ST, "st", "check steppers"},
{-SCMD_WD, "wd", "check watchdog"},
{0, NULL, NULL}
};
void dumpcmdcodes(_U_ char *txt){
SEND("Commands list:\n");
for(uint16_t i = 0; i < CMD_AMOUNT; ++i){
printu(i);
SEND(" - ");
const commands *c = textcommands;
while(c->command){
if(c->cmd_code == i && *c->command){
SEND(c->help); break;
}
++c;
}
newline();
}
sendbuf();
}
/*
void stp_check(char *txt){
uint8_t N = *txt - '0';
if(N < 3){
MOTOR_EN(N);
MOTOR_CW(N);
mottimers[N]->ARR = 300;
mottimers[N]->CR1 |= TIM_CR1_CEN;
}else{
for(N = 0; N < 3; ++N){
MOTOR_DIS(N);
MOTOR_CCW(N);
mottimers[N]->CR1 &= ~TIM_CR1_CEN;
}
}
}*/
static void showHelp(){
SEND("https://github.com/eddyem/stm32samples/tree/master/F0-nolib/3steppersLB build#" BUILD_NUMBER " @ " BUILD_DATE "\n");
SEND("Common commands format is cmd[ N[ = val]]\n\twhere N is command argument (0..127), val is its value\n");
//SEND("Commands list:\n");
const commands *cmd = textcommands;
while(cmd->command){
if(*cmd->command){
bufputchar('\t');
SEND(cmd->command); /*SEND(" (");
if(cmd->cmd_code < 0) bufputchar('u');
else bufputchar('c');
SEND(") - ");*/
SEND(" - ");
}
SEND(cmd->help); newline();
++cmd;
}
sendbuf();
}
/**
* @brief cmd_parser - command parsing
* @param txt - buffer with commands & data (will be broken by this function!)
* @param isUSB - == 1 if data got from USB
* Common commands format: command [[N]=I], where
* command - one of `command` from `cmdlist`
* N - optional parameter (0..255)
* I - value (int32_t), need for setter
* Special commands format: s_command [text], where
* s_command - one of `spec_cmdlist`
* text - optional list of arguments
* The space after command name is mandatory (it will be substituted by \0)
*/
void cmd_parser(char *txt){
char cmd[32], *pcmd = cmd;
int i = 0;
char *eptr = omit_spaces(txt);
if(!*eptr) return;
while(*eptr && i < 30){
if(*eptr < 'a' || *eptr > 'z') break;
*pcmd++ = *eptr++;
++i;
}
*pcmd = 0;
if(cmd[0] == 0){ // empty command
showHelp();
return;
}
if(eptr && *eptr){
eptr = omit_spaces(eptr);
}
// find command
const commands *c = textcommands;
while(c->command){
if(0 == cmpstr(c->command, cmd)){
#ifdef EBUG
SEND("Find known command: "); SEND(cmd);
if(eptr && *eptr) SEND(", args: "); SEND(eptr);
NL();
#endif
if(c->cmd_code < 0){ // USB-only command
speccmdlist[-(c->cmd_code)](eptr);
}else{ // common command
uint8_t par = CANMESG_NOPAR;
int32_t val = 0;
if(eptr && *eptr){
char *nxt = getnum(eptr, &val);
if(nxt && nxt != eptr){ // command has parameter?
if(val < 0 || val >= CANMESG_NOPAR){
SEND("Command parameter should be 0..126!"); NL();
return;
}
par = (uint8_t)val;
}else nxt = eptr;
eptr = getchr(nxt, '=');
if(eptr){ // command has value?
eptr = omit_spaces(eptr + 1);
nxt = getnum(eptr, &val);
if(nxt != eptr){
par |= 0x80; // setter
}
}
}
// here we got command & ppar/pval -> call CMD
errcodes retcode = cmdlist[c->cmd_code](par, &val);
SEND(cmd);
par &= 0x7f;
if(par != CANMESG_NOPAR) printu(par);
bufputchar('='); printi(val);
SEND(" ("); printuhex((uint32_t)val); bufputchar(')');
if(ERR_OK != retcode){
SEND("\nERRCODE=");
printu(retcode);
}
}
NL();
return;
}
++c;
}
showHelp();
}
// print 32bit unsigned int
void printu(uint32_t val){
char buf[11], *bufptr = &buf[10];
*bufptr = 0;
if(!val){
*(--bufptr) = '0';
}else{
while(val){
register uint32_t o = val;
val /= 10;
*(--bufptr) = (o - 10*val) + '0';
}
}
addtobuf(bufptr);
}
void printi(int32_t val){
if(val < 0){
val = -val;
bufputchar('-');
}
printu((uint32_t)val);
}
// print 32bit unsigned int as hex
void printuhex(uint32_t val){
addtobuf("0x");
uint8_t *ptr = (uint8_t*)&val + 3;
int i, j, z = 1;
for(i = 0; i < 4; ++i, --ptr){
if(*ptr == 0){ // omit leading zeros
if(i == 3) z = 0;
if(z) continue;
}
else z = 0;
for(j = 1; j > -1; --j){
uint8_t half = (*ptr >> (4*j)) & 0x0f;
if(half < 10) bufputchar(half + '0');
else bufputchar(half - 10 + 'a');
}
}
}
// check Ignore_IDs & return 1 if ID isn't in list
uint8_t isgood(uint16_t ID){
for(int i = 0; i < IgnSz; ++i)
if(Ignore_IDs[i] == ID) return 0;
return 1;
}
char *omit_spaces(char *buf){
while(*buf){
if(*buf > ' ') break;
++buf;
}
return buf;
}
// THERE'S NO OVERFLOW PROTECTION IN NUMBER READ PROCEDURES!
// read decimal number
static char *getdec(const char *buf, int32_t *N){
int32_t num = 0;
int positive = TRUE;
if(*buf == '-'){
positive = FALSE;
++buf;
}
while(*buf){
char c = *buf;
if(c < '0' || c > '9'){
break;
}
num *= 10;
num += c - '0';
++buf;
}
*N = (positive) ? num : -num;
return (char *)buf;
}
// read hexadecimal number (without 0x prefix!)
static char *gethex(const char *buf, int32_t *N){
uint32_t num = 0;
while(*buf){
char c = *buf;
uint8_t M = 0;
if(c >= '0' && c <= '9'){
M = '0';
}else if(c >= 'A' && c <= 'F'){
M = 'A' - 10;
}else if(c >= 'a' && c <= 'f'){
M = 'a' - 10;
}
if(M){
num <<= 4;
num += c - M;
}else{
break;
}
++buf;
}
*N = (int32_t)num;
return (char *)buf;
}
// read binary number (without 0b prefix!)
static char *getbin(const char *buf, int32_t *N){
uint32_t num = 0;
while(*buf){
char c = *buf;
if(c < '0' || c > '1'){
break;
}
num <<= 1;
if(c == '1') num |= 1;
++buf;
}
*N = (int32_t)num;
return (char *)buf;
}
/**
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
* @param buf - buffer with number and so on
* @param N - the number read
* @return pointer to first non-number symbol in buf (if it is == buf, there's no number)
*/
char *getnum(char *txt, int32_t *N){
if(*txt == '0'){
if(txt[1] == 'x' || txt[1] == 'X') return gethex(txt+2, N);
if(txt[1] == 'b' || txt[1] == 'B') return getbin(txt+2, N);
}
return getdec(txt, N);
}

View File

@@ -0,0 +1,61 @@
/*
* This file is part of the 3steppers project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef STRFUNCT_H__
#define STRFUNCT_H__
#include "stm32f0.h"
#include "hardware.h"
#define BUFSZ (64)
// macro for static strings
#define SEND(str) do{addtobuf(str);}while(0)
#ifdef EBUG
#define DBG(str) do{addtobuf(__FILE__ " (L" STR(__LINE__) "): " str); NL();}while(0)
#else
#define DBG(str)
#endif
#define newline() do{bufputchar('\n');}while(0)
// newline & send buffer
#define NL() do{bufputchar('\n'); sendbuf();}while(0)
#define IGN_SIZE 10
extern uint16_t Ignore_IDs[IGN_SIZE];
extern uint8_t IgnSz;
extern uint8_t ShowMsgs;
void cmd_parser(char *buf);
void addtobuf(const char *txt);
void bufputchar(char ch);
void printu(uint32_t val);
void printi(int32_t val);
void printuhex(uint32_t val);
void sendbuf();
int cmpstr(const char *s1, const char *s2);
char *getchr(const char *str, char symbol);
char *omit_spaces(char *buf);
char *getnum(char *buf, int32_t *N);
uint8_t isgood(uint16_t ID);
#endif // STRFUNCT_H__

View File

@@ -0,0 +1,175 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "usb.h"
#include "usb_lib.h"
static volatile uint8_t tx_succesfull = 1;
static volatile uint8_t rxNE = 0;
// interrupt IN handler (never used?)
static void EP1_Handler(){
uint16_t epstatus = KEEP_DTOG(USB->EPnR[1]);
if(RX_FLAG(epstatus)) epstatus = (epstatus & ~USB_EPnR_STAT_TX) ^ USB_EPnR_STAT_RX; // set valid RX
else epstatus = epstatus & ~(USB_EPnR_STAT_TX|USB_EPnR_STAT_RX);
// clear CTR
epstatus = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX));
USB->EPnR[1] = epstatus;
}
// data IN/OUT handlers
static void transmit_Handler(){ // EP3IN
tx_succesfull = 1;
uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[3]);
// clear CTR keep DTOGs & STATs
USB->EPnR[3] = (epstatus & ~(USB_EPnR_CTR_TX)); // clear TX ctr
}
static void receive_Handler(){ // EP2OUT
rxNE = 1;
uint16_t epstatus = KEEP_DTOG_STAT(USB->EPnR[2]);
USB->EPnR[2] = (epstatus & ~(USB_EPnR_CTR_RX)); // clear RX ctr
}
void USB_setup(){
RCC->APB1ENR |= RCC_APB1ENR_CRSEN | RCC_APB1ENR_USBEN; // enable CRS (hsi48 sync) & USB
RCC->CFGR3 &= ~RCC_CFGR3_USBSW; // reset USB
RCC->CR2 |= RCC_CR2_HSI48ON; // turn ON HSI48
uint32_t tmout = 16000000;
while(!(RCC->CR2 & RCC_CR2_HSI48RDY)){if(--tmout == 0) break;}
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
CRS->CFGR &= ~CRS_CFGR_SYNCSRC;
CRS->CFGR |= CRS_CFGR_SYNCSRC_1; // USB SOF selected as sync source
CRS->CR |= CRS_CR_AUTOTRIMEN; // enable auto trim
CRS->CR |= CRS_CR_CEN; // enable freq counter & block CRS->CFGR as read-only
RCC->CFGR |= RCC_CFGR_SW;
// allow RESET and CTRM interrupts
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_WKUPM;
// clear flags
USB->ISTR = 0;
// and activate pullup
USB->BCDR |= USB_BCDR_DPPU;
NVIC_EnableIRQ(USB_IRQn);
}
static int usbwr(const uint8_t *buf, uint16_t l){
uint32_t ctra = 1000000;
while(--ctra && tx_succesfull == 0){
nop();
}
tx_succesfull = 0;
EP_Write(3, buf, l);
ctra = 1000000;
while(--ctra && tx_succesfull == 0){
nop();
}
if(tx_succesfull == 0){usbON = 0; return 1;} // usb is OFF?
return 0;
}
static uint8_t usbbuff[USB_TXBUFSZ-1]; // temporary buffer (63 - to prevent need of ZLP)
static uint8_t buflen = 0; // amount of symbols in usbbuff
// send next up to 63 bytes of data in usbbuff
static void send_next(){
if(!buflen || !tx_succesfull) return;
tx_succesfull = 0;
EP_Write(3, usbbuff, buflen);
buflen = 0;
}
// unblocking sending - just fill a buffer
void USB_send(const uint8_t *buf, uint16_t len){
if(!usbON || !len) return;
if(len > USB_TXBUFSZ-1 - buflen){
usbwr(usbbuff, buflen);
buflen = 0;
}
if(len > USB_TXBUFSZ-1){
USB_send_blk(buf, len);
return;
}
while(len--) usbbuff[buflen++] = *buf++;
}
// send zero-terminated string
void USB_sendstr(const char *str){
uint16_t l = 0;
const char *ptr = str;
while(*ptr++) ++l;
USB_send((uint8_t*)str, l);
}
// blocking sending
void USB_send_blk(const uint8_t *buf, uint16_t len){
if(!usbON || !len) return; // USB disconnected
if(buflen){
usbwr(usbbuff, buflen);
buflen = 0;
}
int needzlp = 0;
while(len){
if(len == USB_TXBUFSZ) needzlp = 1;
uint16_t s = (len > USB_TXBUFSZ) ? USB_TXBUFSZ : len;
if(usbwr(buf, s)) return;
len -= s;
buf += s;
}
if(needzlp){
usbwr(NULL, 0);
}
}
void usb_proc(){
switch(USB_Dev.USB_Status){
case USB_STATE_CONFIGURED:
// make new BULK endpoint
// Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features)
EP_Init(1, EP_TYPE_INTERRUPT, USB_EP1BUFSZ, 0, EP1_Handler); // IN1 - transmit
EP_Init(2, EP_TYPE_BULK, 0, USB_RXBUFSZ, receive_Handler); // OUT2 - receive data
EP_Init(3, EP_TYPE_BULK, USB_TXBUFSZ, 0, transmit_Handler); // IN3 - transmit data
USB_Dev.USB_Status = USB_STATE_CONNECTED;
break;
case USB_STATE_DEFAULT:
case USB_STATE_ADDRESSED:
if(usbON){
usbON = 0;
}
break;
default: // USB_STATE_CONNECTED - send next data portion
if(!usbON) return;
send_next();
}
}
/**
* @brief USB_receive
* @param buf (i) - buffer[64] for received data
* @return amount of received bytes
*/
uint8_t USB_receive(uint8_t *buf){
if(!usbON || !rxNE) return 0;
uint8_t sz = EP_Read(2, buf);
uint16_t epstatus = KEEP_DTOG(USB->EPnR[2]);
// keep stat_tx & set ACK rx
USB->EPnR[2] = (epstatus & ~(USB_EPnR_STAT_TX)) ^ USB_EPnR_STAT_RX;
rxNE = 0;
return sz;
}

View File

@@ -0,0 +1,37 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __USB_H__
#define __USB_H__
#include "hardware.h"
#define BUFFSIZE (64)
// send string with constant length
#define USND(str) do{USB_send((uint8_t*)str, sizeof(str)-1);}while(0)
void USB_setup();
void usb_proc();
void USB_send(const uint8_t *buf, uint16_t len);
void USB_sendstr(const char *str);
void USB_send_blk(const uint8_t *buf, uint16_t len);
uint8_t USB_receive(uint8_t *buf);
#endif // __USB_H__

View File

@@ -0,0 +1,99 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __USB_DEFS_H__
#define __USB_DEFS_H__
#include <stm32f0.h>
// max endpoints number
#define STM32ENDPOINTS 8
/**
* Buffers size definition
**/
// !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!!
#define USB_BTABLE_SIZE 768
// for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303)
#define USB_EP0_BUFSZ 64
// USB transmit buffer size (64 for PL2303)
#define USB_TXBUFSZ 64
// USB receive buffer size (64 for PL2303)
#define USB_RXBUFSZ 64
// EP1 - interrupt - buffer size
#define USB_EP1BUFSZ 8
#define USB_BTABLE_BASE 0x40006000
#ifdef USB_BTABLE
#undef USB_BTABLE
#endif
#define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE))
#define USB_ISTR_EPID 0x0000000F
#define USB_FNR_LSOF_0 0x00000800
#define USB_FNR_lSOF_1 0x00001000
#define USB_LPMCSR_BESL_0 0x00000010
#define USB_LPMCSR_BESL_1 0x00000020
#define USB_LPMCSR_BESL_2 0x00000040
#define USB_LPMCSR_BESL_3 0x00000080
#define USB_EPnR_CTR_RX 0x00008000
#define USB_EPnR_DTOG_RX 0x00004000
#define USB_EPnR_STAT_RX 0x00003000
#define USB_EPnR_STAT_RX_0 0x00001000
#define USB_EPnR_STAT_RX_1 0x00002000
#define USB_EPnR_SETUP 0x00000800
#define USB_EPnR_EP_TYPE 0x00000600
#define USB_EPnR_EP_TYPE_0 0x00000200
#define USB_EPnR_EP_TYPE_1 0x00000400
#define USB_EPnR_EP_KIND 0x00000100
#define USB_EPnR_CTR_TX 0x00000080
#define USB_EPnR_DTOG_TX 0x00000040
#define USB_EPnR_STAT_TX 0x00000030
#define USB_EPnR_STAT_TX_0 0x00000010
#define USB_EPnR_STAT_TX_1 0x00000020
#define USB_EPnR_EA 0x0000000F
#define USB_COUNTn_RX_BLSIZE 0x00008000
#define USB_COUNTn_NUM_BLOCK 0x00007C00
#define USB_COUNTn_RX 0x0000003F
#define USB_TypeDef USB_TypeDef_custom
typedef struct{
__IO uint32_t EPnR[STM32ENDPOINTS];
__IO uint32_t RESERVED[STM32ENDPOINTS];
__IO uint32_t CNTR;
__IO uint32_t ISTR;
__IO uint32_t FNR;
__IO uint32_t DADDR;
__IO uint32_t BTABLE;
__IO uint32_t LPMCSR;
__IO uint32_t BCDR;
} USB_TypeDef;
typedef struct{
__IO uint16_t USB_ADDR_TX;
__IO uint16_t USB_COUNT_TX;
__IO uint16_t USB_ADDR_RX;
__IO uint16_t USB_COUNT_RX;
} USB_EPDATA_TypeDef;
typedef struct{
__IO USB_EPDATA_TypeDef EP[STM32ENDPOINTS];
} USB_BtableDef;
#endif // __USB_DEFS_H__

View File

@@ -0,0 +1,468 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include "usb_lib.h"
ep_t endpoints[STM32ENDPOINTS];
usb_dev_t USB_Dev;
uint8_t usbON = 0;
static usb_LineCoding lineCoding = {115200, 0, 0, 8};
static config_pack_t setup_packet;
static uint8_t ep0databuf[EP0DATABUF_SIZE];
static uint8_t ep0dbuflen = 0;
usb_LineCoding getLineCoding(){return lineCoding;}
// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor
#define bcdUSB_L 0x10
#define bcdUSB_H 0x01
#define bDeviceClass 0
#define bDeviceSubClass 0
#define bDeviceProtocol 0
#define bNumConfigurations 1
static const uint8_t USB_DeviceDescriptor[] = {
18, // bLength
0x01, // bDescriptorType - Device descriptor
bcdUSB_L, // bcdUSB_L - 1.10
bcdUSB_H, // bcdUSB_H
bDeviceClass, // bDeviceClass - USB_COMM
bDeviceSubClass, // bDeviceSubClass
bDeviceProtocol, // bDeviceProtocol
USB_EP0_BUFSZ, // bMaxPacketSize
0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303
0x06, // idVendor_H
0x03, // idProduct_L
0x23, // idProduct_H
0x00, // bcdDevice_Ver_L
0x03, // bcdDevice_Ver_H
0x01, // iManufacturer
0x02, // iProduct
0x00, // iSerialNumber
bNumConfigurations // bNumConfigurations
};
static const uint8_t USB_DeviceQualifierDescriptor[] = {
10, //bLength
0x06, // bDescriptorType - Device qualifier
bcdUSB_L, // bcdUSB_L
bcdUSB_H, // bcdUSB_H
bDeviceClass, // bDeviceClass
bDeviceSubClass, // bDeviceSubClass
bDeviceProtocol, // bDeviceProtocol
USB_EP0_BUFSZ, // bMaxPacketSize0
bNumConfigurations, // bNumConfigurations
0x00 // Reserved
};
static const uint8_t USB_ConfigDescriptor[] = {
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
0x02, /* bDescriptorType: Configuration */
39, /* wTotalLength:no of returned bytes */
0x00,
0x01, /* bNumInterfaces: 1 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xa0, /* bmAttributes - Bus powered, Remote wakeup */
0x32, /* MaxPower 100 mA */
/*---------------------------------------------------------------------------*/
/*Interface Descriptor */
0x09, /* bLength: Interface Descriptor size */
0x04, /* bDescriptorType: Interface */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x03, /* bNumEndpoints: 3 endpoints used */
0xff, /* bInterfaceClass */
0x00, /* bInterfaceSubClass */
0x00, /* bInterfaceProtocol */
0x00, /* iInterface: */
///////////////////////////////////////////////////
/*Endpoint 1 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
0x05, /* bDescriptorType: Endpoint */
0x81, /* bEndpointAddress IN1 */
0x03, /* bmAttributes: Interrupt */
0x0a, /* wMaxPacketSize LO: */
0x00, /* wMaxPacketSize HI: */
0x01, /* bInterval: */
/*Endpoint OUT2 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
0x05, /* bDescriptorType: Endpoint */
0x02, /* bEndpointAddress: OUT2 */
0x02, /* bmAttributes: Bulk */
(USB_RXBUFSZ & 0xff), /* wMaxPacketSize: 64 */
(USB_RXBUFSZ >> 8),
0x00, /* bInterval: ignore for Bulk transfer */
/*Endpoint IN3 Descriptor*/
0x07, /* bLength: Endpoint Descriptor size */
0x05, /* bDescriptorType: Endpoint */
0x83, /* bEndpointAddress IN3 */
0x02, /* bmAttributes: Bulk */
(USB_TXBUFSZ & 0xff), /* wMaxPacketSize: 64 */
(USB_TXBUFSZ >> 8),
0x00, /* bInterval: ignore for Bulk transfer */
};
_USB_LANG_ID_(USB_StringLangDescriptor, LANG_US);
// these descriptors are not used in PL2303 emulator!
_USB_STRING_(USB_StringSerialDescriptor, u"0");
_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.");
_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller");
/*
* default handlers
*/
// SET_LINE_CODING
void WEAK linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){
}
// SET_CONTROL_LINE_STATE
void WEAK clstate_handler(uint16_t __attribute__((unused)) val){
}
// SEND_BREAK
void WEAK break_handler(){
}
// handler of vendor requests
void WEAK vendor_handler(config_pack_t *packet){
if(packet->bmRequestType & 0x80){ // read
uint8_t c;
switch(packet->wValue){
case 0x8484:
c = 2;
break;
case 0x0080:
c = 1;
break;
case 0x8686:
c = 0xaa;
break;
default:
c = 0;
}
EP_WriteIRQ(0, &c, 1);
}else{ // write ZLP
EP_WriteIRQ(0, (uint8_t *)0, 0);
}
}
static void wr0(const uint8_t *buf, uint16_t size){
if(setup_packet.wLength < size) size = setup_packet.wLength; // shortened request
if(size < endpoints[0].txbufsz){
EP_WriteIRQ(0, buf, size);
return;
}
while(size){
uint16_t l = size;
if(l > endpoints[0].txbufsz) l = endpoints[0].txbufsz;
EP_WriteIRQ(0, buf, l);
buf += l;
size -= l;
uint8_t needzlp = (l == endpoints[0].txbufsz) ? 1 : 0;
if(size || needzlp){ // send last data buffer
uint16_t status = KEEP_DTOG(USB->EPnR[0]);
// keep DTOGs, clear CTR_RX,TX, set TX VALID, leave stat_Rx
USB->EPnR[0] = (status & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX|USB_EPnR_STAT_RX))
^ USB_EPnR_STAT_TX;
uint32_t ctr = 1000000;
while(--ctr && (USB->ISTR & USB_ISTR_CTR) == 0){nop();}
if((USB->ISTR & USB_ISTR_CTR) == 0){
return;
}
if(needzlp) EP_WriteIRQ(0, (uint8_t*)0, 0);
}
}
}
static inline void get_descriptor(){
switch(setup_packet.wValue){
case DEVICE_DESCRIPTOR:
wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
break;
case CONFIGURATION_DESCRIPTOR:
wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
break;
case STRING_LANG_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE);
break;
case STRING_MAN_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength);
break;
case STRING_PROD_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength);
break;
case STRING_SN_DESCRIPTOR:
wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength);
break;
case DEVICE_QUALIFIER_DESCRIPTOR:
wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]);
break;
default:
break;
}
}
static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured)
static inline void std_d2h_req(){
uint16_t status = 0; // bus powered
switch(setup_packet.bRequest){
case GET_DESCRIPTOR:
get_descriptor();
break;
case GET_STATUS:
EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered
break;
case GET_CONFIGURATION:
EP_WriteIRQ(0, &configuration, 1);
break;
default:
break;
}
}
static inline void std_h2d_req(){
switch(setup_packet.bRequest){
case SET_ADDRESS:
// new address will be assigned later - after acknowlegement or request to host
USB_Dev.USB_Addr = setup_packet.wValue;
break;
case SET_CONFIGURATION:
// Now device configured
USB_Dev.USB_Status = USB_STATE_CONFIGURED;
configuration = setup_packet.wValue;
break;
default:
break;
}
}
/*
bmRequestType: 76543210
7 direction: 0 - host->device, 1 - device->host
65 type: 0 - standard, 1 - class, 2 - vendor
4..0 getter: 0 - device, 1 - interface, 2 - endpoint, 3 - other
*/
/**
* Endpoint0 (control) handler
*/
static void EP0_Handler(){
uint16_t epstatus = USB->EPnR[0]; // EP0R on input -> return this value after modifications
uint8_t reqtype = setup_packet.bmRequestType & 0x7f;
uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0;
int rxflag = RX_FLAG(epstatus);
if(rxflag && SETUP_FLAG(epstatus)){
switch(reqtype){
case STANDARD_DEVICE_REQUEST_TYPE: // standard device request
if(dev2host){
std_d2h_req();
}else{
std_h2d_req();
EP_WriteIRQ(0, (uint8_t *)0, 0);
}
break;
case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request
if(setup_packet.bRequest == CLEAR_FEATURE){
EP_WriteIRQ(0, (uint8_t *)0, 0);
}
break;
case VENDOR_REQUEST_TYPE:
vendor_handler(&setup_packet);
break;
case CONTROL_REQUEST_TYPE:
switch(setup_packet.bRequest){
case GET_LINE_CODING:
EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding));
break;
case SET_LINE_CODING: // omit this for next stage, when data will come
break;
case SET_CONTROL_LINE_STATE:
usbON = 1;
clstate_handler(setup_packet.wValue);
break;
case SEND_BREAK:
usbON = 0;
break_handler();
break;
default:
break;
}
if(setup_packet.bRequest != GET_LINE_CODING) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement
break;
default:
EP_WriteIRQ(0, (uint8_t *)0, 0);
}
}else if(rxflag){ // got data over EP0 or host acknowlegement
if(endpoints[0].rx_cnt){
if(setup_packet.bRequest == SET_LINE_CODING){
linecoding_handler((usb_LineCoding*)ep0databuf);
}
}
} else if(TX_FLAG(epstatus)){ // package transmitted
// now we can change address after enumeration
if ((USB->DADDR & USB_DADDR_ADD) != USB_Dev.USB_Addr){
USB->DADDR = USB_DADDR_EF | USB_Dev.USB_Addr;
// change state to ADRESSED
USB_Dev.USB_Status = USB_STATE_ADDRESSED;
}
}
epstatus = KEEP_DTOG(USB->EPnR[0]);
if(rxflag) epstatus ^= USB_EPnR_STAT_TX; // start ZLP/data transmission
else epstatus &= ~USB_EPnR_STAT_TX; // or leave unchanged
// keep DTOGs, clear CTR_RX,TX, set RX VALID
USB->EPnR[0] = (epstatus & ~(USB_EPnR_CTR_RX|USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_RX;
}
static uint16_t lastaddr = LASTADDR_DEFAULT;
/**
* Endpoint initialisation
* !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!!
* @param number - EP num (0...7)
* @param type - EP type (EP_TYPE_BULK, EP_TYPE_CONTROL, EP_TYPE_ISO, EP_TYPE_INTERRUPT)
* @param txsz - transmission buffer size @ USB/CAN buffer
* @param rxsz - reception buffer size @ USB/CAN buffer
* @param uint16_t (*func)(ep_t *ep) - EP handler function
* @return 0 if all OK
*/
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)()){
if(number >= STM32ENDPOINTS) return 4; // out of configured amount
if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large
if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable
USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA);
USB->EPnR[number] ^= USB_EPnR_STAT_RX | USB_EPnR_STAT_TX_1;
if(rxsz & 1 || rxsz > 512) return 3; // wrong rx buffer size
uint16_t countrx = 0;
if(rxsz < 64) countrx = rxsz / 2;
else{
if(rxsz & 0x1f) return 3; // should be multiple of 32
countrx = 31 + rxsz / 32;
}
USB_BTABLE->EP[number].USB_ADDR_TX = lastaddr;
endpoints[number].tx_buf = (uint16_t *)(USB_BTABLE_BASE + lastaddr);
endpoints[number].txbufsz = txsz;
lastaddr += txsz;
USB_BTABLE->EP[number].USB_COUNT_TX = 0;
USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr;
endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr);
lastaddr += rxsz;
// buffer size: Table127 of RM
USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10;
endpoints[number].func = func;
return 0;
}
// standard IRQ handler
void usb_isr(){
if (USB->ISTR & USB_ISTR_RESET){
// Reinit registers
USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
USB->ISTR = 0;
// Endpoint 0 - CONTROL
// ON USB LS size of EP0 may be 8 bytes, but on FS it should be 64 bytes!
lastaddr = LASTADDR_DEFAULT; // roll back to beginning of buffer
EP_Init(0, EP_TYPE_CONTROL, USB_EP0_BUFSZ, USB_EP0_BUFSZ, EP0_Handler);
// clear address, leave only enable bit
USB->DADDR = USB_DADDR_EF;
// state is default - wait for enumeration
USB_Dev.USB_Status = USB_STATE_DEFAULT;
}
if(USB->ISTR & USB_ISTR_CTR){
// EP number
uint8_t n = USB->ISTR & USB_ISTR_EPID;
// copy status register
uint16_t epstatus = USB->EPnR[n];
// copy received bytes amount
endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter
// check direction
if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit)
if(n == 0){ // control endpoint
if(epstatus & USB_EPnR_SETUP){ // setup packet -> copy data to conf_pack
EP_Read(0, (uint8_t*)&setup_packet);
ep0dbuflen = 0;
// interrupt handler will be called later
}else if(epstatus & USB_EPnR_CTR_RX){ // data packet -> push received data to ep0databuf
ep0dbuflen = endpoints[0].rx_cnt;
EP_Read(0, (uint8_t*)&ep0databuf);
}
}
}
// call EP handler
if(endpoints[n].func) endpoints[n].func(endpoints[n]);
}
if(USB->ISTR & USB_ISTR_SUSP){ // suspend -> still no connection, may sleep
usbON = 0;
USB->CNTR |= USB_CNTR_FSUSP | USB_CNTR_LPMODE;
USB->ISTR = ~USB_ISTR_SUSP;
}
if(USB->ISTR & USB_ISTR_WKUP){ // wakeup
USB->CNTR &= ~(USB_CNTR_FSUSP | USB_CNTR_LPMODE); // clear suspend flags
USB->ISTR = ~USB_ISTR_WKUP;
}
}
/**
* Write data to EP buffer (called from IRQ handler)
* @param number - EP number
* @param *buf - array with data
* @param size - its size
*/
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){
uint8_t i;
if(size > USB_TXBUFSZ) size = USB_TXBUFSZ;
uint16_t N2 = (size + 1) >> 1;
// the buffer is 16-bit, so we should copy data as it would be uint16_t
uint16_t *buf16 = (uint16_t *)buf;
for (i = 0; i < N2; i++){
endpoints[number].tx_buf[i] = buf16[i];
}
USB_BTABLE->EP[number].USB_COUNT_TX = size;
}
/**
* Write data to EP buffer (called outside IRQ handler)
* @param number - EP number
* @param *buf - array with data
* @param size - its size
*/
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size){
EP_WriteIRQ(number, buf, size);
uint16_t status = KEEP_DTOG(USB->EPnR[number]);
// keep DTOGs, clear CTR_TX & set TX VALID to start transmission
USB->EPnR[number] = (status & ~(USB_EPnR_CTR_TX)) ^ USB_EPnR_STAT_TX;
}
/*
* Copy data from EP buffer into user buffer area
* @param *buf - user array for data
* @return amount of data read
*/
int EP_Read(uint8_t number, uint8_t *buf){
int n = endpoints[number].rx_cnt;
if(n){
for(int i = 0; i < n; ++i)
buf[i] = endpoints[number].rx_buf[i];
}
return n;
}

View File

@@ -0,0 +1,184 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef __USB_LIB_H__
#define __USB_LIB_H__
#include <wchar.h>
#include "usb_defs.h"
#define EP0DATABUF_SIZE (64)
#define LASTADDR_DEFAULT (STM32ENDPOINTS * 8)
// bmRequestType & 0x7f
#define STANDARD_DEVICE_REQUEST_TYPE 0
#define STANDARD_ENDPOINT_REQUEST_TYPE 2
#define VENDOR_REQUEST_TYPE 0x40
#define CONTROL_REQUEST_TYPE 0x21
// bRequest, standard; for bmRequestType == 0x80
#define GET_STATUS 0x00
#define GET_DESCRIPTOR 0x06
#define GET_CONFIGURATION 0x08
// for bmRequestType == 0
#define CLEAR_FEATURE 0x01
#define SET_FEATURE 0x03 // unused
#define SET_ADDRESS 0x05
#define SET_DESCRIPTOR 0x07 // unused
#define SET_CONFIGURATION 0x09
// for bmRequestType == 0x81, 1 or 0xB2
#define GET_INTERFACE 0x0A // unused
#define SET_INTERFACE 0x0B // unused
#define SYNC_FRAME 0x0C // unused
#define VENDOR_REQUEST 0x01 // unused
// Class-Specific Control Requests
#define SEND_ENCAPSULATED_COMMAND 0x00 // unused
#define GET_ENCAPSULATED_RESPONSE 0x01 // unused
#define SET_COMM_FEATURE 0x02 // unused
#define GET_COMM_FEATURE 0x03 // unused
#define CLEAR_COMM_FEATURE 0x04 // unused
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
#define SEND_BREAK 0x23
// control line states
#define CONTROL_DTR 0x01
#define CONTROL_RTS 0x02
// wValue
#define DEVICE_DESCRIPTOR 0x100
#define CONFIGURATION_DESCRIPTOR 0x200
#define STRING_LANG_DESCRIPTOR 0x300
#define STRING_MAN_DESCRIPTOR 0x301
#define STRING_PROD_DESCRIPTOR 0x302
#define STRING_SN_DESCRIPTOR 0x303
#define DEVICE_QUALIFIER_DESCRIPTOR 0x600
#define RX_FLAG(epstat) (epstat & USB_EPnR_CTR_RX)
#define TX_FLAG(epstat) (epstat & USB_EPnR_CTR_TX)
#define SETUP_FLAG(epstat) (epstat & USB_EPnR_SETUP)
// EPnR bits manipulation
#define KEEP_DTOG_STAT(EPnR) (EPnR & ~(USB_EPnR_STAT_RX|USB_EPnR_STAT_TX|USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX))
#define KEEP_DTOG(EPnR) (EPnR & ~(USB_EPnR_DTOG_RX|USB_EPnR_DTOG_TX))
// USB state: uninitialized, addressed, ready for use, client connected
typedef enum{
USB_STATE_DEFAULT,
USB_STATE_ADDRESSED,
USB_STATE_CONFIGURED,
USB_STATE_CONNECTED
} USB_state;
// EP types
#define EP_TYPE_BULK 0x00
#define EP_TYPE_CONTROL 0x01
#define EP_TYPE_ISO 0x02
#define EP_TYPE_INTERRUPT 0x03
#define LANG_US (uint16_t)0x0409
#define _USB_STRING_(name, str) \
static const struct name \
{ \
uint8_t bLength; \
uint8_t bDescriptorType; \
uint16_t bString[(sizeof(str) - 2) / 2]; \
\
} \
name = {sizeof(name), 0x03, str}
#define _USB_LANG_ID_(name, lng_id) \
\
static const struct name \
{ \
uint8_t bLength; \
uint8_t bDescriptorType; \
uint16_t bString; \
\
} \
name = {0x04, 0x03, lng_id}
#define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4)
// EP0 configuration packet
typedef struct {
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} config_pack_t;
// endpoints state
typedef struct __ep_t{
uint16_t *tx_buf; // transmission buffer address
uint16_t txbufsz; // transmission buffer size
uint8_t *rx_buf; // reception buffer address
void (*func)(); // endpoint action function
uint16_t rx_cnt; // received data counter
} ep_t;
// USB status & its address
typedef struct {
uint8_t USB_Status;
uint16_t USB_Addr;
}usb_dev_t;
typedef struct {
uint32_t dwDTERate;
uint8_t bCharFormat;
#define USB_CDC_1_STOP_BITS 0
#define USB_CDC_1_5_STOP_BITS 1
#define USB_CDC_2_STOP_BITS 2
uint8_t bParityType;
#define USB_CDC_NO_PARITY 0
#define USB_CDC_ODD_PARITY 1
#define USB_CDC_EVEN_PARITY 2
#define USB_CDC_MARK_PARITY 3
#define USB_CDC_SPACE_PARITY 4
uint8_t bDataBits;
} __attribute__ ((packed)) usb_LineCoding;
typedef struct {
uint8_t bmRequestType;
uint8_t bNotificationType;
uint16_t wValue;
uint16_t wIndex;
uint16_t wLength;
} __attribute__ ((packed)) usb_cdc_notification;
extern ep_t endpoints[];
extern usb_dev_t USB_Dev;
extern uint8_t usbON;
void USB_Init();
uint8_t USB_GetState();
int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, void (*func)());
void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size);
void EP_Write(uint8_t number, const uint8_t *buf, uint16_t size);
int EP_Read(uint8_t number, uint8_t *buf);
usb_LineCoding getLineCoding();
void linecoding_handler(usb_LineCoding *lc);
void clstate_handler(uint16_t val);
void break_handler();
void vendor_handler(config_pack_t *packet);
#endif // __USB_LIB_H__

View File

@@ -0,0 +1,2 @@
#define BUILD_NUMBER "139"
#define BUILD_DATE "2021-12-02"

Binary file not shown.

View File

@@ -0,0 +1 @@
Rx RS485 должен быть в режиме подтяжки к плюсу!

View File

@@ -0,0 +1,3 @@
# CAN bus stepper controller
Move one stepper (12..36V) by CAN or USB bus.

View File

@@ -0,0 +1,22 @@
EESchema-LIBRARY Version 2.3 Date: Sun 04 May 2014 09:27:50 PM MSK
#encoding utf-8
#
# ACS712
#
DEF ACS712 U 0 40 Y Y 1 F N
F0 "U" 0 300 60 H V C CNN
F1 "ACS712" 0 -350 60 H V C CNN
DRAW
S -450 250 450 -300 0 1 0 N
X IP+ 1 -550 150 300 R 50 50 1 1 I
X IP+ 2 -550 50 300 R 50 50 1 1 I
X IP- 3 -550 -100 300 R 50 50 1 1 I
X IP- 4 -550 -200 300 R 50 50 1 1 I
X GND 5 550 -200 300 L 50 50 1 1 I
X FILTER 6 550 -100 300 L 50 50 1 1 I
X VIOUT 7 550 50 300 L 50 50 1 1 I
X Vcc 8 550 150 300 L 50 50 1 1 I
ENDDRAW
ENDDEF
#
#End Library

View File

@@ -0,0 +1,190 @@
EESchema-LIBRARY Version 2.3
#encoding utf-8
#
# 74HC4051
#
DEF 74HC4051 U 0 10 Y Y 1 F N
F0 "U" 0 0 50 H V C CNN
F1 "74HC4051" 0 -150 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
$FPLIST
SO16
TSSOP16
SSOP16
DHVQFN16
$ENDFPLIST
DRAW
S -400 450 400 -450 0 1 0 N
X Y4 1 700 -50 300 L 50 50 1 1 B
X Y6 2 700 -250 300 L 50 50 1 1 B
X Z 3 0 -750 300 U 50 50 1 1 B
X Y7 4 700 -350 300 L 50 50 1 1 B
X Y5 5 700 -150 300 L 50 50 1 1 B
X ~E 6 -700 -350 300 R 50 50 1 1 I I
X VEE 7 -700 0 300 R 50 50 1 1 W
X GND 8 -700 -200 300 R 50 50 1 1 W
X S2 9 -700 150 300 R 50 50 1 1 I
X S1 10 -700 250 300 R 50 50 1 1 I
X S0 11 -700 350 300 R 50 50 1 1 I
X Y3 12 700 50 300 L 50 50 1 1 B
X Y0 13 700 350 300 L 50 50 1 1 B
X Y1 14 700 250 300 L 50 50 1 1 B
X Y2 15 700 150 300 L 50 50 1 1 B
X VCC 16 -700 -100 300 R 50 50 1 1 W
ENDDRAW
ENDDEF
#
# D_Schottky_x2_ACom_AKK
#
DEF D_Schottky_x2_ACom_AKK D 0 30 Y N 1 F N
F0 "D" 50 -100 50 H V C CNN
F1 "D_Schottky_x2_ACom_AKK" 0 100 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
DRAW
P 2 0 1 0 -140 0 150 0 N
P 2 0 1 0 0 0 0 -100 N
P 3 0 1 8 -150 50 -150 -50 -150 -50 N
P 3 0 1 8 150 50 150 -50 150 -50 N
P 4 0 1 8 -150 50 -170 50 -170 40 -170 40 N
P 4 0 1 8 150 -50 170 -50 170 -40 170 -40 N
P 4 0 1 8 150 50 130 50 130 40 130 40 N
P 5 0 1 8 -130 -40 -130 -50 -150 -50 -150 -50 -150 -50 N
P 6 0 1 8 -50 -50 -150 0 -50 50 -50 -50 -50 -50 -50 -50 N
P 6 0 1 8 50 50 150 0 50 -50 50 50 50 50 50 50 N
X A 1 0 -200 100 U 50 50 0 1 P
X K 2 -300 0 150 R 50 50 0 1 P
X K 3 300 0 150 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# LM1117-ADJ
#
DEF LM1117-ADJ U 0 30 Y Y 1 F N
F0 "U" 100 -250 50 H V C CNN
F1 "LM1117-ADJ" 0 250 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
ALIAS LM1117-1.8 LM1117-2.5 LM1117-3.3 LM1117-5.0
$FPLIST
SOT-223*
TO-263*
TO-252*
$ENDFPLIST
DRAW
S -200 -200 200 200 0 1 10 f
X GND/ADJ 1 0 -300 100 U 50 50 1 1 W
X VO 2 300 0 100 L 50 50 1 1 w
X VI 3 -300 0 100 R 50 50 1 1 W
ENDDRAW
ENDDEF
#
# PESD1CAN
#
DEF PESD1CAN D 0 30 Y N 1 F N
F0 "D" 0 -350 50 H V C CNN
F1 "PESD1CAN" 50 150 50 H V C CNN
F2 "" 0 0 50 H V C CNN
F3 "" 0 0 50 H V C CNN
$FPLIST
SOT23
$ENDFPLIST
DRAW
S -200 100 300 -300 0 1 0 N
P 2 0 1 0 -140 -200 150 -200 N
P 2 0 1 0 -140 0 150 0 N
P 3 0 1 8 -150 -150 -150 -250 -150 -250 N
P 3 0 1 8 -150 50 -150 -50 -150 -50 N
P 3 0 1 8 150 -150 150 -250 150 -250 N
P 3 0 1 8 150 50 150 -50 150 -50 N
P 4 0 1 8 -150 -150 -170 -150 -170 -160 -170 -160 N
P 4 0 1 8 -150 50 -170 50 -170 40 -170 40 N
P 4 0 1 8 150 -250 170 -250 170 -240 170 -240 N
P 4 0 1 8 150 -150 130 -150 130 -160 130 -160 N
P 4 0 1 8 150 -50 170 -50 170 -40 170 -40 N
P 4 0 1 0 150 0 250 0 250 -200 150 -200 N
P 4 0 1 8 150 50 130 50 130 40 130 40 N
P 5 0 1 8 -130 -240 -130 -250 -150 -250 -150 -250 -150 -250 N
P 5 0 1 8 -130 -40 -130 -50 -150 -50 -150 -50 -150 -50 N
P 6 0 1 8 -50 -250 -150 -200 -50 -150 -50 -250 -50 -250 -50 -250 N
P 6 0 1 8 -50 -50 -150 0 -50 50 -50 -50 -50 -50 -50 -50 N
P 6 0 1 8 50 -150 150 -200 50 -250 50 -150 50 -150 50 -150 N
P 6 0 1 8 50 50 150 0 50 -50 50 50 50 50 50 50 N
X K 1 -300 0 150 R 50 50 0 1 P
X K 2 -300 -200 150 R 50 50 0 1 P
X O 3 400 -100 150 L 50 50 0 1 P
ENDDRAW
ENDDEF
#
# TPS2051
#
DEF TPS2051 U 0 40 Y Y 1 F N
F0 "U" 0 -300 60 H V C CNN
F1 "TPS2051" 0 300 60 H V C CNN
F2 "" 0 0 60 H I C CNN
F3 "" 0 0 60 H I C CNN
DRAW
S -250 250 250 -250 0 1 0 N
X GND 1 -450 150 200 R 50 50 1 1 W
X IN 2 -450 50 200 R 50 50 1 1 W
X IN 3 -450 -50 200 R 50 50 1 1 P
X EN 4 -450 -150 200 R 50 50 1 1 I
X ~OC 5 450 -150 200 L 50 50 1 1 O
X OUT 6 450 -50 200 L 50 50 1 1 P
X OUT 7 450 50 200 L 50 50 1 1 P
X OUT 8 450 150 200 L 50 50 1 1 w
ENDDRAW
ENDDEF
#
# USB6B1
#
DEF USB6B1 D 0 30 Y N 1 F N
F0 "D" 0 -450 50 H V C CNN
F1 "USB6B1" 0 400 50 H V C CNN
F2 "" 200 -100 50 V V C CNN
F3 "" 200 -100 50 V V C CNN
$FPLIST
SO8
$ENDFPLIST
DRAW
C -150 -300 7 0 1 0 N
C -150 100 7 0 1 0 N
C -150 300 7 0 1 0 N
C 0 -300 7 0 1 0 N
C 0 -100 7 0 1 0 N
C 0 300 7 0 1 0 N
C 200 -300 7 0 1 0 N
C 200 300 7 0 1 0 N
S -300 -100 300 -100 0 1 0 N
S -300 300 300 300 0 1 0 N
S -200 -150 -100 -150 0 1 0 N
S -200 250 -100 250 0 1 0 N
S -150 300 -150 -300 0 1 0 N
S -50 -150 50 -150 0 1 0 N
S -50 250 50 250 0 1 0 N
S 0 300 0 -300 0 1 0 N
S 200 300 200 -300 0 1 0 N
S 300 -300 -300 -300 0 1 0 N
S 300 100 -300 100 0 1 0 N
P 3 0 1 8 150 50 250 50 250 50 N
P 4 0 1 8 150 50 150 30 160 30 160 30 N
P 4 0 1 8 250 50 250 70 240 70 240 70 N
P 5 0 1 0 -250 350 300 350 300 -350 -250 -350 -250 350 N
P 6 0 1 8 -200 -250 -150 -150 -100 -250 -200 -250 -200 -250 -200 -250 N
P 6 0 1 8 -200 150 -150 250 -100 150 -200 150 -200 150 -200 150 N
P 6 0 1 8 -50 -250 0 -150 50 -250 -50 -250 -50 -250 -50 -250 N
P 6 0 1 8 -50 150 0 250 50 150 -50 150 -50 150 -50 150 N
P 6 0 1 8 150 -50 200 50 250 -50 150 -50 150 -50 150 -50 N
X VCC 1 -500 300 200 R 50 50 1 1 P
X I/O1 2 -500 100 200 R 50 50 1 1 P
X I/O2 3 -500 -100 200 R 50 50 1 1 P
X GND 4 -500 -300 200 R 50 50 1 1 P
X GND 5 500 -300 200 L 50 50 1 1 P
X I/O2 6 500 -100 200 L 50 50 1 1 P
X I/O1 7 500 100 200 L 50 50 1 1 P
X VCC 8 500 300 200 L 50 50 1 1 P
ENDDRAW
ENDDEF
#
#End Library

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
(fp_lib_table
(lib (name TestPoint)(type KiCad)(uri ${KISYSMOD}/TestPoint.pretty)(options "")(descr ""))
(lib (name Fuse)(type KiCad)(uri ${KISYSMOD}/Fuse.pretty)(options "")(descr ""))
(lib (name MyFootprints)(type KiCad)(uri /home/eddy/Docs/SAO/ELECTRONICS/STM32/F0-srcs/CANbus_stepper/my_footprints.pretty)(options "")(descr ""))
(lib (name Connector_Dsub)(type KiCad)(uri /usr/share/kicad/kicad-footprints/Connector_Dsub.pretty)(options "")(descr ""))
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,5.1.4*
G04 #@! TF.CreationDate,2020-02-05T09:24:40+03:00*
G04 #@! TF.ProjectId,stm32,73746d33-322e-46b6-9963-61645f706362,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Profile,NP*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW 5.1.4) date 2020-02-05 09:24:40*
%MOMM*%
%LPD*%
G04 APERTURE LIST*
%ADD10C,0.150000*%
G04 APERTURE END LIST*
D10*
X80500000Y-117500000D02*
X174000000Y-117500000D01*
X174000000Y-62500000D02*
X80500000Y-62500000D01*
X82166666Y-62500000D02*
G75*
G03X82166666Y-62500000I-1666666J0D01*
G01*
X78000000Y-62500000D02*
X83000000Y-62500000D01*
X80500000Y-60000000D02*
X80500000Y-65000000D01*
X80500000Y-117500000D02*
X80500000Y-62500000D01*
X174000000Y-62500000D02*
X174000000Y-117500000D01*
M02*

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
(module FuseHolder (layer F.Cu) (tedit 5E318B39)
(fp_text reference REF** (at 0 4.4) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value FuseHolder (at -0.1 -0.1) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -9.9 3.4) (end -9.9 -3.4) (layer F.SilkS) (width 0.15))
(fp_line (start 9.9 3.4) (end -9.9 3.4) (layer F.SilkS) (width 0.15))
(fp_line (start 9.9 -3.4) (end 9.9 3.4) (layer F.SilkS) (width 0.15))
(fp_line (start -9.9 -3.4) (end 9.9 -3.4) (layer F.SilkS) (width 0.15))
(pad 1 thru_hole oval (at 6.95 -1.75) (size 4 2.5) (drill oval 1.7 0.6) (layers *.Cu *.Mask))
(pad 1 thru_hole oval (at 6.95 1.75) (size 4 2.5) (drill oval 1.7 0.6) (layers *.Cu *.Mask))
(pad 2 thru_hole oval (at -6.95 1.75) (size 4 2.5) (drill oval 1.7 0.6) (layers *.Cu *.Mask))
(pad 2 thru_hole oval (at -6.95 -1.75) (size 4 2.5) (drill oval 1.7 0.6) (layers *.Cu *.Mask))
)

View File

@@ -0,0 +1,9 @@
(module Hole_3mm (layer F.Cu) (tedit 5913F6E4)
(fp_text reference REF** (at 0 3.81) (layer F.SilkS) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value Hole_3mm (at 0 -7.62) (layer F.Fab) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 thru_hole circle (at 0 0) (size 5 5) (drill 3) (layers *.Cu *.Mask))
)

View File

@@ -0,0 +1,31 @@
(module RJ9-4P4C (layer F.Cu) (tedit 555F7A30)
(fp_text reference J** (at 0 -10.1346) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value RJ9-4P4C (at 0 10.2108) (layer F.Fab) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end -0.25 0) (layer F.CrtYd) (width 0.05))
(fp_line (start -5.84 -9.25) (end 5.84 -9.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 5.84 -9.25) (end 5.84 9.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 5.84 9.25) (end -5.84 9.25) (layer F.CrtYd) (width 0.05))
(fp_line (start -5.84 9.25) (end -5.84 -9.25) (layer F.CrtYd) (width 0.05))
(fp_line (start 0 -0.35) (end 0 0.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -0.35 0) (end 0.35 0) (layer F.CrtYd) (width 0.05))
(fp_line (start -5.59 9) (end -5.59 -9) (layer F.Fab) (width 0.12))
(fp_line (start -5.59 -9) (end 5.59 -9) (layer F.Fab) (width 0.12))
(fp_line (start 5.59 -9) (end 5.59 9) (layer F.Fab) (width 0.12))
(fp_line (start 5.59 9) (end -5.59 9) (layer F.Fab) (width 0.12))
(fp_line (start -5.59 8.8) (end -5.59 -9) (layer F.SilkS) (width 0.12))
(fp_line (start -5.59 -9) (end 5.59 -9) (layer F.SilkS) (width 0.12))
(fp_line (start 5.59 -9) (end 5.59 8.8) (layer F.SilkS) (width 0.12))
(fp_circle (center 3.81 1.15) (end 5.75 1.15) (layer B.CrtYd) (width 0.05))
(fp_circle (center -3.81 1.15) (end -5.75 1.15) (layer B.CrtYd) (width 0.05))
(fp_circle (center -1.905 -6.12) (end -1.805 -6.12) (layer F.SilkS) (width 0.2))
(pad 1 thru_hole circle (at -1.905 -5.2) (size 1.2 1.2) (drill 0.8) (layers *.Cu *.Mask))
(pad 2 thru_hole circle (at -0.635 -7.74) (size 1.2 1.2) (drill 0.8) (layers *.Cu *.Mask))
(pad 3 thru_hole circle (at 0.635 -5.2) (size 1.2 1.2) (drill 0.8) (layers *.Cu *.Mask))
(pad 4 thru_hole circle (at 1.905 -7.74) (size 1.2 1.2) (drill 0.8) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at -3.81 1.15) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask))
(pad "" np_thru_hole circle (at 3.81 1.15) (size 3.2 3.2) (drill 3.2) (layers *.Cu *.Mask))
)

View File

@@ -0,0 +1,12 @@
(module SMD_conn_4x2.5mm (layer F.Cu) (tedit 58B86145)
(fp_text reference REF** (at 0 3.81) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value SMD_conn_4x2.5mm (at 0 -3.81) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 smd rect (at -3.81 0) (size 1.5 5) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at -1.27 0) (size 1.5 5) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at 1.27 0) (size 1.5 5) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at 3.81 0) (size 1.5 5) (layers F.Cu F.Paste F.Mask))
)

View File

@@ -0,0 +1,10 @@
(module TH_via (layer F.Cu) (tedit 5A5E619A)
(fp_text reference REF** (at 0 0.5) (layer F.SilkS) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value TH_via (at 0 -0.5) (layer F.Fab) hide
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 1 thru_hole circle (at 0 0) (size 1.5 1.5) (drill 0.8) (layers *.Cu *.Mask)
(zone_connect 1))
)

View File

@@ -0,0 +1,122 @@
"Source:","/home/eddy/Yandex.Disk/Projects/stm32samples/F0-nolib/CANbus_stepper/kicad/stm32.sch"
"Date:","÷Ô 10 ÍÁÒ 2020 09:31:14"
"Tool:","Eeschema 5.1.4"
"Generator:","/usr/local/share/kicad/plugins/bom_csv_grouped_by_value.py"
"Component Count:","66"
"Individual Components:"
"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet"
"","","C1","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C2","100uF","Device:CP","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","~"
"","","C3","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C4","47uF, 10V","Device:CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","~"
"","","C5","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C6","47uF, 10V","Device:CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","~"
"","","C7","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C8","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C9","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C10","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C11","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","C12","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","D1","MBRS130L","Device:D_Schottky","Diode_SMD:D_SMB_Handsoldering",""
"","","D2","MBRS130L","Device:D_Schottky","Diode_SMD:D_SMB_Handsoldering",""
"","","D3","PESD3V3L4UG","Power_Protection:PESD3V3L4UG","TO_SOT_Packages_SMD:SOT-363_SC-70-6_Handsoldering","https://assets.nexperia.com/documents/data-sheet/PESDXL4UF_G_W.pdf"
"","","D4","PESD1CAN","elements:PESD1CAN","TO_SOT_Packages_SMD:SOT-23_Handsoldering",""
"","","D5","MM3Z7V5","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~"
"","","D6","USB6B1","Power_Protection:USB6B1","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",""
"","","D7","MM3Z3V9","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder",""
"","","D8","MM3Z3V9","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder",""
"","","F1","1A","Device:Fuse","MyFootprints:FuseHolder","~"
"","","J1","A","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J2","B","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J3","Conn_01x08_Female","Connector:Conn_01x08_Female","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","~"
"","","J4","Conn_01x08_Female","Connector:Conn_01x08_Female","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","~"
"","","J5","+/-","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J6","CONN_02X03","Switch:SW_DIP_x04","Button_Switch_THT:SW_DIP_SPSTx04_Slide_9.78x12.34mm_W7.62mm_P2.54mm",""
"","","J7","0/1","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J8","2/3","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J9","DB9_Female","Connector:DB9_Female","Connector_Dsub:DSUB-9_Female_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm",""
"","","J10","12v","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J11","DB9_Male","Connector:DB9_Male","Connector_Dsub:DSUB-9_Male_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm",""
"","","J12","RS-485","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"","","J13","Conn_01x06","Connector_Generic:Conn_01x06","Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Vertical","~"
"","","P1","USB_A","Connector:USB_B","Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal",""
"","","P2","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3",""
"","","P3","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3",""
"","","P4","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3",""
"","","P5","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3",""
"","","Q1","SI2305","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","~"
"","","Q2","AO3407","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering",""
"","","R1","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R2","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R3","120","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R4","15k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R5","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R6","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R7","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R8","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R9","120","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R10","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","R11","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R12","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R13","220k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R14","56k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R15","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R16","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R17","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"","","R18","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"","","SW1","SW_DIP_x01","Switch:SW_DIP_x01","Button_Switch_THT:SW_DIP_SPSTx01_Slide_6.7x4.1mm_W7.62mm_P2.54mm_LowProfile","~"
"","","U1","ISO1050DUB","Interface_CAN_LIN:ISO1050DUB","Package_SO:SOP-8_6.62x9.15mm_P2.54mm","http://www.ti.com/lit/ds/symlink/iso1050.pdf"
"","","U2","LM1117-5.0","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2",""
"","","U3","LM1117-3.3","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2",""
"","","U4","MCP2551-I/SN","Interface_CAN_LIN:MCP2551-I-SN","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",""
"","","U5","STM32F072CBTx","MCU_ST_STM32F0:STM32F072CBTx","Package_QFP:LQFP-48_7x7mm_P0.5mm","http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf"
"","","U6","MAX3485","Interface_UART:MAX3485","Package_SO:SO-8_3.9x4.9mm_P1.27mm","https://datasheets.maximintegrated.com/en/ds/MAX3483-MAX3491.pdf"
"Collated Components:"
"Item","Qty","Reference(s)","Value","LibPart","Footprint","Datasheet"
"1","9","C1, C3, C5, C7, C8, C9, C10, C11, C12","0.1","Device:C","Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"2","1","C2","100uF","Device:CP","Capacitor_THT:CP_Radial_D8.0mm_P3.50mm","~"
"3","2","C4, C6","47uF, 10V","Device:CP","Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder","~"
"4","2","D1, D2","MBRS130L","Device:D_Schottky","Diode_SMD:D_SMB_Handsoldering",""
"5","1","D3","PESD3V3L4UG","Power_Protection:PESD3V3L4UG","TO_SOT_Packages_SMD:SOT-363_SC-70-6_Handsoldering","https://assets.nexperia.com/documents/data-sheet/PESDXL4UF_G_W.pdf"
"6","1","D4","PESD1CAN","elements:PESD1CAN","TO_SOT_Packages_SMD:SOT-23_Handsoldering",""
"7","1","D5","MM3Z7V5","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder","~"
"8","1","D6","USB6B1","Power_Protection:USB6B1","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",""
"9","2","D7, D8","MM3Z3V9","Device:D_Zener","Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder",""
"10","1","F1","1A","Device:Fuse","MyFootprints:FuseHolder","~"
"11","1","J1","A","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"12","1","J2","B","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"13","2","J3, J4","Conn_01x08_Female","Connector:Conn_01x08_Female","Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical","~"
"14","1","J5","+/-","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"15","1","J6","CONN_02X03","Switch:SW_DIP_x04","Button_Switch_THT:SW_DIP_SPSTx04_Slide_9.78x12.34mm_W7.62mm_P2.54mm",""
"16","1","J7","0/1","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"17","1","J8","2/3","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"18","1","J9","DB9_Female","Connector:DB9_Female","Connector_Dsub:DSUB-9_Female_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm",""
"19","1","J10","12v","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"20","1","J11","DB9_Male","Connector:DB9_Male","Connector_Dsub:DSUB-9_Male_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm",""
"21","1","J12","RS-485","Connector:Screw_Terminal_01x02","TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal",""
"22","1","J13","Conn_01x06","Connector_Generic:Conn_01x06","Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Vertical","~"
"23","1","P1","USB_A","Connector:USB_B","Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal",""
"24","4","P2, P3, P4, P5","Hole","Connector_Generic:Conn_01x01","MountingHole:MountingHole_3.2mm_M3",""
"25","1","Q1","SI2305","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering","~"
"26","1","Q2","AO3407","Device:Q_PMOS_GSD","TO_SOT_Packages_SMD:SOT-23_Handsoldering",""
"27","5","R1, R5, R6, R7, R8","330","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"28","2","R2, R10","10k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"29","2","R3, R9","120","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"30","1","R4","15k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"31","3","R11, R12, R18","22","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder","~"
"32","1","R13","220k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"33","1","R14","56k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"34","3","R15, R16, R17","47k","Device:R","Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder",""
"35","1","SW1","SW_DIP_x01","Switch:SW_DIP_x01","Button_Switch_THT:SW_DIP_SPSTx01_Slide_6.7x4.1mm_W7.62mm_P2.54mm_LowProfile","~"
"36","1","U1","ISO1050DUB","Interface_CAN_LIN:ISO1050DUB","Package_SO:SOP-8_6.62x9.15mm_P2.54mm","http://www.ti.com/lit/ds/symlink/iso1050.pdf"
"37","1","U2","LM1117-5.0","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2",""
"38","1","U3","LM1117-3.3","Regulator_Linear:LM1117-3.3","TO_SOT_Packages_SMD:SOT-223-3_TabPin2",""
"39","1","U4","MCP2551-I/SN","Interface_CAN_LIN:MCP2551-I-SN","Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",""
"40","1","U5","STM32F072CBTx","MCU_ST_STM32F0:STM32F072CBTx","Package_QFP:LQFP-48_7x7mm_P0.5mm","http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf"
"41","1","U6","MAX3485","Interface_UART:MAX3485","Package_SO:SO-8_3.9x4.9mm_P1.27mm","https://datasheets.maximintegrated.com/en/ds/MAX3483-MAX3491.pdf"
1 Source: /home/eddy/Yandex.Disk/Projects/stm32samples/F0-nolib/CANbus_stepper/kicad/stm32.sch
2 Date: ÷Ô 10 ÍÁÒ 2020 09:31:14
3 Tool: Eeschema 5.1.4
4 Generator: /usr/local/share/kicad/plugins/bom_csv_grouped_by_value.py
5 Component Count: 66
6 Individual Components:
7 Item Qty Reference(s) Value LibPart Footprint Datasheet
8 C1 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
9 C2 100uF Device:CP Capacitor_THT:CP_Radial_D8.0mm_P3.50mm ~
10 C3 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
11 C4 47uF, 10V Device:CP Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder ~
12 C5 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
13 C6 47uF, 10V Device:CP Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder ~
14 C7 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
15 C8 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
16 C9 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
17 C10 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
18 C11 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
19 C12 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
20 D1 MBRS130L Device:D_Schottky Diode_SMD:D_SMB_Handsoldering
21 D2 MBRS130L Device:D_Schottky Diode_SMD:D_SMB_Handsoldering
22 D3 PESD3V3L4UG Power_Protection:PESD3V3L4UG TO_SOT_Packages_SMD:SOT-363_SC-70-6_Handsoldering https://assets.nexperia.com/documents/data-sheet/PESDXL4UF_G_W.pdf
23 D4 PESD1CAN elements:PESD1CAN TO_SOT_Packages_SMD:SOT-23_Handsoldering
24 D5 MM3Z7V5 Device:D_Zener Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder ~
25 D6 USB6B1 Power_Protection:USB6B1 Package_SO:SOIC-8_3.9x4.9mm_P1.27mm
26 D7 MM3Z3V9 Device:D_Zener Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder
27 D8 MM3Z3V9 Device:D_Zener Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder
28 F1 1A Device:Fuse MyFootprints:FuseHolder ~
29 J1 A Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
30 J2 B Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
31 J3 Conn_01x08_Female Connector:Conn_01x08_Female Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical ~
32 J4 Conn_01x08_Female Connector:Conn_01x08_Female Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical ~
33 J5 +/- Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
34 J6 CONN_02X03 Switch:SW_DIP_x04 Button_Switch_THT:SW_DIP_SPSTx04_Slide_9.78x12.34mm_W7.62mm_P2.54mm
35 J7 0/1 Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
36 J8 2/3 Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
37 J9 DB9_Female Connector:DB9_Female Connector_Dsub:DSUB-9_Female_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm
38 J10 12v Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
39 J11 DB9_Male Connector:DB9_Male Connector_Dsub:DSUB-9_Male_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm
40 J12 RS-485 Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
41 J13 Conn_01x06 Connector_Generic:Conn_01x06 Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Vertical ~
42 P1 USB_A Connector:USB_B Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal
43 P2 Hole Connector_Generic:Conn_01x01 MountingHole:MountingHole_3.2mm_M3
44 P3 Hole Connector_Generic:Conn_01x01 MountingHole:MountingHole_3.2mm_M3
45 P4 Hole Connector_Generic:Conn_01x01 MountingHole:MountingHole_3.2mm_M3
46 P5 Hole Connector_Generic:Conn_01x01 MountingHole:MountingHole_3.2mm_M3
47 Q1 SI2305 Device:Q_PMOS_GSD TO_SOT_Packages_SMD:SOT-23_Handsoldering ~
48 Q2 AO3407 Device:Q_PMOS_GSD TO_SOT_Packages_SMD:SOT-23_Handsoldering
49 R1 330 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
50 R2 10k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
51 R3 120 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
52 R4 15k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
53 R5 330 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
54 R6 330 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
55 R7 330 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
56 R8 330 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
57 R9 120 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
58 R10 10k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
59 R11 22 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
60 R12 22 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
61 R13 220k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
62 R14 56k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
63 R15 47k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
64 R16 47k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
65 R17 47k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
66 R18 22 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
67 SW1 SW_DIP_x01 Switch:SW_DIP_x01 Button_Switch_THT:SW_DIP_SPSTx01_Slide_6.7x4.1mm_W7.62mm_P2.54mm_LowProfile ~
68 U1 ISO1050DUB Interface_CAN_LIN:ISO1050DUB Package_SO:SOP-8_6.62x9.15mm_P2.54mm http://www.ti.com/lit/ds/symlink/iso1050.pdf
69 U2 LM1117-5.0 Regulator_Linear:LM1117-3.3 TO_SOT_Packages_SMD:SOT-223-3_TabPin2
70 U3 LM1117-3.3 Regulator_Linear:LM1117-3.3 TO_SOT_Packages_SMD:SOT-223-3_TabPin2
71 U4 MCP2551-I/SN Interface_CAN_LIN:MCP2551-I-SN Package_SO:SOIC-8_3.9x4.9mm_P1.27mm
72 U5 STM32F072CBTx MCU_ST_STM32F0:STM32F072CBTx Package_QFP:LQFP-48_7x7mm_P0.5mm http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf
73 U6 MAX3485 Interface_UART:MAX3485 Package_SO:SO-8_3.9x4.9mm_P1.27mm https://datasheets.maximintegrated.com/en/ds/MAX3483-MAX3491.pdf
74 Collated Components:
75 Item Qty Reference(s) Value LibPart Footprint Datasheet
76 1 9 C1, C3, C5, C7, C8, C9, C10, C11, C12 0.1 Device:C Capacitor_SMD:C_0603_1608Metric_Pad1.05x0.95mm_HandSolder
77 2 1 C2 100uF Device:CP Capacitor_THT:CP_Radial_D8.0mm_P3.50mm ~
78 3 2 C4, C6 47uF, 10V Device:CP Capacitor_Tantalum_SMD:CP_EIA-6032-28_Kemet-C_Pad2.25x2.35mm_HandSolder ~
79 4 2 D1, D2 MBRS130L Device:D_Schottky Diode_SMD:D_SMB_Handsoldering
80 5 1 D3 PESD3V3L4UG Power_Protection:PESD3V3L4UG TO_SOT_Packages_SMD:SOT-363_SC-70-6_Handsoldering https://assets.nexperia.com/documents/data-sheet/PESDXL4UF_G_W.pdf
81 6 1 D4 PESD1CAN elements:PESD1CAN TO_SOT_Packages_SMD:SOT-23_Handsoldering
82 7 1 D5 MM3Z7V5 Device:D_Zener Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder ~
83 8 1 D6 USB6B1 Power_Protection:USB6B1 Package_SO:SOIC-8_3.9x4.9mm_P1.27mm
84 9 2 D7, D8 MM3Z3V9 Device:D_Zener Diode_SMD:D_0805_2012Metric_Pad1.15x1.40mm_HandSolder
85 10 1 F1 1A Device:Fuse MyFootprints:FuseHolder ~
86 11 1 J1 A Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
87 12 1 J2 B Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
88 13 2 J3, J4 Conn_01x08_Female Connector:Conn_01x08_Female Connector_PinSocket_2.54mm:PinSocket_1x08_P2.54mm_Vertical ~
89 14 1 J5 +/- Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
90 15 1 J6 CONN_02X03 Switch:SW_DIP_x04 Button_Switch_THT:SW_DIP_SPSTx04_Slide_9.78x12.34mm_W7.62mm_P2.54mm
91 16 1 J7 0/1 Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
92 17 1 J8 2/3 Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
93 18 1 J9 DB9_Female Connector:DB9_Female Connector_Dsub:DSUB-9_Female_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm
94 19 1 J10 12v Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
95 20 1 J11 DB9_Male Connector:DB9_Male Connector_Dsub:DSUB-9_Male_Horizontal_P2.77x2.84mm_EdgePinOffset4.94mm_Housed_MountingHolesOffset7.48mm
96 21 1 J12 RS-485 Connector:Screw_Terminal_01x02 TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2_1x02_P5.00mm_Horizontal
97 22 1 J13 Conn_01x06 Connector_Generic:Conn_01x06 Connector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_Vertical ~
98 23 1 P1 USB_A Connector:USB_B Connectors_USB:USB_B_OST_USB-B1HSxx_Horizontal
99 24 4 P2, P3, P4, P5 Hole Connector_Generic:Conn_01x01 MountingHole:MountingHole_3.2mm_M3
100 25 1 Q1 SI2305 Device:Q_PMOS_GSD TO_SOT_Packages_SMD:SOT-23_Handsoldering ~
101 26 1 Q2 AO3407 Device:Q_PMOS_GSD TO_SOT_Packages_SMD:SOT-23_Handsoldering
102 27 5 R1, R5, R6, R7, R8 330 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
103 28 2 R2, R10 10k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
104 29 2 R3, R9 120 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
105 30 1 R4 15k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
106 31 3 R11, R12, R18 22 Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder ~
107 32 1 R13 220k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
108 33 1 R14 56k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
109 34 3 R15, R16, R17 47k Device:R Resistor_SMD:R_0603_1608Metric_Pad1.05x0.95mm_HandSolder
110 35 1 SW1 SW_DIP_x01 Switch:SW_DIP_x01 Button_Switch_THT:SW_DIP_SPSTx01_Slide_6.7x4.1mm_W7.62mm_P2.54mm_LowProfile ~
111 36 1 U1 ISO1050DUB Interface_CAN_LIN:ISO1050DUB Package_SO:SOP-8_6.62x9.15mm_P2.54mm http://www.ti.com/lit/ds/symlink/iso1050.pdf
112 37 1 U2 LM1117-5.0 Regulator_Linear:LM1117-3.3 TO_SOT_Packages_SMD:SOT-223-3_TabPin2
113 38 1 U3 LM1117-3.3 Regulator_Linear:LM1117-3.3 TO_SOT_Packages_SMD:SOT-223-3_TabPin2
114 39 1 U4 MCP2551-I/SN Interface_CAN_LIN:MCP2551-I-SN Package_SO:SOIC-8_3.9x4.9mm_P1.27mm
115 40 1 U5 STM32F072CBTx MCU_ST_STM32F0:STM32F072CBTx Package_QFP:LQFP-48_7x7mm_P0.5mm http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00090510.pdf
116 41 1 U6 MAX3485 Interface_UART:MAX3485 Package_SO:SO-8_3.9x4.9mm_P1.27mm https://datasheets.maximintegrated.com/en/ds/MAX3483-MAX3491.pdf

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
update=Пн 03 фев 2020 17:18:45
version=1
last_client=kicad
[cvpcb]
version=1
NetIExt=net
[general]
version=1
[eeschema]
version=1
LibDir=
[schematic_editor]
version=1
PageLayoutDescrFile=
PlotDirectoryName=
SubpartIdSeparator=46
SubpartFirstId=49
NetFmtName=Pcbnew
SpiceAjustPassiveValues=0
LabSize=50
ERC_TestSimilarLabels=1
[pcbnew]
version=1
PageLayoutDescrFile=
LastNetListRead=stm32.net
CopperLayerCount=2
BoardThickness=2.5
AllowMicroVias=0
AllowBlindVias=0
RequireCourtyardDefinitions=0
ProhibitOverlappingCourtyards=1
MinTrackWidth=0.2
MinViaDiameter=0.7999999999999999
MinViaDrill=0.5
MinMicroViaDiameter=0.2
MinMicroViaDrill=0.09999999999999999
MinHoleToHole=0.25
TrackWidth1=0.2
TrackWidth2=0.2
TrackWidth3=0.3
TrackWidth4=0.5
TrackWidth5=1
TrackWidth6=2
ViaDiameter1=1
ViaDrill1=0.6
ViaDiameter2=1
ViaDrill2=0.6
ViaDiameter3=1.5
ViaDrill3=0.8
dPairWidth1=0.2
dPairGap1=0.25
dPairViaGap1=0.25
SilkLineWidth=0.15
SilkTextSizeV=1
SilkTextSizeH=1
SilkTextSizeThickness=0.15
SilkTextItalic=0
SilkTextUpright=1
CopperLineWidth=0.2
CopperTextSizeV=1.5
CopperTextSizeH=1.5
CopperTextThickness=0.3
CopperTextItalic=0
CopperTextUpright=1
EdgeCutLineWidth=0.15
CourtyardLineWidth=0.05
OthersLineWidth=0.15
OthersTextSizeV=1
OthersTextSizeH=1
OthersTextSizeThickness=0.15
OthersTextItalic=0
OthersTextUpright=1
SolderMaskClearance=0.2
SolderMaskMinWidth=0
SolderPasteClearance=0
SolderPasteRatio=-0
[pcbnew/Layer.F.Cu]
Name=F.Cu
Type=0
Enabled=1
[pcbnew/Layer.In1.Cu]
Name=In1.Cu
Type=0
Enabled=0
[pcbnew/Layer.In2.Cu]
Name=In2.Cu
Type=0
Enabled=0
[pcbnew/Layer.In3.Cu]
Name=In3.Cu
Type=0
Enabled=0
[pcbnew/Layer.In4.Cu]
Name=In4.Cu
Type=0
Enabled=0
[pcbnew/Layer.In5.Cu]
Name=In5.Cu
Type=0
Enabled=0
[pcbnew/Layer.In6.Cu]
Name=In6.Cu
Type=0
Enabled=0
[pcbnew/Layer.In7.Cu]
Name=In7.Cu
Type=0
Enabled=0
[pcbnew/Layer.In8.Cu]
Name=In8.Cu
Type=0
Enabled=0
[pcbnew/Layer.In9.Cu]
Name=In9.Cu
Type=0
Enabled=0
[pcbnew/Layer.In10.Cu]
Name=In10.Cu
Type=0
Enabled=0
[pcbnew/Layer.In11.Cu]
Name=In11.Cu
Type=0
Enabled=0
[pcbnew/Layer.In12.Cu]
Name=In12.Cu
Type=0
Enabled=0
[pcbnew/Layer.In13.Cu]
Name=In13.Cu
Type=0
Enabled=0
[pcbnew/Layer.In14.Cu]
Name=In14.Cu
Type=0
Enabled=0
[pcbnew/Layer.In15.Cu]
Name=In15.Cu
Type=0
Enabled=0
[pcbnew/Layer.In16.Cu]
Name=In16.Cu
Type=0
Enabled=0
[pcbnew/Layer.In17.Cu]
Name=In17.Cu
Type=0
Enabled=0
[pcbnew/Layer.In18.Cu]
Name=In18.Cu
Type=0
Enabled=0
[pcbnew/Layer.In19.Cu]
Name=In19.Cu
Type=0
Enabled=0
[pcbnew/Layer.In20.Cu]
Name=In20.Cu
Type=0
Enabled=0
[pcbnew/Layer.In21.Cu]
Name=In21.Cu
Type=0
Enabled=0
[pcbnew/Layer.In22.Cu]
Name=In22.Cu
Type=0
Enabled=0
[pcbnew/Layer.In23.Cu]
Name=In23.Cu
Type=0
Enabled=0
[pcbnew/Layer.In24.Cu]
Name=In24.Cu
Type=0
Enabled=0
[pcbnew/Layer.In25.Cu]
Name=In25.Cu
Type=0
Enabled=0
[pcbnew/Layer.In26.Cu]
Name=In26.Cu
Type=0
Enabled=0
[pcbnew/Layer.In27.Cu]
Name=In27.Cu
Type=0
Enabled=0
[pcbnew/Layer.In28.Cu]
Name=In28.Cu
Type=0
Enabled=0
[pcbnew/Layer.In29.Cu]
Name=In29.Cu
Type=0
Enabled=0
[pcbnew/Layer.In30.Cu]
Name=In30.Cu
Type=0
Enabled=0
[pcbnew/Layer.B.Cu]
Name=B.Cu
Type=0
Enabled=1
[pcbnew/Layer.B.Adhes]
Enabled=1
[pcbnew/Layer.F.Adhes]
Enabled=1
[pcbnew/Layer.B.Paste]
Enabled=1
[pcbnew/Layer.F.Paste]
Enabled=1
[pcbnew/Layer.B.SilkS]
Enabled=1
[pcbnew/Layer.F.SilkS]
Enabled=1
[pcbnew/Layer.B.Mask]
Enabled=1
[pcbnew/Layer.F.Mask]
Enabled=1
[pcbnew/Layer.Dwgs.User]
Enabled=1
[pcbnew/Layer.Cmts.User]
Enabled=1
[pcbnew/Layer.Eco1.User]
Enabled=1
[pcbnew/Layer.Eco2.User]
Enabled=1
[pcbnew/Layer.Edge.Cuts]
Enabled=1
[pcbnew/Layer.Margin]
Enabled=1
[pcbnew/Layer.B.CrtYd]
Enabled=1
[pcbnew/Layer.F.CrtYd]
Enabled=1
[pcbnew/Layer.B.Fab]
Enabled=1
[pcbnew/Layer.F.Fab]
Enabled=1
[pcbnew/Layer.Rescue]
Enabled=0
[pcbnew/Netclasses]
[pcbnew/Netclasses/Default]
Name=Default
Clearance=0.2
TrackWidth=0.2
ViaDiameter=1
ViaDrill=0.6
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/1]
Name=0.5
Clearance=0.3
TrackWidth=0.5
ViaDiameter=1
ViaDrill=0.6
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25
[pcbnew/Netclasses/2]
Name=1
Clearance=0.5
TrackWidth=1
ViaDiameter=1.5
ViaDrill=0.8
uViaDiameter=0.3
uViaDrill=0.1
dPairWidth=0.2
dPairGap=0.25
dPairViaGap=0.25

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
(sym_lib_table
(lib (name elements)(type Legacy)(uri ${KIPRJMOD}/elements.lib)(options "")(descr ""))
)

Binary file not shown.

View File

@@ -0,0 +1,155 @@
# make debug adds -DEBUG -Werror
# make ADDEFS="additional defs"
BINARY = canstepper
BOOTPORT ?= /dev/ttyUSB0
BOOTSPEED ?= 115200
# MCU FAMILY
FAMILY ?= F0
# MCU code (STM32F072xx)
MCU ?= F072xB
# change this linking script depending on particular MCU model,
LDSCRIPT ?= stm32f0728.ld
DEFS = ${ADDEFS} -DVERSION=\"0.0.1\" -DUSARTNUM=1
TARGET := RELEASE
FP_FLAGS ?= -msoft-float
ASM_FLAGS ?= -mthumb -mcpu=cortex-m0 -march=armv6-m -mtune=cortex-m0
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
###############################################################################
# Executables
#PREFIX ?= arm-none-eabi
# gcc from arm web site
PREFIX ?= /opt/bin/arm-none-eabi
RM := rm -f
RMDIR := rmdir
CC := $(PREFIX)-gcc
LD := $(PREFIX)-gcc
AR := $(PREFIX)-ar
AS := $(PREFIX)-as
SIZE := $(PREFIX)-size
OBJCOPY := $(PREFIX)-objcopy
OBJDUMP := $(PREFIX)-objdump
GDB := $(PREFIX)-gdb
STFLASH := $(shell which st-flash)
STBOOT := $(shell which stm32flash)
DFUUTIL := $(shell which dfu-util)
###############################################################################
# Source files
OBJDIR = mk
SRC := $(wildcard *.c)
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
STARTUP = $(OBJDIR)/startup.o
OBJS += $(STARTUP)
# dependencies: we need them to recompile files if their headers-dependencies changed
DEPS := $(OBJS:.o=.d)
INC_DIR ?= ../../inc
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
LIB_DIR := $(INC_DIR)/ld
###############################################################################
# C flags
CFLAGS += -O2 -g -MD -D__thumb2__=1
CFLAGS += -Wall -Wextra -Wshadow
CFLAGS += -fno-common -ffunction-sections -fdata-sections
###############################################################################
# Linker flags
LDFLAGS += --static -nostartfiles --specs=nano.specs
LDFLAGS += -L$(LIB_DIR)
LDFLAGS += -T$(LDSCRIPT)
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map
LDFLAGS += -Wl,--gc-sections
###############################################################################
# Used libraries
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU)
ELF := $(OBJDIR)/$(BINARY).elf
LIST := $(OBJDIR)/$(BINARY).list
BIN := $(BINARY).bin
HEX := $(BINARY).hex
all: $(OBJDIR)/RELEASE bin list size
release: all
debug: CFLAGS += -DEBUG -Werror -W -Wimplicit-function-declaration
debug: $(OBJDIR)/DEBUG bin list size
$(OBJDIR)/DEBUG:
@rm -rf $(OBJDIR)
@mkdir $(OBJDIR)
@> $(OBJDIR)/DEBUG
@echo "TARGET: DEBUG"
echo "CFLAGS += -DEBUG -Werror -W -Wimplicit-function-declaration" > $(OBJDIR)/CFLAGS
$(OBJDIR)/RELEASE:
@rm -rf $(OBJDIR)
@mkdir $(OBJDIR)
@> $(OBJDIR)/RELEASE
@echo "TARGET: RELEASE"
echo "" > $(OBJDIR)/CFLAGS
elf: $(ELF)
bin: $(BIN)
hex: $(HEX)
list: $(LIST)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
-include $(OBJDIR)/CFLAGS
endif
$(OBJDIR):
mkdir $(OBJDIR)
$(STARTUP): $(INC_DIR)/startup/vector.c
@echo " CC startup"
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
$(OBJDIR)/%.o: %.c
@echo " CC $<"
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
$(BIN): $(ELF)
@echo " OBJCOPY $(BIN)"
$(OBJCOPY) -Obinary $(ELF) $(BIN)
$(HEX): $(ELF)
@echo " OBJCOPY $(HEX)"
$(OBJCOPY) -Oihex $(ELF) $(HEX)
$(LIST): $(ELF)
@echo " OBJDUMP $(LIST)"
$(OBJDUMP) -S $(ELF) > $(LIST)
$(ELF): $(OBJDIR) $(OBJS)
@echo " LD $(ELF)"
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
size: $(ELF)
$(SIZE) $(ELF)
clean:
@echo " CLEAN"
@$(RM) $(HEX)
@$(RM) -rf $(OBJDIR) 2>/dev/null || true
flash: $(BIN)
@echo " FLASH $(BIN)"
$(STFLASH) --reset write $(BIN) 0x8000000
boot: $(BIN)
@echo " LOAD $(BIN) through bootloader"
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
dfuboot: $(BIN)
@echo " LOAD $(BIN) THROUGH DFU"
$(DFUUTIL) -a0 -D $(BIN) -s 0x08000000
.PHONY: clean flash boot

View File

@@ -0,0 +1,61 @@
Development board for TMC2130/DRV8825 stepper driver modules
============================================================
Stepper control over CAN bus, RS-485 and USB.
Pinout
======
PA0 - AIN0 (12V voltage control) AIN
PA1 - AIN1 (5V voltage control) AIN
PA3 - STEP timer
PA4 - DIR PP
PA5 - SCK - CFG1 - microstepping1 SPI/PP
PA6 - MISO - CFG0 - ~RST SPI/PP
PA7 - MOSI - CFG1 - microstepping0 SPI/PP
PA8 - Tx|Rx (RS485 direction) PP
PA9 - Tx (RS485) USART
PA10 - Rx (RS485) USART
PA11 - DM (USB) USB
PA12 - DP (USB) USB
PA13 - SWDIO (st-link) SWD
PA14 - SWCLK (st-link) SWD
PB0 - ESW0 PUin
PB1 - ESW1 (limit switches or other inputs) PUin
PB2 - ESW2 PUin
PB8 - CAN_Rx (CAN) CAN
PB9 - CAN_Tx (CAN) CAN
PB10 - ESW3 PUin
PB12 - brdaddr0 PUin
PB13 - brdaddr1 (bits of board address switch) PUin
PB14 - brdaddr2 PUin
PB15 - brdaddr3 PUin
PC13 - CFG6 - ~EN PP
PC14 - CFG3 - ~CS - microstepping2 PP
PC15 - ~SLEEP PP
PF0 - VIO_on (turn ON Vdd of driver 4988 or 2130) OD
PF1 - ~FAULT (~fault output of 8825) FLin
RS-485
======
The same protocol as USB, but 1st symbol should be BRDADDR
CAN
===
Data format: big-endian. For example 0x03 0x04 0x05 0x0a means 0x0304050a.
Messages with variable width.
IN messages have ID = 0x70 | (devNo<<1), devNo - number, selected by jumpers @ board.
OUT messages have ID=IN+1.
zeros byte of data is command. All other - data.
TODO
====
Add linecoding_handler to change RS-485 speed due to USB connection settings?

View File

@@ -0,0 +1,156 @@
/*
* This file is part of the TSYS_controller project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "adc.h"
/**
* @brief ADC_array - array for ADC channels with median filtering:
* 0..3 - external channels
* 4 - internal Tsens
* 5 - Vref
*/
#define TSENS_CHAN (NUMBER_OF_ADC_CHANNELS-2)
#define VREF_CHAN (NUMBER_OF_ADC_CHANNELS-1)
static uint16_t ADC_array[NUMBER_OF_ADC_CHANNELS*9];
/*
* ADC channels:
* IN0 - V12
* IN1 - V5
* IN16- temperature sensor
* IN17- vref
*/
void adc_setup(){
uint16_t ctr = 0; // 0xfff0 - more than 1.3ms
// Enable clocking
/* (1) Enable the peripheral clock of the ADC */
/* (2) Start HSI14 RC oscillator */
/* (3) Wait HSI14 is ready */
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* (1) */
RCC->CR2 |= RCC_CR2_HSI14ON; /* (2) */
while ((RCC->CR2 & RCC_CR2_HSI14RDY) == 0 && ++ctr < 0xfff0){}; /* (3) */
// calibration
/* (1) Ensure that ADEN = 0 */
/* (2) Clear ADEN */
/* (3) Launch the calibration by setting ADCAL */
/* (4) Wait until ADCAL=0 */
if ((ADC1->CR & ADC_CR_ADEN) != 0){ /* (1) */
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN); /* (2) */
}
ADC1->CR |= ADC_CR_ADCAL; /* (3) */
ctr = 0; // ADC calibration time is 5.9us
while ((ADC1->CR & ADC_CR_ADCAL) != 0 && ++ctr < 0xfff0){}; /* (4) */
// enable ADC
ctr = 0;
do{
ADC1->CR |= ADC_CR_ADEN;
}while ((ADC1->ISR & ADC_ISR_ADRDY) == 0 && ++ctr < 0xfff0);
// configure ADC
/* (1) Select HSI14 by writing 00 in CKMODE (reset value) */
/* (2) Select the continuous mode */
/* (3) Select CHSEL0,1 - ADC inputs, 16,17 - t. sensor and vref */
/* (4) Select a sampling mode of 111 i.e. 239.5 ADC clk to be greater than 17.1us */
/* (5) Wake-up the VREFINT and Temperature sensor (only for VBAT, Temp sensor and VRefInt) */
// ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */
ADC1->CFGR1 |= ADC_CFGR1_CONT; /* (2)*/
ADC1->CHSELR = ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17; /* (3)*/
ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* (4) */
ADC->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN; /* (5) */
// configure DMA for ADC
// DMA for AIN
/* (1) Enable the peripheral clock on DMA */
/* (2) Enable DMA transfer on ADC and circular mode */
/* (3) Configure the peripheral data register address */
/* (4) Configure the memory address */
/* (5) Configure the number of DMA tranfer to be performs on DMA channel 1 */
/* (6) Configure increment, size, interrupts and circular mode */
/* (7) Enable DMA Channel 1 */
RCC->AHBENR |= RCC_AHBENR_DMA1EN; /* (1) */
ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG; /* (2) */
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR)); /* (3) */
DMA1_Channel1->CMAR = (uint32_t)(ADC_array); /* (4) */
DMA1_Channel1->CNDTR = NUMBER_OF_ADC_CHANNELS * 9; /* (5) */
DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC; /* (6) */
DMA1_Channel1->CCR |= DMA_CCR_EN; /* (7) */
ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversions */
}
/**
* @brief getADCval - calculate median value for `nch` channel
* @param nch - number of channel
* @return
*/
uint16_t getADCval(int nch){
int i, addr = nch;
register uint16_t temp;
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
#define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; }
uint16_t p[9];
for(i = 0; i < 9; ++i, addr += NUMBER_OF_ADC_CHANNELS) // first we should prepare array for optmed
p[i] = ADC_array[addr];
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ;
PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ;
PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ;
PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ;
PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ;
PIX_SORT(p[4], p[2]) ;
return p[4];
#undef PIX_SORT
#undef PIX_SWAP
}
// return MCU temperature (degrees of celsius * 10)
int32_t getMCUtemp(){
int32_t ADval = getADCval(TSENS_CHAN);
int32_t temperature = (int32_t) *TEMP30_CAL_ADDR - ADval;
temperature *= (int32_t)(1100 - 300);
temperature /= (int32_t)(*TEMP30_CAL_ADDR - *TEMP110_CAL_ADDR);
temperature += 300;
return(temperature);
}
// return Vdd * 100 (V)
uint32_t getVdd(){
uint32_t vdd = ((uint32_t) *VREFINT_CAL_ADDR) * (uint32_t)330; // 3.3V
vdd /= getADCval(VREF_CHAN);
return vdd;
}
static inline uint32_t Ufromadu(uint8_t nch, uint32_t vdd){
uint32_t ADU = getADCval(nch);
ADU *= vdd;
ADU >>= 12; // /4096
return ADU;
}
/**
* @brief getUval - calculate U12/U5
* @return array with members:
* 0 - V12 * 100V (U12 = 12Vin/4.93)
* 1 - V5 * 100V (U5 = 5Vin /2)
*/
uint16_t *getUval(){
static uint16_t Uval[4];
uint32_t vdd = getVdd();
uint32_t val = Ufromadu(0, vdd) * 493;
Uval[0] = (uint16_t)(val / 100);
Uval[1] = (uint16_t)(Ufromadu(1, vdd) << 1);
return Uval;
}

View File

@@ -0,0 +1,31 @@
/*
* This file is part of the TSYS_controller project.
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ADC_H
#define ADC_H
#include "stm32f0.h"
#define NUMBER_OF_ADC_CHANNELS (4)
int32_t getMCUtemp();
uint32_t getVdd();
uint16_t getADCval(int nch);
void adc_setup();
uint16_t *getUval();
#endif // ADC_H

View File

@@ -0,0 +1,356 @@
/*
* geany_encoding=koi8-r
* can.c
*
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include "can.h"
#include "hardware.h"
#include "proto.h"
#include "usart.h"
#include <string.h> // memcpy
// circular buffer for received messages
static CAN_message messages[CAN_INMESSAGE_SIZE];
static uint8_t first_free_idx = 0; // index of first empty cell
static int8_t first_nonfree_idx = -1; // index of first data cell
static uint16_t oldspeed = 100; // speed of last init
static uint16_t CANID = 0xFFFF;
uint16_t masterID = 0;
static CAN_status can_status = CAN_STOP;
static void can_process_fifo(uint8_t fifo_num);
//static CAN_message loc_flood_msg;
//static CAN_message *flood_msg = NULL; // == loc_flood_msg - to flood
CAN_status CAN_get_status(){
CAN_status st = can_status;
// give overrun message only once
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY;
return st;
}
// push next message into buffer; return 1 if buffer overfull
static int CAN_messagebuf_push(CAN_message *msg){
//MSG("Try to push\n");
if(first_free_idx == first_nonfree_idx) return 1; // no free space
if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer
memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message));
// need to roll?
if(first_free_idx == CAN_INMESSAGE_SIZE) first_free_idx = 0;
return 0;
}
// pop message from buffer
CAN_message *CAN_messagebuf_pop(){
if(first_nonfree_idx < 0) return NULL;
CAN_message *msg = &messages[first_nonfree_idx++];
if(first_nonfree_idx == CAN_INMESSAGE_SIZE) first_nonfree_idx = 0;
if(first_nonfree_idx == first_free_idx){ // buffer is empty - refresh it
first_nonfree_idx = -1;
first_free_idx = 0;
}
return msg;
}
// get CAN address data from GPIO pins
void readCANID(){
uint8_t CAN_addr = refreshBRDaddr();
CANID = (CAN_ID_PREFIX & CAN_ID_MASK) | (CAN_addr << 1);
masterID = CANID + 1;
}
uint16_t getCANID(){
return CANID;
}
void CAN_reinit(uint16_t speed){
readCANID();
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
CAN_setup(speed);
}
/*
Can filtering: FSCx=0 (CAN->FS1R) -> 16-bit identifiers
MASK: FBMx=0 (CAN->FM1R), two filters (n in FR1 and n+1 in FR2)
ID: CAN->sFilterRegister[x].FRn[0..15]
MASK: CAN->sFilterRegister[x].FRn[16..31]
FR bits: STID[10:0] RTR IDE EXID[17:15]
LIST: FBMx=1, four filters (n&n+1 in FR1, n+2&n+3 in FR2)
IDn: CAN->sFilterRegister[x].FRn[0..15]
IDn+1: CAN->sFilterRegister[x].FRn[16..31]
*/
/*
Can timing: main freq - APB (PLL=48MHz)
segment = 1sync + TBS1 + TBS2, sample point is between TBS1 and TBS2,
so if TBS1=4 and TBS2=3, sum=8, bit sampling freq is 48/8 = 6MHz
-> to get 100kbps we need prescaler=60
250kbps - 24
500kbps - 12
1MBps - 6
*/
// speed - in kbps
void CAN_setup(uint16_t speed){
if(speed == 0) speed = oldspeed;
else if(speed < 50) speed = 50;
else if(speed > 3000) speed = 3000;
oldspeed = speed;
uint32_t tmout = 16000000;
if(CANID == 0xFFFF) readCANID();
// Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx
/* (1) Select AF mode (10) on PB8 and PB9 */
/* (2) AF4 for CAN signals */
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER8 | GPIO_MODER_MODER9))
| (GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF); /* (1) */
GPIOB->AFR[1] = (GPIOB->AFR[1] &~ (GPIO_AFRH_AFRH0 | GPIO_AFRH_AFRH1))\
| (4 << (0 * 4)) | (4 << (1 * 4)); /* (2) */
/* Enable the peripheral clock CAN */
RCC->APB1ENR |= RCC_APB1ENR_CANEN;
/* Configure CAN */
/* (1) Enter CAN init mode to write the configuration */
/* (2) Wait the init mode entering */
/* (3) Exit sleep mode */
/* (4) Normal mode, set timing to 100kb/s: TBS1 = 4, TBS2 = 3, prescaler = 60 */
/* (5) Leave init mode */
/* (6) Wait the init mode leaving */
/* (13) Set error interrupts enable */
CAN->MCR |= CAN_MCR_INRQ; /* (1) */
while((CAN->MSR & CAN_MSR_INAK)!=CAN_MSR_INAK) /* (2) */
{
if(--tmout == 0) break;
}
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */
CAN->BTR = 2 << 20 | 3 << 16 | (6000/speed - 1); /* (4) */
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
tmout = 16000000;
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) if(--tmout == 0) break; /* (6) */
// init filter: accept data only for this board
can_accept_one();
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1; /* (13) */
/* Configure IT */
/* (14) Set priority for CAN_IRQn */
/* (15) Enable CAN_IRQn */
NVIC_SetPriority(CEC_CAN_IRQn, 0); /* (14) */
NVIC_EnableIRQ(CEC_CAN_IRQn); /* (15) */
can_status = CAN_READY;
}
void can_proc(){
// check for messages in FIFO0 & FIFO1
if(CAN->RF0R & CAN_RF0R_FMP0){
can_process_fifo(0);
}
if(CAN->RF1R & CAN_RF1R_FMP1){
can_process_fifo(1);
}
IWDG->KR = IWDG_REFRESH;
if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS
SEND("\nToo much errors, restarting CAN!\n");
SEND("Receive error counter: ");
printu((CAN->ESR & CAN_ESR_REC)>>24);
SEND("\nTransmit error counter: ");
printu((CAN->ESR & CAN_ESR_TEC)>>16);
SEND("\nLast error code: ");
int lec = (CAN->ESR & CAN_ESR_LEC) >> 4;
const char *errmsg = "No";
switch(lec){
case 1: errmsg = "Stuff"; break;
case 2: errmsg = "Form"; break;
case 3: errmsg = "Ack"; break;
case 4: errmsg = "Bit recessive"; break;
case 5: errmsg = "Bit dominant"; break;
case 6: errmsg = "CRC"; break;
case 7: errmsg = "(set by software)"; break;
}
SEND(errmsg); SEND(" error\n");
if(CAN->ESR & CAN_ESR_BOFF) SEND("Bus off");
if(CAN->ESR & CAN_ESR_EPVF) SEND("Passive error limit");
if(CAN->ESR & CAN_ESR_EWGF) SEND("Error counter limit");
// request abort for all mailboxes
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
// reset CAN bus
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
CAN_setup(0);
}
/*
static uint32_t lastFloodTime = 0;
if(flood_msg && (Tms - lastFloodTime) > (FLOOD_PERIOD_MS-1)){ // flood every ~5ms
lastFloodTime = Tms;
can_send(flood_msg->data, flood_msg->length, flood_msg->ID);
}*/
}
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){
uint8_t mailbox = 0;
// check first free mailbox
if(CAN->TSR & (CAN_TSR_TME)){
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
}else{ // no free mailboxes
return CAN_BUSY;
}
CAN_TxMailBox_TypeDef *box = &CAN->sTxMailBox[mailbox];
uint32_t lb = 0, hb = 0;
switch(len){
case 8:
hb |= (uint32_t)msg[7] << 24;
__attribute__((fallthrough));
case 7:
hb |= (uint32_t)msg[6] << 16;
__attribute__((fallthrough));
case 6:
hb |= (uint32_t)msg[5] << 8;
__attribute__((fallthrough));
case 5:
hb |= (uint32_t)msg[4];
__attribute__((fallthrough));
case 4:
lb |= (uint32_t)msg[3] << 24;
__attribute__((fallthrough));
case 3:
lb |= (uint32_t)msg[2] << 16;
__attribute__((fallthrough));
case 2:
lb |= (uint32_t)msg[1] << 8;
__attribute__((fallthrough));
default:
lb |= (uint32_t)msg[0];
}
box->TDLR = lb;
box->TDHR = hb;
box->TDTR = len;
box->TIR = (target_id & 0x7FF) << 21 | CAN_TI0R_TXRQ;
return CAN_OK;
}
/*
void can_send_dummy(){
uint8_t msg = CMD_TOGGLE;
if(CAN_OK != can_send(&msg, 1, TARG_ID)) SEND("Bus busy!\n");
}
void can_send_broadcast(){
uint8_t msg = CMD_BCAST;
if(CAN_OK != can_send(&msg, 1, BCAST_ID)) SEND("Bus busy!\n");
MSG("Broadcast message sent\n");
}
void set_flood(CAN_message *msg){
if(!msg) flood_msg = NULL;
else{
memcpy(&loc_flood_msg, msg, sizeof(CAN_message));
flood_msg = &loc_flood_msg;
}
}*/
static void can_process_fifo(uint8_t fifo_num){
if(fifo_num > 1) return;
CAN_FIFOMailBox_TypeDef *box = &CAN->sFIFOMailBox[fifo_num];
volatile uint32_t *RFxR = (fifo_num) ? &CAN->RF1R : &CAN->RF0R;
// read all
while(*RFxR & CAN_RF0R_FMP0){ // amount of messages pending
// CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length
CAN_message msg;
uint8_t *dat = msg.data;
uint8_t len = box->RDTR & 0x0f;
msg.length = len;
msg.ID = box->RIR >> 21;
msg.fifoNum = fifo_num; // @parsing only data from FIFO0 will be accepted, FIFO1 is for monitoring
if(len){ // message can be without data
uint32_t hb = box->RDHR, lb = box->RDLR;
switch(len){
case 8:
dat[7] = hb>>24;
__attribute__((fallthrough));
case 7:
dat[6] = (hb>>16) & 0xff;
__attribute__((fallthrough));
case 6:
dat[5] = (hb>>8) & 0xff;
__attribute__((fallthrough));
case 5:
dat[4] = hb & 0xff;
__attribute__((fallthrough));
case 4:
dat[3] = lb>>24;
__attribute__((fallthrough));
case 3:
dat[2] = (lb>>16) & 0xff;
__attribute__((fallthrough));
case 2:
dat[1] = (lb>>8) & 0xff;
__attribute__((fallthrough));
case 1:
dat[0] = lb & 0xff;
}
}
if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
}
*RFxR = 0; // clear FOVR & FULL
}
void cec_can_isr(){
if(CAN->RF0R & CAN_RF0R_FOVR0){ // FIFO overrun
CAN->RF0R &= ~CAN_RF0R_FOVR0;
can_status = CAN_FIFO_OVERRUN;
}
if(CAN->RF1R & CAN_RF1R_FOVR1){
CAN->RF1R &= ~CAN_RF1R_FOVR1;
can_status = CAN_FIFO_OVERRUN;
}
if(CAN->MSR & CAN_MSR_ERRI){ // Error
CAN->MSR &= ~CAN_MSR_ERRI;
// request abort for problem mailbox
if(CAN->TSR & CAN_TSR_TERR0) CAN->TSR |= CAN_TSR_ABRQ0;
if(CAN->TSR & CAN_TSR_TERR1) CAN->TSR |= CAN_TSR_ABRQ1;
if(CAN->TSR & CAN_TSR_TERR2) CAN->TSR |= CAN_TSR_ABRQ2;
}
}
// accept only data for given device @ FIFO0, filter 0
void can_accept_one(){
CAN->FMR = CAN_FMR_FINIT; // Enter filter init mode, (16-bit + mask, bank 0 for FIFO 0)
CAN->FA1R = CAN_FA1R_FACT0; // Acivate filter 0 for ID
// main data - FIFO0, filter0
CAN->FM1R = CAN_FM1R_FBM0; // Identifier list mode
CAN->sFilterRegister[0].FR1 = (CANID << 5) | (0x8f<<16); // Set the Id list
//CAN->sFilterRegister[0].FR2 = (0x8f<<16) | 0x8f;
CAN->FMR &= ~CAN_FMR_FINIT; // Leave filter init
}
// accept everything @ FIFO1, filter 4
void can_accept_any(){
CAN->FMR = CAN_FMR_FINIT;
CAN->FA1R |= CAN_FA1R_FACT1; // Acivate bank 1
CAN->FFA1R = CAN_FFA1R_FFA1; // bank 1 for FIFO1
CAN->FM1R &= ~CAN_FM1R_FBM1; // MASK
CAN->sFilterRegister[1].FR1 = 0; // all IDs
CAN->sFilterRegister[1].FR2 = (0x8f<<16) | 0x8f;
CAN->FMR &= ~CAN_FMR_FINIT;
}

View File

@@ -0,0 +1,89 @@
/*
* geany_encoding=koi8-r
* can.h
*
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#pragma once
#ifndef __CAN_H__
#define __CAN_H__
#include "hardware.h"
// default CAN speed - 100kbps
#define CAN_SPEED_DEFAULT 100
// amount of filter banks in STM32F0
#define STM32F0FBANKNO 28
// flood period in milliseconds
#define FLOOD_PERIOD_MS 5
// simple 1-byte commands
//#define CMD_TOGGLE (0xDA)
//#define CMD_BCAST (0xAD)
// mask clearing bits of board address
#define CAN_ID_MASK (0x7E0)
// prefix to make ID from any number
#define CAN_ID_PREFIX (0x70)
// "target" ID: num=0
//#define TARG_ID (CAN_ID_PREFIX & CAN_ID_MASK)
// "broadcast" ID: all ones
//#define BCAST_ID (0x7FF)
// incoming message buffer size
#define CAN_INMESSAGE_SIZE (8)
// CAN message
typedef struct{
uint8_t data[8]; // up to 8 bytes of data
uint8_t length; // data length
//uint8_t filterNo; // filter number
uint8_t fifoNum; // message FIFO number
uint16_t ID; // ID of receiver
} CAN_message;
typedef enum{
CAN_STOP,
CAN_READY,
CAN_BUSY,
CAN_OK,
CAN_FIFO_OVERRUN
} CAN_status;
extern uint16_t masterID; // ID to send answers by CAN
CAN_status CAN_get_status();
void readCANID();
uint16_t getCANID();
void CAN_reinit(uint16_t speed);
void CAN_setup(uint16_t speed);
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id);
//void can_send_dummy();
//void can_send_broadcast();
void can_proc();
CAN_message *CAN_messagebuf_pop();
void can_accept_any();
void can_accept_one();
//void set_flood(CAN_message *msg);
#endif // __CAN_H__

View File

@@ -0,0 +1,101 @@
/*
* geany_encoding=koi8-r
* can_process.c
*
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include "adc.h"
#include "can.h"
#include "can_process.h"
#include "proto.h"
extern volatile uint32_t Tms; // timestamp data
// v==0 - send V12 & V5
static void senduival(){
uint8_t buf[5];
uint16_t *vals = getUval();
buf[0] = CMD_GETUVAL; // V12 and V5
buf[1] = vals[0] >> 8; // H
buf[2] = vals[0] & 0xff;// L
buf[3] = vals[1] >> 8; // -//-
buf[4] = vals[1] & 0xff;
SEND_CAN(buf, 5);
}
static void sendu16(uint8_t cmd, uint16_t data){
uint8_t buf[3];
buf[0] = cmd;
buf[1] = data >> 8;
buf[2] = data & 0xff;
SEND_CAN(buf, 3);
}
void can_messages_proc(){
CAN_message *can_mesg = CAN_messagebuf_pop();
if(!can_mesg) return; // no data in buffer
uint8_t len = can_mesg->length;
#ifndef EBUG
if(can_mesg->fifoNum == 1){ // not my data - just show it
#endif
if(monitCAN){
printu(Tms);
SEND(" #");
printuhex(can_mesg->ID);
SEND(" (F#"); printu(can_mesg->fifoNum); SEND(")");
for(uint8_t ctr = 0; ctr < len; ++ctr){
SEND(" ");
printuhex(can_mesg->data[ctr]);
}
IWDG->KR = IWDG_REFRESH;
newline(); sendbuf();
}
#ifndef EBUG
return;
}
#endif
IWDG->KR = IWDG_REFRESH;
if(!len) return; // no data in message
uint8_t *data = can_mesg->data;
switch(data[0]){
case CMD_PING: // pong
SEND_CAN(data, 1);
break;
case CMD_GETMCUTEMP:
sendu16(CMD_GETMCUTEMP, (int16_t)getMCUtemp());
break;
case CMD_GETUVAL:
senduival();
break;
case CMD_GETU3V3:
sendu16(CMD_GETU3V3, (uint16_t)getVdd());
break;
}
}
// try to send messages, wait no more than 100ms
CAN_status try2send(uint8_t *buf, uint8_t len, uint16_t id){
uint32_t Tstart = Tms;
while(Tms - Tstart < SEND_TIMEOUT_MS){
if(CAN_OK == can_send(buf, len, id)) return CAN_OK;
IWDG->KR = IWDG_REFRESH;
}
SEND("CAN_BUSY\n");
return CAN_BUSY;
}

View File

@@ -0,0 +1,38 @@
/*
* geany_encoding=koi8-r
* can_process.h
*
* Copyright 2018 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include "can.h"
// timeout for trying to send data
#define SEND_TIMEOUT_MS (10)
// 8-bit commands sent by master
typedef enum{
CMD_PING, // just echo it back
CMD_GETMCUTEMP, // MCU temperature value
CMD_GETUVAL, // answer with values of V12 and V5
CMD_GETU3V3, // answer with values of V3.3
} CAN_commands;
void can_messages_proc();
#define SEND_CAN(a,b) try2send(a, b, masterID)
CAN_status try2send(uint8_t *buf, uint8_t len, uint16_t id);

Binary file not shown.

View File

@@ -0,0 +1,244 @@
/*
* geany_encoding=koi8-r
* flash.c
*
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
/**
ATTENTION!!
This things works only if you will add next section:
.myvars :
{
. = ALIGN(1024);
__varsstart = ABSOLUTE(.);
KEEP(*(.myvars));
} > rom
after section .data
*/
#include <stm32f0.h>
#include "adc.h"
#include "flash.h"
#include "proto.h" // printout
#include "steppers.h"
#include <string.h> // memcpy
// max amount of Config records stored (will be recalculate in flashstorage_init()
static uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
#define USERCONF_INITIALIZER { \
.userconf_sz = sizeof(user_conf) \
,.defflags.reverse = 0 \
,.CANspeed = 100 \
,.driver_type = DRV_8825 \
,.microsteps = 16 \
,.accdecsteps = 25 \
,.motspd = 1000 \
,.maxsteps = 50000 \
}
static int erase_flash(const void*, const void*);
static int write2flash(const void*, const void*, uint32_t);
// don't write `static` here, or get error:
// 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t'
const user_conf *Flash_Data = (const user_conf *)(&__varsstart);
user_conf the_conf = USERCONF_INITIALIZER;
static int currentconfidx = -1; // index of current configuration
/**
* @brief binarySearch - binary search in flash for last non-empty cell
* any struct searched should have its sizeof() @ the first field!!!
* @param l - left index
* @param r - right index (should be @1 less than last index!)
* @param start - starting address
* @param stor_size - size of structure to search
* @return index of non-empty cell or -1
*/
static int binarySearch(int r, const uint8_t *start, int stor_size){
int l = 0;
while(r >= l){
int mid = l + (r - l) / 2;
const uint8_t *s = start + mid * stor_size;
if(*((const uint16_t*)s) == stor_size){
if(*((const uint16_t*)(s + stor_size)) == 0xffff){ // next is free
return mid;
}else{ // element is to the right
l = mid + 1;
}
}else{ // element is to the left
r = mid - 1;
}
}
return -1; // not found
}
/**
* @brief flashstorage_init - initialization of user conf storage
* run in once @ start
*/
void flashstorage_init(){
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
flsz -= (uint32_t)(&__varsstart) - FLASH_BASE;
maxCnum = flsz / sizeof(user_conf);
//SEND("flsz="); printu(flsz);
//SEND("\nmaxCnum="); printu(maxCnum); newline(); sendbuf();
}
// -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
currentconfidx = binarySearch((int)maxCnum-2, (const uint8_t*)Flash_Data, sizeof(user_conf));
if(currentconfidx > -1){
memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf));
}
}
// store new configuration
// @return 0 if all OK
int store_userconf(){
// maxnum - 3 means that there always should be at least one empty record after last data
// for binarySearch() checking that there's nothing more after it!
if(currentconfidx > (int)maxCnum - 3){ // there's no more place
currentconfidx = 0;
if(erase_flash(Flash_Data, (&__varsstart))) return 1;
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
}
static int write2flash(const void *start, const void *wrdata, uint32_t stor_size){
int ret = 0;
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
while (FLASH->SR & FLASH_SR_BSY);
if(FLASH->SR & FLASH_SR_WRPRTERR){
MSG("Can't remove write protection\n");
return 1; // write protection
}
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
FLASH->CR |= FLASH_CR_PG;
const uint16_t *data = (const uint16_t*) wrdata;
volatile uint16_t *address = (volatile uint16_t*) start;
uint32_t i, count = (stor_size + 1) / 2;
for (i = 0; i < count; ++i){
IWDG->KR = IWDG_REFRESH;
*(volatile uint16_t*)(address + i) = data[i];
while (FLASH->SR & FLASH_SR_BSY);
if(FLASH->SR & FLASH_SR_PGERR){
ret = 1; // program error - meet not 0xffff
MSG("FLASH_SR_PGERR\n");
break;
}else while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
}
FLASH->CR |= FLASH_CR_LOCK; // lock it back
FLASH->CR &= ~(FLASH_CR_PG);
MSG("Flash stored\n");
return ret;
}
/**
* @brief erase_flash - erase N pages of flash memory
* @param start - first address
* @param end - last address (or NULL if need to erase all flash remaining)
* @return 0 if succeed
*/
static int erase_flash(const void *start, const void *end){
int ret = 0;
uint32_t nblocks = 1, flsz = 0;
if(!end){ // erase all remaining
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
flsz = FLASH_SIZE * 1024; // size in bytes
flsz -= (uint32_t)start - FLASH_BASE;
}
}else{ // erase a part
flsz = (uint32_t)end - (uint32_t)start;
}
nblocks = flsz / FLASH_BLOCK_SIZE;
if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1;
for(uint32_t i = 0; i < nblocks; ++i){
#ifdef EBUG
SEND("Try to erase page #"); printu(i); newline(); sendbuf();
#endif
IWDG->KR = IWDG_REFRESH;
/* (1) Wait till no operation is on going */
/* (2) Clear error & EOP bits */
/* (3) Check that the Flash is unlocked */
/* (4) Perform unlock sequence */
while ((FLASH->SR & FLASH_SR_BSY) != 0){} /* (1) */
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; /* (2) */
/* if (FLASH->SR & FLASH_SR_EOP){
FLASH->SR |= FLASH_SR_EOP;
}*/
if ((FLASH->CR & FLASH_CR_LOCK) != 0){ /* (3) */
FLASH->KEYR = FLASH_KEY1; /* (4) */
FLASH->KEYR = FLASH_KEY2;
}
/* (1) Set the PER bit in the FLASH_CR register to enable page erasing */
/* (2) Program the FLASH_AR register to select a page to erase */
/* (3) Set the STRT bit in the FLASH_CR register to start the erasing */
/* (4) Wait until the EOP flag in the FLASH_SR register set */
/* (5) Clear EOP flag by software by writing EOP at 1 */
/* (6) Reset the PER Bit to disable the page erase */
FLASH->CR |= FLASH_CR_PER; /* (1) */
FLASH->AR = (uint32_t)Flash_Data + i*FLASH_BLOCK_SIZE; /* (2) */
FLASH->CR |= FLASH_CR_STRT; /* (3) */
while(!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR |= FLASH_SR_EOP; /* (5)*/
if(FLASH->SR & FLASH_SR_WRPRTERR){ /* Check Write protection error */
ret = 1;
MSG("Write protection error!\n");
FLASH->SR |= FLASH_SR_WRPRTERR; /* Clear the flag by software by writing it at 1*/
break;
}
FLASH->CR &= ~FLASH_CR_PER; /* (6) */
}
return ret;
}
void dump_userconf(){
SEND("userconf_addr="); printuhex((uint32_t)Flash_Data);
SEND("\nuserconf_sz="); printu(the_conf.userconf_sz);
SEND("\nCANspeed="); printu(the_conf.CANspeed);
SEND("\ndriver_type=");
const char *p = "NONE";
switch(the_conf.driver_type){
case DRV_2130:
p = "TMC2130";
break;
case DRV_4988:
p = "A4988";
break;
case DRV_8825:
p = "DRV8825";
break;
}
SEND(p);
SEND("\nmicrosteps="); printu(the_conf.microsteps);
SEND("\naccdecsteps="); printu(the_conf.accdecsteps);
SEND("\nmotspd="); printu(the_conf.motspd);
SEND("\nmaxsteps="); printu(the_conf.maxsteps);
//flags
SEND("\nreverse="); bufputchar('0' + the_conf.defflags.reverse);
newline();
sendbuf();
}

View File

@@ -0,0 +1,59 @@
/*
* flash.h
*
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#pragma once
#ifndef __FLASH_H__
#define __FLASH_H__
#include "hardware.h"
#define FLASH_BLOCK_SIZE (1024)
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC)
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
typedef struct{
uint8_t reverse : 1;
} defflags_t;
/*
* struct to save user configurations
*/
typedef struct __attribute__((packed, aligned(4))){
uint32_t maxsteps; // maximal amount of steps from ESW0 to EWS3
uint16_t userconf_sz; // "magick number"
uint16_t CANspeed; // default CAN speed
uint16_t microsteps; // microsteps amount per step
uint16_t accdecsteps; // amount of steps need for full acceleration/deceleration cycle
uint16_t motspd; // max motor speed (steps per second)
defflags_t defflags; // default flags
uint8_t driver_type; // user's settings: type of stepper's driver
} user_conf;
extern user_conf the_conf; // global user config (read from FLASH to RAM)
// data from ld-file: start address of storage
extern const uint32_t __varsstart;
void flashstorage_init();
int store_userconf();
void dump_userconf();
#endif // __FLASH_H__

Some files were not shown because too many files have changed in this diff Show More