changed processor

This commit is contained in:
2021-04-29 08:31:28 +02:00
parent 28790bb2f4
commit 2f7f724046
53 changed files with 12162 additions and 6131 deletions

6
clockclock/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.DS_Store

7
clockclock/.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

View File

@@ -0,0 +1,45 @@
{
"build": {
"cpu": "cortex-m0plus",
"extra_flags": "-DSTM32L031xx",
"f_cpu": "32000000L",
"mcu": "stm32l031k6t6",
"product_line": "STM32L031xx",
"variant": "STM32L031K6",
"variants_dir": "variants"
},
"debug": {
"default_tools": [
"stlink"
],
"jlink_device": "STM32L031K6",
"onboard_tools": [
"stlink"
],
"openocd_target": "stm32l0",
"svd_path": "STM32L0x1.svd"
},
"frameworks": [
"arduino",
"cmsis",
"mbed",
"stm32cube",
"libopencm3"
],
"name": "STM32L031K6",
"upload": {
"maximum_ram_size": 8192,
"maximum_size": 32768,
"protocol": "stlink",
"protocols": [
"jlink",
"cmsis-dap",
"stlink",
"blackmagic",
"mbed"
]
},
"url": "https://developer.mbed.org/platforms/ST-Nucleo-L031K6/",
"vendor": "ST"
}

View File

@@ -0,0 +1,45 @@
{
"build": {
"cpu": "cortex-m0plus",
"extra_flags": "-DSTM32L422xx",
"f_cpu": "80000000L",
"mcu": "stm32l422KB",
"product_line": "STM32L422xx",
"variant": "STM32L422KB",
"variants_dir": "variants"
},
"debug": {
"default_tools": [
"stlink"
],
"jlink_device": "STM32L422KB",
"onboard_tools": [
"stlink"
],
"openocd_target": "stm32l4x",
"svd_path": "STM32L4x2.svd"
},
"frameworks": [
"arduino",
"cmsis",
"mbed",
"stm32cube",
"libopencm3"
],
"name": "STM32L422KB",
"upload": {
"maximum_ram_size": 8192,
"maximum_size": 131072,
"protocol": "stlink",
"protocols": [
"jlink",
"cmsis-dap",
"stlink",
"blackmagic",
"mbed"
]
},
"url": "https://developer.mbed.org/platforms/ST-Nucleo-L031K6/",
"vendor": "ST"
}

View File

@@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}

39
clockclock/include/README Normal file
View File

@@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View File

@@ -0,0 +1,11 @@
#pragma once
#ifndef HARDWAREVERSION
#define HARDWAREVERSION 10
#endif
#if HARDWAREVERSION == 10
#include "board_v10.h"
#endif

View File

@@ -0,0 +1,24 @@
#pragma once
//hardware version v1.0
#define MOT_STCK0 PA1
#define MOT_DIR0 PA2
#define MOT_RST0 PA3
#define MOT_EN0 PA4
#define MOT_VREF1 PA5
#define MOT_STCK1 PA6
#define MOT_DIR1 PA7
#define MOT_RST1 PB0
#define MOT_EN1 PB1
#define ADDR0 PA12
#define ADDR1 PA11
#define ADDR2 PA8
#define ADDR3 PB7
#define I2C_CLK PA9
#define I2C_SDA PA10
#define MCU_BUT_MIN PB4
#define MCU_BUT_PLUS PB5

View File

@@ -0,0 +1,100 @@
// Arduino Button Library
// https://github.com/JChristensen/JC_Button
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
#include "JC_Button.h"
/*----------------------------------------------------------------------*
/ initialize a Button object and the pin it's connected to. *
/-----------------------------------------------------------------------*/
void Button::begin()
{
pinMode(m_pin, m_puEnable ? INPUT_PULLUP : INPUT);
m_state = digitalRead(m_pin);
if (m_invert) m_state = !m_state;
m_time = millis();
m_lastState = m_state;
m_changed = false;
m_lastChange = m_time;
}
/*----------------------------------------------------------------------*
/ returns the state of the button, true if pressed, false if released. *
/ does debouncing, captures and maintains times, previous state, etc. *
/-----------------------------------------------------------------------*/
bool Button::read()
{
uint32_t ms = millis();
bool pinVal = digitalRead(m_pin);
if (m_invert) pinVal = !pinVal;
if (ms - m_lastChange < m_dbTime)
{
m_changed = false;
}
else
{
m_lastState = m_state;
m_state = pinVal;
m_changed = (m_state != m_lastState);
if (m_changed) m_lastChange = ms;
}
m_time = ms;
return m_state;
}
/*----------------------------------------------------------------------*
* isPressed() and isReleased() check the button state when it was last *
* read, and return false (0) or true (!=0) accordingly. *
* These functions do not cause the button to be read. *
*----------------------------------------------------------------------*/
bool Button::isPressed()
{
return m_state;
}
bool Button::isReleased()
{
return !m_state;
}
/*----------------------------------------------------------------------*
* wasPressed() and wasReleased() check the button state to see if it *
* changed between the last two reads and return false (0) or *
* true (!=0) accordingly. *
* These functions do not cause the button to be read. *
*----------------------------------------------------------------------*/
bool Button::wasPressed()
{
return m_state && m_changed;
}
bool Button::wasReleased()
{
return !m_state && m_changed;
}
/*----------------------------------------------------------------------*
* pressedFor(ms) and releasedFor(ms) check to see if the button is *
* pressed (or released), and has been in that state for the specified *
* time in milliseconds. Returns false (0) or true (!=0) accordingly. *
* These functions do not cause the button to be read. *
*----------------------------------------------------------------------*/
bool Button::pressedFor(uint32_t ms)
{
return m_state && m_time - m_lastChange >= ms;
}
bool Button::releasedFor(uint32_t ms)
{
return !m_state && m_time - m_lastChange >= ms;
}
/*----------------------------------------------------------------------*
* lastChange() returns the time the button last changed state, *
* in milliseconds. *
*----------------------------------------------------------------------*/
uint32_t Button::lastChange()
{
return m_lastChange;
}

View File

@@ -0,0 +1,111 @@
// Arduino Button Library
// https://github.com/JChristensen/JC_Button
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
#ifndef JC_BUTTON_H_INCLUDED
#define JC_BUTTON_H_INCLUDED
#include <Arduino.h>
class Button
{
public:
// Button(pin, dbTime, puEnable, invert) instantiates a button object.
//
// Required parameter:
// pin The Arduino pin the button is connected to
//
// Optional parameters:
// dbTime Debounce time in milliseconds (default 25ms)
// puEnable true to enable the AVR internal pullup resistor (default true)
// invert true to interpret a low logic level as pressed (default true)
Button(uint8_t pin, uint32_t dbTime=25, uint8_t puEnable=true, uint8_t invert=true)
: m_pin(pin), m_dbTime(dbTime), m_puEnable(puEnable), m_invert(invert) {}
// Initialize a Button object and the pin it's connected to
void begin();
// Returns the current debounced button state, true for pressed,
// false for released. Call this function frequently to ensure
// the sketch is responsive to user input.
bool read();
// Returns true if the button state was pressed at the last call to read().
// Does not cause the button to be read.
bool isPressed();
// Returns true if the button state was released at the last call to read().
// Does not cause the button to be read.
bool isReleased();
// Returns true if the button state at the last call to read() was pressed,
// and this was a change since the previous read.
bool wasPressed();
// Returns true if the button state at the last call to read() was released,
// and this was a change since the previous read.
bool wasReleased();
// Returns true if the button state at the last call to read() was pressed,
// and has been in that state for at least the given number of milliseconds.
bool pressedFor(uint32_t ms);
// Returns true if the button state at the last call to read() was released,
// and has been in that state for at least the given number of milliseconds.
bool releasedFor(uint32_t ms);
// Returns the time in milliseconds (from millis) that the button last
// changed state.
uint32_t lastChange();
private:
uint8_t m_pin; // arduino pin number connected to button
uint32_t m_dbTime; // debounce time (ms)
bool m_puEnable; // internal pullup resistor enabled
bool m_invert; // if true, interpret logic low as pressed, else interpret logic high as pressed
bool m_state; // current button state, true=pressed
bool m_lastState; // previous button state
bool m_changed; // state changed since last read
uint32_t m_time; // time of current state (ms from millis)
uint32_t m_lastChange; // time of last state change (ms)
};
// a derived class for a "push-on, push-off" (toggle) type button.
// initial state can be given, default is off (false).
class ToggleButton : public Button
{
public:
// constructor is similar to Button, but includes the initial state for the toggle.
ToggleButton(uint8_t pin, bool initialState=false, uint32_t dbTime=25, uint8_t puEnable=true, uint8_t invert=true)
: Button(pin, dbTime, puEnable, invert), m_toggleState(initialState) {}
// read the button and return its state.
// should be called frequently.
bool read()
{
Button::read();
if (wasPressed())
{
m_toggleState = !m_toggleState;
m_changed = true;
}
else
{
m_changed = false;
}
return m_toggleState;
}
// has the state changed?
bool changed() {return m_changed;}
// return the current state
bool toggleState() {return m_toggleState;}
private:
bool m_toggleState;
bool m_changed;
};
#endif

46
clockclock/lib/README Normal file
View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -0,0 +1,95 @@
/*
* A4988 - Stepper Motor Driver Driver
* Indexer mode only.
* Copyright (C)2015 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include "A4988.h"
/*
* Microstepping resolution truth table (Page 6 of A4988 pdf)
* 0bMS3,MS2,MS1 for 1,2,4,8,16 microsteps
*/
const uint8_t A4988::MS_TABLE[] = {0b000, 0b001, 0b010, 0b011, 0b111};
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
A4988::A4988(short steps, short dir_pin, short step_pin)
:BasicStepperDriver(steps, dir_pin, step_pin)
{}
A4988::A4988(short steps, short dir_pin, short step_pin, short enable_pin)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin)
{}
/*
* Fully wired.
* All the necessary control pins for A4988 are connected.
*/
A4988::A4988(short steps, short dir_pin, short step_pin, short ms1_pin, short ms2_pin, short ms3_pin)
:BasicStepperDriver(steps, dir_pin, step_pin),
ms1_pin(ms1_pin), ms2_pin(ms2_pin), ms3_pin(ms3_pin)
{}
A4988::A4988(short steps, short dir_pin, short step_pin, short enable_pin, short ms1_pin, short ms2_pin, short ms3_pin)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin),
ms1_pin(ms1_pin), ms2_pin(ms2_pin), ms3_pin(ms3_pin)
{}
void A4988::begin(float rpm, short microsteps){
BasicStepperDriver::begin(rpm, microsteps);
if (!IS_CONNECTED(ms1_pin) || !IS_CONNECTED(ms2_pin) || !IS_CONNECTED(ms3_pin)){
return;
}
pinMode(ms1_pin, OUTPUT);
pinMode(ms2_pin, OUTPUT);
pinMode(ms3_pin, OUTPUT);
}
/*
* Set microstepping mode (1:divisor)
* Allowed ranges for A4988 are 1:1 to 1:16
* If the control pins are not connected, we recalculate the timing only
*/
short A4988::setMicrostep(short microsteps){
BasicStepperDriver::setMicrostep(microsteps);
if (!IS_CONNECTED(ms1_pin) || !IS_CONNECTED(ms2_pin) || !IS_CONNECTED(ms3_pin)){
return this->microsteps;
}
const uint8_t* ms_table = getMicrostepTable();
size_t ms_table_size = getMicrostepTableSize();
unsigned short i = 0;
while (i < ms_table_size){
if (this->microsteps & (1<<i)){
uint8_t mask = ms_table[i];
digitalWrite(ms3_pin, mask & 4);
digitalWrite(ms2_pin, mask & 2);
digitalWrite(ms1_pin, mask & 1);
break;
}
i++;
}
return this->microsteps;
}
const uint8_t* A4988::getMicrostepTable(){
return A4988::MS_TABLE;
}
size_t A4988::getMicrostepTableSize(){
return sizeof(A4988::MS_TABLE);
}
short A4988::getMaxMicrostep(){
return A4988::MAX_MICROSTEP;
}

View File

@@ -0,0 +1,56 @@
/*
* A4988 - Stepper Motor Driver Driver
* Indexer mode only.
*
* Copyright (C)2015 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef A4988_H
#define A4988_H
#include <Arduino.h>
#include "BasicStepperDriver.h"
class A4988 : public BasicStepperDriver {
protected:
static const uint8_t MS_TABLE[];
short ms1_pin = PIN_UNCONNECTED;
short ms2_pin = PIN_UNCONNECTED;
short ms3_pin = PIN_UNCONNECTED;
// tA STEP minimum, HIGH pulse width (1us)
static const int step_high_min = 1;
// tB STEP minimum, LOW pulse width (1us)
static const int step_low_min = 1;
// wakeup time, nSLEEP inactive to STEP (1000us)
static const int wakeup_time = 1000;
// also 200ns between ENBL/DIR/MSx changes and STEP HIGH
// Get the microstep table
virtual const uint8_t* getMicrostepTable();
virtual size_t getMicrostepTableSize();
// Get max microsteps supported by the device
short getMaxMicrostep() override;
private:
// microstep range (1, 16, 32 etc)
static const short MAX_MICROSTEP = 16;
public:
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
A4988(short steps, short dir_pin, short step_pin);
A4988(short steps, short dir_pin, short step_pin, short enable_pin);
void begin(float rpm=60, short microsteps=1);
/*
* Fully wired. All the necessary control pins for A4988 are connected.
*/
A4988(short steps, short dir_pin, short step_pin, short ms1_pin, short ms2_pin, short ms3_pin);
A4988(short steps, short dir_pin, short step_pin, short enable_pin, short ms1_pin, short ms2_pin, short ms3_pin);
short setMicrostep(short microsteps) override;
};
#endif // A4988_H

View File

@@ -0,0 +1,360 @@
/*
* Generic Stepper Motor Driver Driver
* Indexer mode only.
* Copyright (C)2015-2019 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*
* Linear speed profile calculations based on
* - Generating stepper-motor speed profiles in real time - David Austin, 2004
* - Atmel AVR446: Linear speed control of stepper motor, 2006
*/
#include "BasicStepperDriver.h"
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
BasicStepperDriver::BasicStepperDriver(short steps, short dir_pin, short step_pin)
:BasicStepperDriver(steps, dir_pin, step_pin, PIN_UNCONNECTED)
{
}
BasicStepperDriver::BasicStepperDriver(short steps, short dir_pin, short step_pin, short enable_pin)
:motor_steps(steps), dir_pin(dir_pin), step_pin(step_pin), enable_pin(enable_pin)
{
steps_to_cruise = 0;
steps_remaining = 0;
dir_state = 0;
steps_to_brake = 0;
step_pulse = 0;
cruise_step_pulse = 0;
rest = 0;
step_count = 0;
}
/*
* Initialize pins, calculate timings etc
*/
void BasicStepperDriver::begin(float rpm, short microsteps){
pinMode(dir_pin, OUTPUT);
digitalWrite(dir_pin, HIGH);
pinMode(step_pin, OUTPUT);
digitalWrite(step_pin, LOW);
if IS_CONNECTED(enable_pin){
pinMode(enable_pin, OUTPUT);
disable();
}
this->rpm = rpm;
setMicrostep(microsteps);
enable();
}
/*
* Set target motor RPM (1-200 is a reasonable range)
*/
void BasicStepperDriver::setRPM(float rpm){
if (this->rpm == 0){ // begin() has not been called (old 1.0 code)
begin(rpm, microsteps);
}
this->rpm = rpm;
}
/*
* Set stepping mode (1:microsteps)
* Allowed ranges for BasicStepperDriver are 1:1 to 1:128
*/
short BasicStepperDriver::setMicrostep(short microsteps){
for (short ms=1; ms <= getMaxMicrostep(); ms<<=1){
if (microsteps == ms){
this->microsteps = microsteps;
break;
}
}
return this->microsteps;
}
/*
* Set speed profile - CONSTANT_SPEED, LINEAR_SPEED (accelerated)
* accel and decel are given in [full steps/s^2]
*/
void BasicStepperDriver::setSpeedProfile(Mode mode, short accel, short decel){
profile.mode = mode;
profile.accel = accel;
profile.decel = decel;
}
void BasicStepperDriver::setSpeedProfile(struct Profile profile){
this->profile = profile;
}
/*
* Move the motor a given number of steps.
* positive to move forward, negative to reverse
*/
void BasicStepperDriver::move(long steps){
startMove(steps);
while (nextAction());
}
/*
* Move the motor a given number of degrees (1-360)
*/
void BasicStepperDriver::rotate(long deg){
move(calcStepsForRotation(deg));
}
/*
* Move the motor with sub-degree precision.
* Note that using this function even once will add 1K to your program size
* due to inclusion of float support.
*/
void BasicStepperDriver::rotate(double deg){
move(calcStepsForRotation(deg));
}
/*
* Set up a new move (calculate and save the parameters)
*/
void BasicStepperDriver::startMove(long steps, long time){
float speed;
// set up new move
dir_state = (steps >= 0) ? HIGH : LOW;
last_action_end = 0;
steps_remaining = labs(steps);
step_count = 0;
rest = 0;
switch (profile.mode){
case LINEAR_SPEED:
// speed is in [steps/s]
speed = rpm * motor_steps / 60;
if (time > 0){
// Calculate a new speed to finish in the time requested
float t = time / (1e+6); // convert to seconds
float d = steps_remaining / microsteps; // convert to full steps
float a2 = 1.0 / profile.accel + 1.0 / profile.decel;
float sqrt_candidate = t*t - 2 * a2 * d; // in √b^2-4ac
if (sqrt_candidate >= 0){
speed = min(speed, (t - (float)sqrt(sqrt_candidate)) / a2);
};
}
// how many microsteps from 0 to target speed
steps_to_cruise = microsteps * (speed * speed / (2 * profile.accel));
// how many microsteps are needed from cruise speed to a full stop
steps_to_brake = steps_to_cruise * profile.accel / profile.decel;
if (steps_remaining < steps_to_cruise + steps_to_brake){
// cannot reach max speed, will need to brake early
steps_to_cruise = steps_remaining * profile.decel / (profile.accel + profile.decel);
steps_to_brake = steps_remaining - steps_to_cruise;
}
// Initial pulse (c0) including error correction factor 0.676 [us]
step_pulse = (1e+6)*0.676*sqrt(2.0f/profile.accel/microsteps);
// Save cruise timing since we will no longer have the calculated target speed later
cruise_step_pulse = 1e+6 / speed / microsteps;
break;
case CONSTANT_SPEED:
default:
steps_to_cruise = 0;
steps_to_brake = 0;
step_pulse = cruise_step_pulse = STEP_PULSE(motor_steps, microsteps, rpm);
if (time > steps_remaining * step_pulse){
step_pulse = (float)time / steps_remaining;
}
}
}
/*
* Alter a running move by adding/removing steps
* FIXME: This is a naive implementation and it only works well in CRUISING state
*/
void BasicStepperDriver::alterMove(long steps){
switch (getCurrentState()){
case ACCELERATING: // this also works but will keep the original speed target
case CRUISING:
if (steps >= 0){
steps_remaining += steps;
} else {
steps_remaining = max(steps_to_brake, steps_remaining+steps);
};
break;
case DECELERATING:
// would need to start accelerating again -- NOT IMPLEMENTED
break;
case STOPPED:
startMove(steps);
break;
}
}
/*
* Brake early.
*/
void BasicStepperDriver::startBrake(void){
switch (getCurrentState()){
case CRUISING: // this applies to both CONSTANT_SPEED and LINEAR_SPEED modes
steps_remaining = steps_to_brake;
break;
case ACCELERATING:
steps_remaining = step_count * profile.accel / profile.decel;
break;
default:
break; // nothing to do if already stopped or braking
}
}
/*
* Stop movement immediately and return remaining steps.
*/
long BasicStepperDriver::stop(void){
long retval = steps_remaining;
steps_remaining = 0;
return retval;
}
/*
* Return calculated time to complete the given move
*/
long BasicStepperDriver::getTimeForMove(long steps){
float t;
long cruise_steps;
float speed;
if (steps == 0){
return 0;
}
switch (profile.mode){
case LINEAR_SPEED:
startMove(steps);
cruise_steps = steps_remaining - steps_to_cruise - steps_to_brake;
speed = rpm * motor_steps / 60; // full steps/s
t = (cruise_steps / (microsteps * speed)) +
sqrt(2.0 * steps_to_cruise / profile.accel / microsteps) +
sqrt(2.0 * steps_to_brake / profile.decel / microsteps);
t *= (1e+6); // seconds -> micros
break;
case CONSTANT_SPEED:
default:
t = steps * STEP_PULSE(motor_steps, microsteps, rpm);
}
return round(t);
}
/*
* Move the motor an integer number of degrees (360 = full rotation)
* This has poor precision for small amounts, since step is usually 1.8deg
*/
void BasicStepperDriver::startRotate(long deg){
startMove(calcStepsForRotation(deg));
}
/*
* Move the motor with sub-degree precision.
* Note that calling this function will increase program size substantially
* due to inclusion of float support.
*/
void BasicStepperDriver::startRotate(double deg){
startMove(calcStepsForRotation(deg));
}
/*
* calculate the interval til the next pulse
*/
void BasicStepperDriver::calcStepPulse(void){
if (steps_remaining <= 0){ // this should not happen, but avoids strange calculations
return;
}
steps_remaining--;
step_count++;
if (profile.mode == LINEAR_SPEED){
switch (getCurrentState()){
case ACCELERATING:
if (step_count < steps_to_cruise){
step_pulse = step_pulse - (2*step_pulse+rest)/(4*step_count+1);
rest = (step_count < steps_to_cruise) ? (2*step_pulse+rest) % (4*step_count+1) : 0;
} else {
// The series approximates target, set the final value to what it should be instead
step_pulse = cruise_step_pulse;
}
break;
case DECELERATING:
step_pulse = step_pulse - (2*step_pulse+rest)/(-4*steps_remaining+1);
rest = (2*step_pulse+rest) % (-4*steps_remaining+1);
break;
default:
break; // no speed changes
}
}
}
/*
* Yield to step control
* Toggle step and return time until next change is needed (micros)
*/
long BasicStepperDriver::nextAction(void){
if (steps_remaining > 0){
delayMicros(next_action_interval, last_action_end);
/*
* DIR pin is sampled on rising STEP edge, so it is set first
*/
digitalWrite(dir_pin, dir_state);
digitalWrite(step_pin, HIGH);
unsigned m = micros();
unsigned long pulse = step_pulse; // save value because calcStepPulse() will overwrite it
calcStepPulse();
// We should pull HIGH for at least 1-2us (step_high_min)
delayMicros(step_high_min);
digitalWrite(step_pin, LOW);
// account for calcStepPulse() execution time; sets ceiling for max rpm on slower MCUs
last_action_end = micros();
m = last_action_end - m;
next_action_interval = (pulse > m) ? pulse - m : 1;
} else {
// end of move
last_action_end = 0;
next_action_interval = 0;
}
return next_action_interval;
}
enum BasicStepperDriver::State BasicStepperDriver::getCurrentState(void){
enum State state;
if (steps_remaining <= 0){
state = STOPPED;
} else {
if (steps_remaining <= steps_to_brake){
state = DECELERATING;
} else if (step_count <= steps_to_cruise){
state = ACCELERATING;
} else {
state = CRUISING;
}
}
return state;
}
/*
* Configure which logic state on ENABLE pin means active
* when using SLEEP (default) this is active HIGH
*/
void BasicStepperDriver::setEnableActiveState(short state){
enable_active_state = state;
}
/*
* Enable/Disable the motor by setting a digital flag
*/
void BasicStepperDriver::enable(void){
if IS_CONNECTED(enable_pin){
digitalWrite(enable_pin, enable_active_state);
};
delayMicros(2);
}
void BasicStepperDriver::disable(void){
if IS_CONNECTED(enable_pin){
digitalWrite(enable_pin, (enable_active_state == HIGH) ? LOW : HIGH);
}
}
short BasicStepperDriver::getMaxMicrostep(){
return BasicStepperDriver::MAX_MICROSTEP;
}

View File

@@ -0,0 +1,251 @@
/*
* Generic Stepper Motor Driver Driver
* Indexer mode only.
*
* Copyright (C)2015-2018 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef STEPPER_DRIVER_BASE_H
#define STEPPER_DRIVER_BASE_H
#include <Arduino.h>
// used internally by the library to mark unconnected pins
#define PIN_UNCONNECTED -1
#define IS_CONNECTED(pin) (pin != PIN_UNCONNECTED)
/*
* calculate the step pulse in microseconds for a given rpm value.
* 60[s/min] * 1000000[us/s] / microsteps / steps / rpm
*/
#define STEP_PULSE(steps, microsteps, rpm) (60.0*1000000L/steps/microsteps/rpm)
// don't call yield if we have a wait shorter than this
#define MIN_YIELD_MICROS 50
/*
* Basic Stepper Driver class.
* Microstepping level should be externally controlled or hardwired.
*/
class BasicStepperDriver {
public:
enum Mode {CONSTANT_SPEED, LINEAR_SPEED};
enum State {STOPPED, ACCELERATING, CRUISING, DECELERATING};
struct Profile {
Mode mode = CONSTANT_SPEED;
short accel = 1000; // acceleration [steps/s^2]
short decel = 1000; // deceleration [steps/s^2]
};
static inline void delayMicros(unsigned long delay_us, unsigned long start_us = 0){
if (delay_us){
if (!start_us){
start_us = micros();
}
if (delay_us > MIN_YIELD_MICROS){
yield();
}
// See https://www.gammon.com.au/millis
while (micros() - start_us < delay_us);
}
}
private:
// calculation remainder to be fed into successive steps to increase accuracy (Atmel DOC8017)
long rest;
unsigned long last_action_end = 0;
unsigned long next_action_interval = 0;
protected:
/*
* Motor Configuration
*/
short motor_steps; // motor steps per revolution (usually 200)
/*
* Driver Configuration
*/
short dir_pin;
short step_pin;
short enable_pin = PIN_UNCONNECTED;
short enable_active_state = HIGH;
// Get max microsteps supported by the device
virtual short getMaxMicrostep();
// current microstep level (1,2,4,8,...), must be < getMaxMicrostep()
short microsteps = 1;
// tWH(STEP) pulse duration, STEP high, min value (us)
static const int step_high_min = 1;
// tWL(STEP) pulse duration, STEP low, min value (us)
static const int step_low_min = 1;
// tWAKE wakeup time, nSLEEP inactive to STEP (us)
static const int wakeup_time = 0;
float rpm = 0;
/*
* Movement state
*/
struct Profile profile;
long step_count; // current position
long steps_remaining; // to complete the current move (absolute value)
long steps_to_cruise; // steps to reach cruising (max) rpm
long steps_to_brake; // steps needed to come to a full stop
long step_pulse; // step pulse duration (microseconds)
long cruise_step_pulse; // step pulse duration for constant speed section (max rpm)
// DIR pin state
short dir_state;
void calcStepPulse(void);
// this is internal because one can call the start methods while CRUISING to get here
void alterMove(long steps);
private:
// microstep range (1, 16, 32 etc)
static const short MAX_MICROSTEP = 128;
public:
/*
* Basic connection: DIR, STEP are connected.
*/
BasicStepperDriver(short steps, short dir_pin, short step_pin);
BasicStepperDriver(short steps, short dir_pin, short step_pin, short enable_pin);
/*
* Initialize pins, calculate timings etc
*/
void begin(float rpm=60, short microsteps=1);
/*
* Set current microstep level, 1=full speed, 32=fine microstepping
* Returns new level or previous level if value out of range
*/
virtual short setMicrostep(short microsteps);
short getMicrostep(void){
return microsteps;
}
short getSteps(void){
return motor_steps;
}
/*
* Set target motor RPM (1-200 is a reasonable range)
*/
void setRPM(float rpm);
float getRPM(void){
return rpm;
};
float getCurrentRPM(void){
return (60.0*1000000L / step_pulse / microsteps / motor_steps);
}
/*
* Set speed profile - CONSTANT_SPEED, LINEAR_SPEED (accelerated)
* accel and decel are given in [full steps/s^2]
*/
void setSpeedProfile(Mode mode, short accel=1000, short decel=1000);
void setSpeedProfile(struct Profile profile);
struct Profile getSpeedProfile(void){
return profile;
}
short getAcceleration(void){
return profile.accel;
}
short getDeceleration(void){
return profile.decel;
}
/*
* Move the motor a given number of steps.
* positive to move forward, negative to reverse
*/
void move(long steps);
/*
* Rotate the motor a given number of degrees (1-360)
*/
void rotate(long deg);
inline void rotate(int deg){
rotate((long)deg);
};
/*
* Rotate using a float or double for increased movement precision.
*/
void rotate(double deg);
/*
* Configure which logic state on ENABLE pin means active
* when using SLEEP (default) this is active HIGH
*/
void setEnableActiveState(short state);
/*
* Turn off/on motor to allow the motor to be moved by hand/hold the position in place
*/
virtual void enable(void);
virtual void disable(void);
/*
* Methods for non-blocking mode.
* They use more code but allow doing other operations between impulses.
* The flow has two parts - start/initiate followed by looping with nextAction.
* See NonBlocking example.
*/
/*
* Initiate a move over known distance (calculate and save the parameters)
* Pick just one based on move type and distance type.
* If time (microseconds) is given, the driver will attempt to execute the move in exactly that time
* by altering rpm for this move only (up to preset rpm).
*/
void startMove(long steps, long time=0);
inline void startRotate(int deg){
startRotate((long)deg);
};
void startRotate(long deg);
void startRotate(double deg);
/*
* Toggle step at the right time and return time until next change is needed (micros)
*/
long nextAction(void);
/*
* Optionally, call this to begin braking (and then stop) early
* For constant speed, this is the same as stop()
*/
void startBrake(void);
/*
* Immediate stop
* Returns the number of steps remaining.
*/
long stop(void);
/*
* State querying
*/
enum State getCurrentState(void);
/*
* Get the number of completed steps so far.
* This is always a positive number
*/
long getStepsCompleted(void){
return step_count;
}
/*
* Get the number of steps remaining to complete the move
* This is always a positive number
*/
long getStepsRemaining(void){
return steps_remaining;
}
/*
* Get movement direction: forward +1, back -1
*/
int getDirection(void){
return (dir_state == HIGH) ? 1 : -1;
}
/*
* Return calculated time to complete the given move
*/
long getTimeForMove(long steps);
/*
* Calculate steps needed to rotate requested angle, given in degrees
*/
long calcStepsForRotation(long deg){
return deg * motor_steps * (long)microsteps / 360;
}
long calcStepsForRotation(double deg){
return deg * motor_steps * microsteps / 360;
}
};
#endif // STEPPER_DRIVER_BASE_H

View File

@@ -0,0 +1,49 @@
/*
* DRV8825 - Stepper Motor Driver Driver
* Indexer mode only.
* Copyright (C)2015 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include "DRV8825.h"
/*
* Microstepping resolution truth table (Page 13 of DRV8825 pdf)
* 0bMODE2,MODE1,MODE0 for 1,2,4,8,16,32 microsteps
*/
const uint8_t DRV8825::MS_TABLE[] = {0b000, 0b001, 0b010, 0b011, 0b100, 0b111};
DRV8825::DRV8825(short steps, short dir_pin, short step_pin)
:A4988(steps, dir_pin, step_pin)
{}
DRV8825::DRV8825(short steps, short dir_pin, short step_pin, short enable_pin)
:A4988(steps, dir_pin, step_pin, enable_pin)
{}
/*
* A4988-DRV8825 Compatibility map: MS1-MODE0, MS2-MODE1, MS3-MODE2
*/
DRV8825::DRV8825(short steps, short dir_pin, short step_pin, short mode0_pin, short mode1_pin, short mode2_pin)
:A4988(steps, dir_pin, step_pin, mode0_pin, mode1_pin, mode2_pin)
{}
DRV8825::DRV8825(short steps, short dir_pin, short step_pin, short enable_pin, short mode0_pin, short mode1_pin, short mode2_pin)
:A4988(steps, dir_pin, step_pin, enable_pin, mode0_pin, mode1_pin, mode2_pin)
{}
const uint8_t* DRV8825::getMicrostepTable()
{
return (uint8_t*)DRV8825::MS_TABLE;
}
size_t DRV8825::getMicrostepTableSize()
{
return sizeof(DRV8825::MS_TABLE);
}
short DRV8825::getMaxMicrostep(){
return DRV8825::MAX_MICROSTEP;
}

View File

@@ -0,0 +1,43 @@
/*
* DRV8825 - Stepper Motor Driver Driver (A4988-compatible)
* Indexer mode only.
*
* Copyright (C)2015 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef DRV8825_H
#define DRV8825_H
#include <Arduino.h>
#include "A4988.h"
class DRV8825 : public A4988 {
protected:
static const uint8_t MS_TABLE[];
// tWH(STEP) pulse duration, STEP high, min value (1.9us)
static const int step_high_min = 2;
// tWL(STEP) pulse duration, STEP low, min value (1.9us)
static const int step_low_min = 2;
// tWAKE wakeup time, nSLEEP inactive to STEP (1000us)
static const int wakeup_time = 1700;
// also 650ns between ENBL/DIR/MODEx changes and STEP HIGH
// Get the microstep table
const uint8_t* getMicrostepTable() override;
size_t getMicrostepTableSize() override;
// Get max microsteps supported by the device
short getMaxMicrostep() override;
private:
// microstep range (1, 16, 32 etc)
static const short MAX_MICROSTEP = 32;
public:
DRV8825(short steps, short dir_pin, short step_pin);
DRV8825(short steps, short dir_pin, short step_pin, short enable_pin);
DRV8825(short steps, short dir_pin, short step_pin, short mode0_pin, short mode1_pin, short mode2_pin);
DRV8825(short steps, short dir_pin, short step_pin, short enable_pin, short mode0_pin, short mode1_pin, short mode2_pin);
};
#endif // DRV8825_H

View File

@@ -0,0 +1,85 @@
/*
* DRV8834 - LV Stepper Motor Driver Driver (A4988-compatible - mostly)
* Indexer mode only.
* Copyright (C)2015 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include "DRV8834.h"
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
DRV8834::DRV8834(short steps, short dir_pin, short step_pin)
:BasicStepperDriver(steps, dir_pin, step_pin)
{}
DRV8834::DRV8834(short steps, short dir_pin, short step_pin, short enable_pin)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin)
{}
/*
* Fully wired. All the necessary control pins for DRV8834 are connected.
*/
DRV8834::DRV8834(short steps, short dir_pin, short step_pin, short m0_pin, short m1_pin)
:BasicStepperDriver(steps, dir_pin, step_pin), m0_pin(m0_pin), m1_pin(m1_pin)
{}
DRV8834::DRV8834(short steps, short dir_pin, short step_pin, short enable_pin, short m0_pin, short m1_pin)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin), m0_pin(m0_pin), m1_pin(m1_pin)
{}
/*
* Set microstepping mode (1:divisor)
* Allowed ranges for DRV8834 are 1:1 to 1:32
* If the control pins are not connected, we recalculate the timing only
*
*/
short DRV8834::setMicrostep(short microsteps){
BasicStepperDriver::setMicrostep(microsteps);
if (!IS_CONNECTED(m0_pin) || !IS_CONNECTED(m1_pin)){
return this->microsteps;
}
/*
* Step mode truth table
* M1 M0 step mode
* 0 0 1
* 0 1 2
* 0 Z 4
* 1 0 8
* 1 1 16
* 1 Z 32
*
* Z = high impedance mode (M0 is tri-state)
*/
pinMode(m1_pin, OUTPUT);
digitalWrite(m1_pin, (this->microsteps < 8) ? LOW : HIGH);
switch(this->microsteps){
case 1:
case 8:
pinMode(m0_pin, OUTPUT);
digitalWrite(m0_pin, LOW);
break;
case 2:
case 16:
pinMode(m0_pin, OUTPUT);
digitalWrite(m0_pin, HIGH);
break;
case 4:
case 32:
pinMode(m0_pin, INPUT); // Z - high impedance
break;
}
return this->microsteps;
}
short DRV8834::getMaxMicrostep(){
return DRV8834::MAX_MICROSTEP;
}

View File

@@ -0,0 +1,48 @@
/*
* DRV8834 - LV Stepper Motor Driver Driver (A4988-compatible - mostly)
* Indexer mode only.
*
* Copyright (C)2015 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef DRV8834_H
#define DRV8834_H
#include <Arduino.h>
#include "BasicStepperDriver.h"
class DRV8834 : public BasicStepperDriver {
protected:
short m0_pin = PIN_UNCONNECTED;
short m1_pin = PIN_UNCONNECTED;
// tWH(STEP) pulse duration, STEP high, min value (1.9us)
static const int step_high_min = 2;
// tWL(STEP) pulse duration, STEP low, min value (1.9us)
static const int step_low_min = 2;
// tWAKE wakeup time, nSLEEP inactive to STEP (1000us)
static const int wakeup_time = 1000;
// also 200ns between ENBL/DIR/Mx changes and STEP HIGH
// Get max microsteps supported by the device
short getMaxMicrostep() override;
private:
// microstep range (1, 16, 32 etc)
static const short MAX_MICROSTEP = 32;
public:
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
DRV8834(short steps, short dir_pin, short step_pin);
DRV8834(short steps, short dir_pin, short step_pin, short enable_pin);
/*
* Fully wired. All the necessary control pins for DRV8834 are connected.
*/
DRV8834(short steps, short dir_pin, short step_pin, short m0_pin, short m1_pin);
DRV8834(short steps, short dir_pin, short step_pin, short enable_pin, short m0_pin, short m1_pin);
short setMicrostep(short microsteps) override;
};
#endif // DRV8834_H

View File

@@ -0,0 +1,121 @@
/*
* DRV8880 - 2A Stepper Motor Driver with AutoTune and Torque Control
*
* Copyright (C)2017 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include "DRV8880.h"
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
DRV8880::DRV8880(short steps, short dir_pin, short step_pin)
:BasicStepperDriver(steps, dir_pin, step_pin)
{}
DRV8880::DRV8880(short steps, short dir_pin, short step_pin, short enable_pin)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin)
{}
/*
* Fully wired. All the necessary control pins for DRV8880 are connected.
*/
DRV8880::DRV8880(short steps, short dir_pin, short step_pin, short m0, short m1)
:BasicStepperDriver(steps, dir_pin, step_pin), m0(m0), m1(m1)
{}
DRV8880::DRV8880(short steps, short dir_pin, short step_pin, short enable_pin, short m0, short m1)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin), m0(m0), m1(m1)
{}
DRV8880::DRV8880(short steps, short dir_pin, short step_pin, short m0, short m1, short trq0, short trq1)
:BasicStepperDriver(steps, dir_pin, step_pin), m0(m0), m1(m1), trq0(trq0), trq1(trq1)
{}
DRV8880::DRV8880(short steps, short dir_pin, short step_pin, short enable_pin, short m0, short m1, short trq0, short trq1)
:BasicStepperDriver(steps, dir_pin, step_pin, enable_pin), m0(m0), m1(m1), trq0(trq0), trq1(trq1)
{}
void DRV8880::begin(float rpm, short microsteps){
BasicStepperDriver::begin(rpm, microsteps);
setCurrent(100);
}
short DRV8880::getMaxMicrostep(){
return DRV8880::MAX_MICROSTEP;
}
/*
* Set microstepping mode (1:divisor)
* Allowed ranges for DRV8880 are 1:1 to 1:16
* If the control pins are not connected, we recalculate the timing only
*/
short DRV8880::setMicrostep(short microsteps){
BasicStepperDriver::setMicrostep(microsteps);
if (!IS_CONNECTED(m0) || !IS_CONNECTED(m1)){
return this->microsteps;
}
/*
* Step mode truth table
* M1 M0 step mode
* 0 0 1
* 1 0 2
* 1 1 4
* 0 Z 8
* 1 Z 16
*
* 0 1 2 (non-circular, not implemented)
* Z = high impedance mode (M0 is tri-state)
*/
pinMode(m1, OUTPUT);
pinMode(m0, OUTPUT);
switch(this->microsteps){
case 1:
digitalWrite(m1, LOW);
digitalWrite(m0, LOW);
break;
case 2:
digitalWrite(m1, HIGH);
digitalWrite(m0, LOW);
break;
case 4:
digitalWrite(m1, HIGH);
digitalWrite(m0, HIGH);
break;
case 8:
digitalWrite(m1, LOW);
pinMode(m0, INPUT); // Z - high impedance
break;
case 16:
digitalWrite(m1, HIGH);
pinMode(m0, INPUT); // Z - high impedance
break;
}
return this->microsteps;
}
void DRV8880::setCurrent(short percent){
/*
* Torque DAC Settings table
* TRQ1 TRQ0 Current scalar
* 1 1 25%
* 1 0 50%
* 0 1 75%
* 0 0 100%
*/
if (!IS_CONNECTED(trq1) || !IS_CONNECTED(trq0)){
return;
}
pinMode(trq1, OUTPUT);
pinMode(trq0, OUTPUT);
percent = (100-percent)/25;
digitalWrite(trq1, percent & 2);
digitalWrite(trq0, percent & 1);
}

View File

@@ -0,0 +1,63 @@
/*
* DRV8880 - 2A Stepper Motor Driver with AutoTune and Torque Control
*
* Copyright (C)2017 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef DRV8880_H
#define DRV8880_H
#include <Arduino.h>
#include "BasicStepperDriver.h"
class DRV8880 : public BasicStepperDriver {
protected:
short m0 = PIN_UNCONNECTED;
short m1 = PIN_UNCONNECTED;
short trq0 = PIN_UNCONNECTED;
short trq1 = PIN_UNCONNECTED;
// tWH(STEP) pulse duration, STEP high, min value
static const int step_high_min = 0; // 0.47us
// tWL(STEP) pulse duration, STEP low, min value
static const int step_low_min = 0; // 0.47us
// tWAKE wakeup time, nSLEEP inactive to STEP
static const int wakeup_time = 1500;
// also 200ns between ENBL/DIR/Mx changes and STEP HIGH
// Get max microsteps supported by the device
short getMaxMicrostep() override;
private:
// microstep range (1, 16, 32 etc)
static const short MAX_MICROSTEP = 16;
public:
/*
* Basic connection: only DIR, STEP are connected.
* Microstepping controls should be hardwired.
*/
DRV8880(short steps, short dir_pin, short step_pin);
DRV8880(short steps, short dir_pin, short step_pin, short enable_pin);
/*
* DIR, STEP and microstep control M0, M1
*/
DRV8880(short steps, short dir_pin, short step_pin, short m0, short m1);
DRV8880(short steps, short dir_pin, short step_pin, short enable_pin, short m0, short m1);
/*
* Fully Wired - DIR, STEP, microstep and current control
*/
DRV8880(short steps, short dir_pin, short step_pin, short m0, short m1, short trq0, short trq1);
DRV8880(short steps, short dir_pin, short step_pin, short enable_pin, short m0, short m1, short trq0, short trq1);
void begin(float rpm=60, short microsteps=1);
short setMicrostep(short microsteps) override;
/*
* Torque DAC Control
* current percent value must be 25, 50, 75 or 100.
*/
void setCurrent(short percent=100);
};
#endif // DRV8880_H

View File

@@ -0,0 +1,123 @@
/*
* Multi-motor group driver
*
* Copyright (C)2017-2019 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include "MultiDriver.h"
#define FOREACH_MOTOR(action) for (short i=count-1; i >= 0; i--){action;}
/*
* Initialize motor parameters
*/
void MultiDriver::startMove(long steps1, long steps2, long steps3){
long steps[3] = {steps1, steps2, steps3};
/*
* Initialize state for all active motors
*/
FOREACH_MOTOR(
if (steps[i]){
motors[i]->startMove(steps[i]);
event_timers[i] = 1;
} else {
event_timers[i] = 0;
}
);
ready = false;
last_action_end = 0;
next_action_interval = 1;
}
/*
* Trigger next step action
*/
long MultiDriver::nextAction(void){
Motor::delayMicros(next_action_interval, last_action_end);
// TODO: unroll these loops
// Trigger all the motors that need it
FOREACH_MOTOR(
if (event_timers[i] <= next_action_interval){
event_timers[i] = motors[i]->nextAction();
} else {
event_timers[i] -= next_action_interval;
}
);
last_action_end = micros();
next_action_interval = 0;
// Find the time when the next pulse needs to fire
// this is the smallest non-zero timer value from all active motors
FOREACH_MOTOR(
if (event_timers[i] > 0 && (event_timers[i] < next_action_interval || next_action_interval == 0)){
next_action_interval = event_timers[i];
}
);
ready = (next_action_interval == 0);
return next_action_interval;
}
/*
* Optionally, call this to begin braking to stop early
*/
void MultiDriver::startBrake(void){
FOREACH_MOTOR(
if (event_timers[i] > 0){
motors[i]->startBrake();
}
)
}
/*
* State querying
*/
bool MultiDriver::isRunning(void){
bool running = false;
FOREACH_MOTOR(
if (motors[i]->getCurrentState() != Motor::STOPPED){
running = true;
break;
}
)
return running;
}
/*
* Move each motor the requested number of steps, in parallel
* positive to move forward, negative to reverse, 0 to remain still
*/
void MultiDriver::move(long steps1, long steps2, long steps3){
startMove(steps1, steps2, steps3);
while (!ready){
nextAction();
}
}
#define CALC_STEPS(i, deg) ((motors[i] && deg) ? motors[i]->calcStepsForRotation(deg) : 0)
void MultiDriver::rotate(long deg1, long deg2, long deg3){
move(CALC_STEPS(0, deg1), CALC_STEPS(1, deg2), CALC_STEPS(2, deg3));
}
void MultiDriver::rotate(double deg1, double deg2, double deg3){
move(CALC_STEPS(0, deg1), CALC_STEPS(1, deg2), CALC_STEPS(2, deg3));
}
void MultiDriver::startRotate(long deg1, long deg2, long deg3){
startMove(CALC_STEPS(0, deg1), CALC_STEPS(1, deg2), CALC_STEPS(2, deg3));
}
void MultiDriver::startRotate(double deg1, double deg2, double deg3){
startMove(CALC_STEPS(0, deg1), CALC_STEPS(1, deg2), CALC_STEPS(2, deg3));
}
void MultiDriver::setMicrostep(unsigned microsteps){
FOREACH_MOTOR(motors[i]->setMicrostep(microsteps));
}
void MultiDriver::enable(void){
FOREACH_MOTOR(motors[i]->enable());
}
void MultiDriver::disable(void){
FOREACH_MOTOR(motors[i]->disable());
}

View File

@@ -0,0 +1,105 @@
/*
* Multi-motor group driver
*
* Copyright (C)2017 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef MULTI_DRIVER_H
#define MULTI_DRIVER_H
#include <Arduino.h>
#include "BasicStepperDriver.h"
#define MAX_MOTORS 3 // a reasonable but arbitrary limit
#define Motor BasicStepperDriver
/*
* Multi-motor group driver class.
*/
class MultiDriver {
protected:
/*
* Configuration
*/
unsigned short count;
Motor* const *motors;
/*
* Generic initializer, will be called by the others
*/
MultiDriver(const unsigned short count, Motor* const *motors)
:count(count), motors(motors)
{};
/*
* Movement state
*/
// ready to start a new move
bool ready = true;
// when next state change is due for each motor
unsigned long event_timers[MAX_MOTORS];
unsigned long next_action_interval = 0;
unsigned long last_action_end = 0;
public:
/*
* Two-motor setup
*/
MultiDriver(Motor& motor1, Motor& motor2)
:MultiDriver(2, new Motor* const[2]{&motor1, &motor2})
{};
/*
* Three-motor setup (X, Y, Z for example)
*/
MultiDriver(Motor& motor1, Motor& motor2, Motor& motor3)
:MultiDriver(3, new Motor* const[3]{&motor1, &motor2, &motor3})
{};
unsigned short getCount(void){
return count;
}
Motor& getMotor(short index){
return *motors[index];
}
/*
* Move the motors a given number of steps.
* positive to move forward, negative to reverse
*/
void move(long steps1, long steps2, long steps3=0);
void rotate(int deg1, int deg2, int deg3=0){
rotate((long)deg1, (long)deg2, (long)deg3);
};
void rotate(long deg1, long deg2, long deg3=0);
void rotate(double deg1, double deg2, double deg3=0);
/*
* Motor movement with external control of timing
*/
virtual void startMove(long steps1, long steps2, long steps3=0);
void startRotate(int deg1, int deg2, int deg3=0){
startRotate((long)deg1, (long)deg2, (long)deg3);
};
void startRotate(long deg1, long deg2, long deg3=0);
void startRotate(double deg1, double deg2, double deg3=0);
/*
* Toggle step and return time until next change is needed (micros)
*/
virtual long nextAction(void);
/*
* Optionally, call this to begin braking to stop early
*/
void startBrake(void);
/*
* State querying
*/
bool isRunning(void);
/*
* Set the same microstepping level on all motors
*/
void setMicrostep(unsigned microsteps);
/*
* Turn all motors on or off
*/
void enable(void);
void disable(void);
};
#endif // MULTI_DRIVER_H

View File

@@ -0,0 +1,43 @@
/*
* Synchronous Multi-motor group driver
* All motors reach their target at the same time.
*
* Copyright (C)2017-2019 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include "SyncDriver.h"
#define FOREACH_MOTOR(action) for (short i=count-1; i >= 0; i--){action;}
/*
* Initialize motor parameters
*/
void SyncDriver::startMove(long steps1, long steps2, long steps3){
long steps[3] = {steps1, steps2, steps3};
/*
* find which motor would take the longest to finish,
*/
long move_time = 0;
FOREACH_MOTOR(
long m = motors[i]->getTimeForMove(labs(steps[i]));
if (m > move_time){
move_time = m;
}
);
/*
* Initialize state for all active motors to complete with <move_time> micros
*/
FOREACH_MOTOR(
if (steps[i]){
motors[i]->startMove(steps[i], move_time);
event_timers[i] = 1;
} else {
event_timers[i] = 0;
}
);
ready = false;
last_action_end = 0;
next_action_interval = 1;
}

View File

@@ -0,0 +1,26 @@
/*
* Synchronous Multi-motor group driver
* All motors reach their target at the same time.
*
* Copyright (C)2017-2019 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#ifndef SYNC_DRIVER_H
#define SYNC_DRIVER_H
#include <Arduino.h>
#include "MultiDriver.h"
/*
* Synchronous Multi-motor group driver class.
* This driver sets up timing so all motors reach their target at the same time.
*/
class SyncDriver : public MultiDriver {
using MultiDriver::MultiDriver;
public:
void startMove(long steps1, long steps2, long steps3=0) override;
};
#endif // SYNC_DRIVER_H

24
clockclock/platformio.ini Normal file
View File

@@ -0,0 +1,24 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env]
platform = ststm32
framework = arduino
upload_port = stlink
debug_tool = stlink
lib_ldf_mode = deep+
lib_deps =
http://192.168.2.3/Bonobo.Git.Server/Accelstepper.git
[env:clockclock_hwV10]
board = STM32L422KB
build_flags =
-DHARDWAREVERSION=10
-O2

View File

@@ -0,0 +1,27 @@
#include "buttons.h"
#include "motor.h"
Button buttonPlus(MCU_BUT_PLUS, 25UL, true, true);
Button buttonMin(MCU_BUT_MIN, 25UL, true, true);
void handleButtons(void)
{
if (buttonPlus.read())
{
increaseMotor(MOTOR0);
}
if (buttonMin.read())
{
increaseMotor(MOTOR1);
}
}
void initButtons(void)
{
buttonPlus.begin();
buttonMin.begin();
}

11
clockclock/src/buttons.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include "Arduino.h"
#include "JC_Button.h"
#include "board.h"
void handleButtons(void);
void initButtons(void);

52
clockclock/src/comms.cpp Normal file
View File

@@ -0,0 +1,52 @@
#include "comms.h"
#include "board.h"
#include "Wire.h"
uint8_t getAddress(void)
{
uint8_t address = 0;
address += (digitalRead(ADDR0)) ? 1 : 0;
address += (digitalRead(ADDR1)) ? 2 : 0;
address += (digitalRead(ADDR2)) ? 4 : 0;
address += (digitalRead(ADDR3)) ? 8 : 0;
return address;
}
void receiveI2CEvent(int bytes) {
Wire.read(); // read one character from the I2C
}
void requestI2CEvent() {
Wire.read(); // read one character from the I2C
}
uint8_t address;
void initI2C( void)
{
pinMode(ADDR0, INPUT_PULLUP);
pinMode(ADDR1, INPUT_PULLUP);
pinMode(ADDR2, INPUT_PULLUP);
pinMode(ADDR3, INPUT_PULLUP);
address = getAddress();
// Start the I2C Bus as Slave on address 9
Wire.begin(address);
// Attach a function to trigger when something is received.
Wire.onReceive(receiveI2CEvent);
Wire.onRequest(requestI2CEvent);
}
void handleI2C ( void )
{
}

28
clockclock/src/comms.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "Arduino.h"
#define MSGLEN 10
class c_message
{
uint8_t _buffer[MSGLEN];
uint8_t _bufIndex = 0;
bool validheader;
public:
c_message();
void addByte(uint8_t byte)
{
_buffer[_bufIndex++] = byte;
if(_bufIndex >= MSGLEN)
{
_bufIndex = 0;
}
}
};
void initI2C( void);
void handleI2C ( void );

16
clockclock/src/main.cpp Normal file
View File

@@ -0,0 +1,16 @@
#include <Arduino.h>
#include "board_v10.h"
#include "motor.h"
#include "buttons.h"
void setup() {
// put your setup code here, to run once:
initMotors();
initButtons();
}
void loop() {
// put your main code here, to run repeatedly:
handleMotors();
handleButtons();
}

105
clockclock/src/motor.cpp Normal file
View File

@@ -0,0 +1,105 @@
#include "motor.h"
#include "arduino.h"
#include "board_v10.h"
#include "MultiStepper.h"
c_motor motor0(MOT_STCK0, MOT_DIR0, MOT_EN0, MOT_RST0);
c_motor motor1(MOT_STCK1, MOT_DIR1, MOT_EN1, MOT_RST1);
MultiStepper motors;
void c_motor::init(bool setvref)
{
pinMode(_rst, OUTPUT);
pinMode(_en, OUTPUT);
pinMode(_sclk, OUTPUT);
pinMode(_dir, OUTPUT);
digitalWrite(_rst, 0);
digitalWrite(_sclk, 0);
digitalWrite(_dir, 0);
digitalWrite(_en, 0);
delay(200);
digitalWrite(_rst, 1);
if (setvref)
{
pinMode(MOT_VREF1, OUTPUT);
analogWrite(MOT_VREF1, 32);
}
}
void c_motor::begin(void)
{
_stepper.begin(RPM, MICROSTEPS);
_stepper.enable();
}
void c_motor::decreasePos(void)
{
if (ready())
{
_stepper.move(-OFFSET);
}
}
void c_motor::increasePos(void)
{
if (ready())
{
_stepper.move(OFFSET);
}
}
bool c_motor::ready(void)
{
return (_stepper.getCurrentState() == _stepper.State::STOPPED);
}
void handleMotors(void)
{
motor0.run();
motor1.run();
}
void initMotors(void)
{
motor0.init(true);
motor0.begin();
motor1.init();
motor1.begin();
}
void SetMotors(long pos0, long pos1)
{
motor0.moveTo(pos0);
motor1.moveTo(pos1);
}
void increaseMotor(e_motor motor)
{
if (motor == MOTOR0)
{
motor0.increasePos();
}
if (motor == MOTOR1)
{
motor1.increasePos();
}
}
void decreaseMotor(e_motor motor)
{
if (motor == MOTOR0)
{
motor0.decreasePos();
}
if (motor == MOTOR1)
{
motor1.decreasePos();
}
}

69
clockclock/src/motor.h Normal file
View File

@@ -0,0 +1,69 @@
#pragma once
//#include "AccelStepper.h"
#include "BasicStepperDriver.h"
#define OFFSET 5
#define MOTOR_STEPS 360
#define RPM 120
#define MICROSTEPS 1
typedef enum
{
MOTOR0,
MOTOR1
} e_motor;
class c_motor
{
const int _sclk;
const int _dir;
const int _en;
const int _rst;
long _currentpos;
long _targetpos;
//AccelStepper _stepper;
BasicStepperDriver _stepper;
public:
c_motor(int sclk, int dir, int en, int rst) : _sclk(sclk), _dir(dir), _en(en), _rst(rst),
_stepper(MOTOR_STEPS, _sclk, _dir, _en)
{
}
void init(bool setvref = false);
void begin(void);
void moveTo(long pos)
{
_stepper.startMove(pos);
if((_targetpos += pos) > 360)
{
_targetpos -= 360;
}
}
bool ready( void );
void run(void)
{
_stepper.nextAction();
}
void increasePos(void);
void decreasePos(void);
BasicStepperDriver *getStepper(void)
{
return &_stepper;
}
};
void handleMotors(void);
void initMotors(void);
void SetMotors(long pos0, long pos1);
void increaseMotor(e_motor motor);
void decreaseMotor(e_motor motor);

11
clockclock/test/README Normal file
View File

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html

View File

@@ -0,0 +1,196 @@
/*
*******************************************************************************
* Copyright (c) 2019, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
* Automatically generated from STM32L031K(4-6)Tx.xml
*/
#include "Arduino.h"
#include "PeripheralPins.h"
/* =====
* Note: Commented lines are alternative possibilities which are not used per default.
* If you change them, you will have to know what you do
* =====
*/
//*** ADC ***
#ifdef HAL_ADC_MODULE_ENABLED
WEAK const PinMap PinMap_ADC[] = {
{PA_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC_IN0
{PA_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC_IN1
// {PA_2, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC_IN2 - Connected to STDIO_UART_TX
{PA_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC_IN3
{PA_4, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC_IN4
{PA_5, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC_IN5
{PA_6, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC_IN6
{PA_7, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC_IN7
{PB_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC_IN8
{PB_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC_IN9
{NC, NP, 0}
};
#endif
//*** No DAC ***
//*** I2C ***
#ifdef HAL_I2C_MODULE_ENABLED
WEAK const PinMap PinMap_I2C_SDA[] = {
{PA_10, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF1_I2C1)},
{PB_7, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF1_I2C1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_I2C_MODULE_ENABLED
WEAK const PinMap PinMap_I2C_SCL[] = {
{PA_9, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF1_I2C1)},
{PB_6, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF1_I2C1)},
{NC, NP, 0}
};
#endif
//*** PWM ***
#ifdef HAL_TIM_MODULE_ENABLED
WEAK const PinMap PinMap_PWM[] = {
{PA_0, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM2, 1, 0)}, // TIM2_CH1
{PA_1, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM2, 2, 0)}, // TIM2_CH2
// {PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM2, 3, 0)}, // TIM2_CH3
// {PA_2, TIM21, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_TIM21, 1, 0)}, // TIM21_CH1
{PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM2, 4, 0)}, // TIM2_CH4
// {PA_3, TIM21, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_TIM21, 2, 0)}, // TIM21_CH2
{PA_5, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM2, 1, 0)}, // TIM2_CH1
{PA_6, TIM22, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM22, 1, 0)}, // TIM22_CH1
{PA_7, TIM22, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM22, 2, 0)}, // TIM22_CH2
{PA_8, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM2, 1, 0)}, // TIM2_CH1
{PA_9, TIM22, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM22, 1, 0)}, // TIM22_CH1
{PA_10, TIM22, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM22, 2, 0)}, // TIM22_CH2
// {PA_11, TIM21, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM21, 2, 0)}, // TIM21_CH2
// {PA_15, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM2, 1, 0)}, // TIM2_CH1
{PB_0, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM2, 3, 0)}, // TIM2_CH3
{PB_1, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM2, 4, 0)}, // TIM2_CH4
{PB_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF2_TIM2, 2, 0)}, // TIM2_CH2
{PB_4, TIM22, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_TIM22, 1, 0)}, // TIM22_CH1
{PB_5, TIM22, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_TIM22, 2, 0)}, // TIM22_CH2
// {PB_6, TIM21, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_TIM21, 1, 0)}, // TIM21_CH1
{NC, NP, 0}
};
#endif
//*** SERIAL ***
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_TX[] = {
// {PA_2, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_LPUART1)},
{PA_2, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)}, // STLink TX
{PA_9, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
// {PA_14, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_LPUART1)},
{PA_14, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
{PB_6, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_USART2)},
{NC, NP, 0}
};
#endif
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_RX[] = {
// {PA_3, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_LPUART1)},
{PA_3, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
{PA_10, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
// {PA_13, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF6_LPUART1)},
{PA_15, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)}, // STLink RX
{PB_7, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_USART2)},
{NC, NP, 0}
};
#endif
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_RTS[] = {
{PA_1, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
{PA_12, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
{PB_0, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
// {PB_1, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_LPUART1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_CTS[] = {
{PA_0, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
// {PA_6, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_LPUART1)},
{PA_7, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
{PA_11, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF4_USART2)},
{NC, NP, 0}
};
#endif
//*** SPI ***
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_MOSI[] = {
{PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{PB_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_SPI1)},
{PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_MISO[] = {
{PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{PB_0, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_SPI1)},
{PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_SCLK[] = {
{PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_SSEL[] = {
{PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
// {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF0_SPI1)},
{NC, NP, 0}
};
#endif
//*** No CAN ***
//*** No ETHERNET ***
//*** No QUADSPI ***
//*** No USB ***

View File

@@ -0,0 +1,25 @@
/* SYS_WKUP */
#ifdef PWR_WAKEUP_PIN1
SYS_WKUP1 = PA_0,
#endif
#ifdef PWR_WAKEUP_PIN2
SYS_WKUP2 = NC,
#endif
#ifdef PWR_WAKEUP_PIN3
SYS_WKUP3 = PA_2,
#endif
#ifdef PWR_WAKEUP_PIN4
SYS_WKUP4 = NC,
#endif
#ifdef PWR_WAKEUP_PIN5
SYS_WKUP5 = NC,
#endif
#ifdef PWR_WAKEUP_PIN6
SYS_WKUP6 = NC,
#endif
#ifdef PWR_WAKEUP_PIN7
SYS_WKUP7 = NC,
#endif
#ifdef PWR_WAKEUP_PIN8
SYS_WKUP8 = NC,
#endif

View File

@@ -0,0 +1,188 @@
/*
*****************************************************************************
**
** File : LinkerScript.ld
**
** Abstract : Linker script for STM32L031K6Tx Device with
** 32KByte FLASH, 8KByte RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
*****************************************************************************
** @attention
**
** <h2><center>&copy; COPYRIGHT(c) 2014 Ac6</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of Ac6 nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20002000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}

View File

@@ -0,0 +1,123 @@
/*
*******************************************************************************
* Copyright (c) 2017, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#include "pins_arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
// Pin number
const PinName digitalPin[] = {
PA_10, //D0
PA_9, //D1
PA_12, //D2
PB_0, //D3
PB_7, //D4
PB_6, //D5
PB_1, //D6
PC_14, //D7
PC_15, //D8
PA_8, //D9
PA_11, //D10
PB_5, //D11
PB_4, //D12
PB_3, //D13 - LED
PA_0, //D14/A0
PA_1, //D15/A1
PA_3, //D16/A2
PA_4, //D17/A3
PA_5, //D18/A4
PA_6, //D19/A5
PA_7, //D20/A6
PA_2, //D21/A7 - STLink Tx
PA_15, //D22 - STLink Rx
PB_2, //D23
PB_8 //D24
};
#ifdef __cplusplus
}
#endif
// ----------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief System Clock Configuration
* @param None
* @retval None
*/
WEAK void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
/* Configure the main internal regulator output voltage */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Initializes the CPU, AHB and APB buses clocks */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_4;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
/* Initializes the CPU, AHB and APB busses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,120 @@
/*
*******************************************************************************
* Copyright (c) 2017, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#ifndef _VARIANT_ARDUINO_STM32_
#define _VARIANT_ARDUINO_STM32_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/*----------------------------------------------------------------------------
* Pins
*----------------------------------------------------------------------------*/
#define PA10 0
#define PA9 1
#define PA12 2
#define PB0 3
#define PB7 4
#define PB6 5
#define PB1 6
#define PC14 7
#define PC15 8
#define PA8 9
#define PA11 10
#define PB5 11
#define PB4 12
#define PB3 13 // LED
#define PA0 14 // A0
#define PA1 15 // A1
#define PA3 16 // A2
#define PA4 17 // A3
#define PA5 18 // A4
#define PA6 19 // A5
#define PA7 20 // A6
#define PA2 21 // A7 - STLink Tx
#define PA15 22 // STLink Rx
#define PB2 23
#define PB8 24
// This must be a literal
#define NUM_DIGITAL_PINS 25
// This must be a literal with a value less than or equal to to MAX_ANALOG_INPUTS
#define NUM_ANALOG_INPUTS 7
#define NUM_ANALOG_FIRST 14
// On-board LED pin number
//#define LED_BUILTIN 13
//#define LED_GREEN LED_BUILTIN
// I2C Definitions
#define PIN_WIRE_SDA 0
#define PIN_WIRE_SCL 1
//Timer Definitions
#define TIMER_TONE TIM2
#define TIMER_SERVO TIM21
// UART Definitions
#define SERIAL_UART_INSTANCE 2 //ex: 2 for Serial2 (USART2)
// Default pin used for 'Serial' instance (ex: ST-Link)
// Mandatory for Firmata
#define PIN_SERIAL_RX PA15
#define PIN_SERIAL_TX PA2
#ifdef __cplusplus
} // extern "C"
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
#define SERIAL_PORT_MONITOR Serial
#define SERIAL_PORT_HARDWARE Serial
#endif
#endif /* _VARIANT_ARDUINO_STM32_ */

View File

@@ -0,0 +1,226 @@
/*
*******************************************************************************
* Copyright (c) 2019, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
* Automatically generated from STM32L412KBTx.xml
*/
#include "Arduino.h"
#include "PeripheralPins.h"
/* =====
* Note: Commented lines are alternative possibilities which are not used per default.
* If you change them, you will have to know what you do
* =====
*/
//*** ADC ***
#ifdef HAL_ADC_MODULE_ENABLED
WEAK const PinMap PinMap_ADC[] = {
{PA_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC1_IN5
{PA_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC1_IN6
// {PA_2, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC1_IN7
// {PA_2, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC2_IN7
// {PA_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC1_IN8
{PA_3, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC2_IN8
{PA_4, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC1_IN9
// {PA_4, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC2_IN9
// {PA_5, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC1_IN10
{PA_5, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC2_IN10
{PA_6, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC1_IN11
// {PA_6, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC2_IN11
// {PA_7, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC1_IN12
{PA_7, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 12, 0)}, // ADC2_IN12
// {PB_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC1_IN15
// {PB_0, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC2_IN15
// {PB_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)}, // ADC1_IN16
// {PB_1, ADC2, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 16, 0)}, // ADC2_IN16
{NC, NP, 0}
};
#endif
//*** No DAC ***
//*** I2C ***
#ifdef HAL_I2C_MODULE_ENABLED
WEAK const PinMap PinMap_I2C_SDA[] = {
{PA_10, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
{PB_4, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C3)},
{PB_7, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_I2C_MODULE_ENABLED
WEAK const PinMap PinMap_I2C_SCL[] = {
{PA_7, I2C3, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C3)},
{PA_9, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
{PB_6, I2C1, STM_PIN_DATA(STM_MODE_AF_OD, GPIO_NOPULL, GPIO_AF4_I2C1)},
{NC, NP, 0}
};
#endif
//*** PWM ***
#ifdef HAL_TIM_MODULE_ENABLED
WEAK const PinMap PinMap_PWM[] = {
{PA_0, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1
{PA_1, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 2, 0)}, // TIM2_CH2
// {PA_1, TIM15, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_TIM15, 1, 1)}, // TIM15_CH1N
// {PA_2, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 3, 0)}, // TIM2_CH3
{PA_2, TIM15, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_TIM15, 1, 0)}, // TIM15_CH1
{PA_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 4, 0)}, // TIM2_CH4
// {PA_3, TIM15, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_TIM15, 2, 0)}, // TIM15_CH2
{PA_5, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1
{PA_6, TIM16, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_TIM16, 1, 0)}, // TIM16_CH1
{PA_7, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 1)}, // TIM1_CH1N
{PA_8, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 1, 0)}, // TIM1_CH1
{PA_9, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 0)}, // TIM1_CH2
{PA_10, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 0)}, // TIM1_CH3
{PA_11, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 4, 0)}, // TIM1_CH4
{PA_15, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 1, 0)}, // TIM2_CH1
{PB_0, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 2, 1)}, // TIM1_CH2N
{PB_1, TIM1, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM1, 3, 1)}, // TIM1_CH3N
{PB_3, TIM2, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF1_TIM2, 2, 0)}, // TIM2_CH2
{PB_6, TIM16, STM_PIN_DATA_EXT(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF14_TIM16, 1, 1)}, // TIM16_CH1N
{NC, NP, 0}
};
#endif
//*** SERIAL ***
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_TX[] = {
// {PA_2, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_LPUART1)},
{PA_2, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
{PA_9, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{PB_6, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_RX[] = {
// {PA_3, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_LPUART1)},
{PA_3, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
{PA_10, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{PA_15, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_USART2)},
{PB_7, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_RTS[] = {
{PA_1, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
{PA_12, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
// {PB_1, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_LPUART1)},
{PB_3, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_UART_MODULE_ENABLED
WEAK const PinMap PinMap_UART_CTS[] = {
{PA_0, USART2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART2)},
// {PA_6, LPUART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF8_LPUART1)},
{PA_11, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{PB_4, USART1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF7_USART1)},
{NC, NP, 0}
};
#endif
//*** SPI ***
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_MOSI[] = {
{PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_MISO[] = {
{PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_SCLK[] = {
{PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{NC, NP, 0}
};
#endif
#ifdef HAL_SPI_MODULE_ENABLED
WEAK const PinMap PinMap_SPI_SSEL[] = {
{PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{PB_0, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)},
{NC, NP, 0}
};
#endif
//*** No CAN ***
//*** No ETHERNET ***
//*** QUADSPI ***
#ifdef HAL_QSPI_MODULE_ENABLED
WEAK const PinMap PinMap_QUADSPI[] = {
{PA_2, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_NCS
{PA_3, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_CLK
{PA_6, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO3
{PA_7, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO2
{PB_0, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO1
{PB_1, QUADSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_QUADSPI)}, // QUADSPI_BK1_IO0
{NC, NP, 0}
};
#endif
//*** USB ***
#ifdef HAL_PCD_MODULE_ENABLED
WEAK const PinMap PinMap_USB[] = {
{PA_11, USB, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_USB_FS)}, // USB_DM
{PA_12, USB, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, GPIO_AF10_USB_FS)}, // USB_DP
{PA_13, USB, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF10_USB_FS)}, // USB_NOE
{NC, NP, 0}
};
#endif
//*** No USB_OTG_FS ***
//*** No USB_OTG_HS ***

View File

@@ -0,0 +1,31 @@
/* SYS_WKUP */
#ifdef PWR_WAKEUP_PIN1
SYS_WKUP1 = PA_0,
#endif
#ifdef PWR_WAKEUP_PIN2
SYS_WKUP2 = PC_13, /* manually updated */
#endif
#ifdef PWR_WAKEUP_PIN3
SYS_WKUP3 = NC,
#endif
#ifdef PWR_WAKEUP_PIN4
SYS_WKUP4 = PA_2, /* manually updated */
#endif
#ifdef PWR_WAKEUP_PIN5
SYS_WKUP5 = PC_5, /* manually updated */
#endif
#ifdef PWR_WAKEUP_PIN6
SYS_WKUP6 = NC,
#endif
#ifdef PWR_WAKEUP_PIN7
SYS_WKUP7 = NC,
#endif
#ifdef PWR_WAKEUP_PIN8
SYS_WKUP8 = NC,
#endif
/* USB */
#ifdef USBCON
USB_DM = PA_11,
USB_DP = PA_12,
USB_NOE = PA_13,
#endif

View File

@@ -0,0 +1,188 @@
/*
*****************************************************************************
**
** File : LinkerScript.ld
**
** Abstract : Linker script for STM32L031K6Tx Device with
** 32KByte FLASH, 8KByte RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
*****************************************************************************
** @attention
**
** <h2><center>&copy; COPYRIGHT(c) 2014 Ac6</center></h2>
**
** Redistribution and use in source and binary forms, with or without modification,
** are permitted provided that the following conditions are met:
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
** 3. Neither the name of Ac6 nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x200009C40; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 40K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}

View File

@@ -0,0 +1,125 @@
/*
*******************************************************************************
* COPYRIGHT(c) 2018 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************
*/
#include "pins_arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
// Pin number
const PinName digitalPin[] = {
PA_10, //D0
PA_9, //D1
PA_12, //D2
PB_0, //D3
PB_7, //D4
PB_6, //D5
PB_1, //D6
PC_14, //D7 - By default, SB6 open PF0/PC14 not connected to D7
PC_15, //D8 - By default, SB8 open PF1/PC15 not connected to D8
PA_8, //D9
PA_11, //D10
PB_5, //D11
PB_4, //D12
PB_3, //D13 - LED
PA_0, //D14/A0
PA_1, //D15/A1
PA_3, //D16/A2
PA_4, //D17/A3
PA_5, //D18/A4
PA_6, //D19/A5
PA_7, //D20/A6
PA_2, //D21/A7 - STLink Tx
PA_15 //D22 - STLink Rx
};
#ifdef __cplusplus
}
#endif
// ----------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief System Clock Configuration
* @param None
* @retval None
*/
WEAK void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {};
RCC_OscInitTypeDef RCC_OscInitStruct = {};
/* Configure LSE Drive Capability */
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
/* Configure the main internal regulator output voltage */
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) {
Error_Handler();
}
/* MSI is enabled after System reset, activate PLL with MSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 40;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
Error_Handler();
}
/* Enable MSI Auto calibration */
HAL_RCCEx_EnableMSIPLLMode();
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,119 @@
/*
*******************************************************************************
* Copyright (c) 2018, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#ifndef _VARIANT_ARDUINO_STM32_
#define _VARIANT_ARDUINO_STM32_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/*----------------------------------------------------------------------------
* Pins
*----------------------------------------------------------------------------*/
#define PA10 0
#define PA9 1
#define PA12 2
#define PB0 3
#define PB7 4
#define PB6 5
#define PB1 6
#define PC14 7 // By default, SB6 open PF0/PC14 not connected to D7
#define PC15 8 // By default, SB8 open PF1/PC15 not connected to D8
#define PA8 9
#define PA11 10
#define PB5 11
#define PB4 12
#define PB3 13 // LED
#define PA0 14 // A0
#define PA1 15 // A1
#define PA3 16 // A2
#define PA4 17 // A3
#define PA5 18 // A4
#define PA6 19 // A5
#define PA7 20 // A6
#define PA2 21 // A7 - STLink Tx
#define PA15 22 // STLink Rx
// This must be a literal
#define NUM_DIGITAL_PINS 23
// This must be a literal with a value less than or equal to to MAX_ANALOG_INPUTS
#define NUM_ANALOG_INPUTS 7
#define NUM_ANALOG_FIRST 14
// On-board LED pin number
#define LED_BUILTIN 13
#define LED_GREEN LED_BUILTIN
// I2C Definitions
#define PIN_WIRE_SDA 4
#define PIN_WIRE_SCL 5
// Timer Definitions
// Use TIM6 when possible as servo and tone don't need GPIO output pin
#define TIMER_TONE TIM6
#define TIMER_SERVO TIM2
// UART Definitions
#define SERIAL_UART_INSTANCE 2 //Connected to ST-Link
// Default pin used for 'Serial' instance (ex: ST-Link)
// Mandatory for Firmata
#define PIN_SERIAL_RX PA15
#define PIN_SERIAL_TX PA2
#ifdef __cplusplus
} // extern "C"
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
// pins are NOT connected to anything by default.
#define SERIAL_PORT_MONITOR Serial
#define SERIAL_PORT_HARDWARE Serial
#endif
#endif /* _VARIANT_ARDUINO_STM32_ */