mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +03:00
add end-switches management
This commit is contained in:
parent
24a270a932
commit
01f6187229
Binary file not shown.
@ -32,6 +32,15 @@
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
// CAN bus oscillator frequency: 36MHz
|
||||
#define CAN_F_OSC (36000000UL)
|
||||
// timing values TBS1 and TBS2 (in BTR [TBS1-1] and [TBS2-1])
|
||||
// use 3 and 2 to get 6MHz
|
||||
#define CAN_TBS1 (3)
|
||||
#define CAN_TBS2 (2)
|
||||
// bitrate oscillator frequency
|
||||
#define CAN_BIT_OSC (CAN_F_OSC / (1+CAN_TBS1+CAN_TBS2))
|
||||
|
||||
uint8_t cansniffer = 0; // 0 - receive only 0 and myID, 1 - receive all
|
||||
|
||||
// circular buffer for received messages
|
||||
@ -143,7 +152,7 @@ void CAN_setup(uint32_t speed){
|
||||
/* (1) Enter CAN init mode to write the configuration */
|
||||
/* (2) Wait the init mode entering */
|
||||
/* (3) Exit sleep mode */
|
||||
/* (4) Normal mode, set timing to 100kb/s: TBS1 = 4, TBS2 = 3, prescaler = 60 */
|
||||
/* (4) Normal mode, set timing : TBS1 = 4, TBS2 = 3 */
|
||||
/* (5) Leave init mode */
|
||||
/* (6) Wait the init mode leaving */
|
||||
/* (7) Enter filter init mode, (16-bit + mask, bank 0 for FIFO 0) */
|
||||
@ -158,8 +167,8 @@ void CAN_setup(uint32_t speed){
|
||||
if(tmout==0){ DBG("timeout!\n");}
|
||||
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
||||
CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */
|
||||
CAN->BTR = 2 << 20 | 3 << 16 | (((uint32_t)4500000UL)/speed - 1); //| CAN_BTR_SILM | CAN_BTR_LBKM; /* (4) */
|
||||
oldspeed = ((uint32_t)4500000UL)/(uint32_t)((CAN->BTR & CAN_BTR_BRP) + 1);
|
||||
CAN->BTR = (CAN_TBS2-1) << 20 | (CAN_TBS1-1) << 16 | (CAN_BIT_OSC/speed - 1); //| CAN_BTR_SILM | CAN_BTR_LBKM; /* (4) */
|
||||
oldspeed = CAN_BIT_OSC/(uint32_t)((CAN->BTR & CAN_BTR_BRP) + 1);
|
||||
CAN->MCR &= ~CAN_MCR_INRQ; /* (5) */
|
||||
tmout = 10000;
|
||||
while(CAN->MSR & CAN_MSR_INAK) /* (6) */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 12.0.1, 2024-01-07T00:44:38. -->
|
||||
<!-- Written by QtCreator 12.0.1, 2024-01-08T22:45:09. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
@ -6,6 +6,8 @@ commonfunctions.c
|
||||
commonfunctions.h
|
||||
flash.c
|
||||
flash.h
|
||||
gpio.c
|
||||
gpio.h
|
||||
hardware.c
|
||||
hardware.h
|
||||
main.c
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "can.h"
|
||||
#include "commonfunctions.h"
|
||||
#include "flash.h"
|
||||
#include "gpio.h"
|
||||
#include "proto.h"
|
||||
#include "usb.h"
|
||||
|
||||
@ -102,7 +103,39 @@ static errcodes erasestor(CAN_message _U_ *msg){
|
||||
if(0 == erase_storage(-1)) return ERR_OK;
|
||||
return ERR_CANTRUN;
|
||||
}
|
||||
|
||||
// relay management
|
||||
static errcodes relay(CAN_message *msg){
|
||||
if(ISSETTER(msg->data)){
|
||||
if(msg->data[4] == 1) RELAY_ON();
|
||||
else RELAY_OFF();
|
||||
}else FIXDL(msg);
|
||||
*(uint32_t*)&msg->data[4] = RELAY_GET();
|
||||
return ERR_OK;
|
||||
}
|
||||
// blocking ESW get status
|
||||
static errcodes eswblk(CAN_message *msg){
|
||||
uint8_t no = msg->data[2] & ~SETTER_FLAG;
|
||||
if(no > 1) return ERR_BADPAR;
|
||||
FIXDL(msg);
|
||||
*(uint32_t*)&msg->data[4] = getSwitches(no);
|
||||
return ERR_OK;
|
||||
}
|
||||
// bounce-free ESW get status
|
||||
static errcodes esw(CAN_message *msg){
|
||||
uint8_t no = msg->data[2] & ~SETTER_FLAG;
|
||||
if(no > 1) return ERR_BADPAR;
|
||||
FIXDL(msg);
|
||||
*(uint32_t*)&msg->data[4] = getESW(no);
|
||||
return ERR_OK;
|
||||
}
|
||||
// bounce constant, ms
|
||||
static errcodes bounce(CAN_message *msg){
|
||||
if(ISSETTER(msg->data)){
|
||||
the_conf.bounce_ms = *(uint32_t*)&msg->data[4];
|
||||
}else FIXDL(msg);
|
||||
*(uint32_t*)&msg->data[4] = the_conf.bounce_ms;
|
||||
return ERR_OK;
|
||||
}
|
||||
/************ END of all common functions list (for `funclist`) ************/
|
||||
|
||||
|
||||
@ -126,6 +159,10 @@ static const commonfunction funclist[CMD_AMOUNT] = {
|
||||
[CMD_ADCMUL] = {adcmul, 0, 0, 3}, // at least parno
|
||||
[CMD_SAVECONF] = {saveconf, 0, 0, 0},
|
||||
[CMD_ERASESTOR] = {erasestor, 0, 0, 0},
|
||||
[CMD_RELAY] = {relay, 0, 1, 0},
|
||||
[CMD_GETESW_BLK] = {eswblk, 0, 0, 3},
|
||||
[CMD_GETESW] = {esw, 0, 0, 3},
|
||||
[CMD_BOUNCE] = {bounce, 0, 300, 0},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here
|
||||
.userconf_sz = sizeof(user_conf) \
|
||||
,.CANspeed = 100000 \
|
||||
,.CANID = 0xaa \
|
||||
,.bounce = 50 \
|
||||
,.adcmul[0] = 10.930f \
|
||||
,.adcmul[1] = 2.028f \
|
||||
,.adcmul[2] = 1.f \
|
||||
|
||||
@ -35,6 +35,7 @@ typedef struct __attribute__((packed, aligned(4))){
|
||||
uint16_t userconf_sz; // "magick number"
|
||||
uint16_t CANID; // identifier
|
||||
uint32_t CANspeed; // default CAN speed
|
||||
uint32_t bounce_ms; // a
|
||||
float adcmul[ADC_TSENS]; // ADC voltage multipliers
|
||||
} user_conf;
|
||||
|
||||
|
||||
102
F3:F303/CANbus4BTA/gpio.c
Normal file
102
F3:F303/CANbus4BTA/gpio.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of the canbus4bta project.
|
||||
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include "gpio.h"
|
||||
#include "hardware.h"
|
||||
|
||||
// GPIO IN management by two 74HC4051
|
||||
|
||||
static uint8_t eswitches[2] = {0};
|
||||
static uint8_t stage = 0;
|
||||
static uint32_t lastT[8][2] = {0}; // last time of ESW changed
|
||||
|
||||
uint8_t getESW(uint8_t nch){
|
||||
return eswitches[nch];
|
||||
}
|
||||
|
||||
// update `eswitches`, anti-bounce
|
||||
TRUE_INLINE void updesw(uint8_t nch, uint8_t newval){
|
||||
uint8_t mask = eswitches[nch] ^ newval, newmask = 0;
|
||||
if(mask == 0) return;
|
||||
for(uint8_t bit = 0; bit < 8; ++bit){ // check all bits of mask
|
||||
newmask >>= 1;
|
||||
if((mask & 1) && Tms - lastT[bit][nch] >= the_conf.bounce_ms){ // OK, change this value
|
||||
newmask |= 0x80;
|
||||
lastT[bit][nch] = Tms;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
if(newmask == 0) return;
|
||||
// now change only allowable bits
|
||||
eswitches[nch] = (eswitches[nch] & ~newmask) | (newval & newmask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ESW_process - process multiplexer 1
|
||||
*/
|
||||
void ESW_process(){
|
||||
static uint8_t curch = 0;
|
||||
static int curaddr = 7;
|
||||
static uint8_t ESW = 0;
|
||||
switch(stage){
|
||||
case 0: // stage 0: change address and turn on multiplexer
|
||||
stage = 1;
|
||||
MULADDR_set(curaddr);
|
||||
MUL_ON(curch);
|
||||
break;
|
||||
case 1: // stage 1: read data and turn off mul
|
||||
default:
|
||||
stage = 0;
|
||||
ESW <<= 1;
|
||||
ESW |= ESW_GET();
|
||||
MUL_OFF(curch);
|
||||
if(--curaddr < 0){
|
||||
updesw(curch, ESW);
|
||||
curch = !curch;
|
||||
curaddr = 7;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void NeverDoThisFuckingShit(){
|
||||
uint32_t ctr = 3;
|
||||
while(ctr--) nop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getSwitches - blocking read of all switches of given channel
|
||||
* @param chno - number of multiplexer: 0 (board switches) or 1 (external ESW)
|
||||
*/
|
||||
uint8_t getSwitches(uint8_t chno){
|
||||
if(chno > 1) return 0;
|
||||
MUL_OFF(0); MUL_OFF(1);
|
||||
uint8_t state = 0;
|
||||
for(int i = 7; i > -1; --i){
|
||||
MULADDR_set(i);
|
||||
MUL_ON(chno);
|
||||
state <<= 1;
|
||||
NeverDoThisFuckingShit();
|
||||
state |= ESW_GET();
|
||||
MUL_OFF(chno);
|
||||
NeverDoThisFuckingShit();
|
||||
}
|
||||
stage = 0; // prevent interference with `ESW_process()`
|
||||
return state;
|
||||
}
|
||||
24
F3:F303/CANbus4BTA/gpio.h
Normal file
24
F3:F303/CANbus4BTA/gpio.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of the canbus4bta project.
|
||||
* Copyright 2024 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stm32f3.h>
|
||||
|
||||
uint8_t getESW(uint8_t nch);
|
||||
void ESW_process();
|
||||
uint8_t getSwitches(uint8_t chno);
|
||||
@ -47,6 +47,7 @@ TRUE_INLINE void iwdg_setup(){
|
||||
#endif
|
||||
|
||||
static inline void gpio_setup(){
|
||||
RELAY_OFF(); MUL_OFF(0); MUL_OFF(1);
|
||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN;
|
||||
// PWM - AF1 @PA7; USB - alternate function 14 @ pins PA11/PA12; USART1 = AF7 @PA9/10; SWD - AF0 @PA13/14
|
||||
GPIOA->AFR[0] = AFRf(1, 7);
|
||||
@ -57,7 +58,8 @@ static inline void gpio_setup(){
|
||||
GPIOA->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_I(4) | MODER_O(5) |
|
||||
MODER_O(6) | MODER_AF(7) | MODER_I(8) | MODER_AF(9) | MODER_AF(10) | MODER_AF(11) |
|
||||
MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_I(15);
|
||||
GPIOA->OSPEEDR = OSPEED_MED(7) | OSPEED_MED(9) | OSPEED_MED(10) | OSPEED_HI(11) | OSPEED_HI(12) | OSPEED_HI(13) | OSPEED_HI(14);
|
||||
GPIOA->OSPEEDR = OSPEED_HI(4) | OSPEED_MED(7) | OSPEED_MED(9) | OSPEED_MED(10) | OSPEED_HI(11) |
|
||||
OSPEED_HI(12) | OSPEED_HI(13) | OSPEED_HI(14);
|
||||
// SPI for SSI: AF5 @PB3, PB4; I2C1: AF4 @PB6, PB7; CAN: AF9 @PB8, PB9; SPI2: AF5 @PB12..PB15
|
||||
GPIOB->AFR[0] = AFRf(5, 3) | AFRf(5, 4) | AFRf(4, 6) | AFRf(4, 7);
|
||||
GPIOB->AFR[1] = AFRf(9, 8) | AFRf(9, 9) | AFRf(5, 12) | AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15);
|
||||
|
||||
@ -20,11 +20,25 @@
|
||||
|
||||
#include <stm32f3.h>
|
||||
|
||||
// USB pullup
|
||||
#define USBPU_port GPIOC
|
||||
#define USBPU_pin (1<<15)
|
||||
#define USBPU_ON() pin_set(USBPU_port, USBPU_pin)
|
||||
#define USBPU_OFF() pin_clear(USBPU_port, USBPU_pin)
|
||||
|
||||
// relay
|
||||
#define RELAY_port GPIOC
|
||||
#define RELAY_pin (1<<14)
|
||||
#define RELAY_ON() pin_set(RELAY_port, RELAY_pin)
|
||||
#define RELAY_OFF() pin_clear(RELAY_port, RELAY_pin)
|
||||
#define RELAY_GET() pin_read(RELAY_port, RELAY_pin)
|
||||
|
||||
// GPIO end-switches multiplexer (addr - PB0..2, ~DEN0 - PA5, ~DEN1 - PA6) and input (PA4)
|
||||
#define ESW_GET() (GPIOA->IDR & (1<<4) ? 0 : 1)
|
||||
#define MULADDR_set(x) do{GPIOB->BSRR = (x&7) | (((~x)&7) << 16);}while(0)
|
||||
#define MUL_ON(x) pin_clear(GPIOA, 1<<(5+x))
|
||||
#define MUL_OFF(x) pin_set(GPIOA, 1<<(5+x))
|
||||
|
||||
extern volatile uint32_t Tms;
|
||||
|
||||
void hw_setup();
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
#include "can.h"
|
||||
#include "flash.h"
|
||||
#include "gpio.h"
|
||||
#include "hardware.h"
|
||||
#include "textfunctions.h"
|
||||
#include "usart.h"
|
||||
@ -57,6 +58,7 @@ int main(void){
|
||||
}
|
||||
flashstorage_init();
|
||||
hw_setup();
|
||||
// getSwitches() and set module role & CAN ID
|
||||
CAN_setup(the_conf.CANspeed);
|
||||
USBPU_ON();
|
||||
while(1){
|
||||
@ -86,5 +88,15 @@ int main(void){
|
||||
const char *ans = run_text_cmd(inbuff);
|
||||
if(ans) USB_sendstr(ans);
|
||||
}
|
||||
ESW_process();
|
||||
static uint8_t oldswitches[2] = {0};
|
||||
for(int i = 0; i < 2; ++i){
|
||||
uint8_t new = getESW(i);
|
||||
if(oldswitches[i] != new){
|
||||
oldswitches[i] = new;
|
||||
USB_sendstr("ESW changed @"); printu(Tms);
|
||||
USB_sendstr(" to "); printuhex(new); newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,6 +60,10 @@ typedef enum{
|
||||
CMD_ADCMUL, // 7 - get/set ADC multipliers 0..4
|
||||
CMD_SAVECONF, // 8 - save configuration
|
||||
CMD_ERASESTOR, // 9 - erase all flash storage
|
||||
CMD_RELAY, // 10 - switch relay ON/OFF
|
||||
CMD_GETESW_BLK, // 11 - blocking read of ESW
|
||||
CMD_GETESW, // 12 - current ESW state, bounce-free
|
||||
CMD_BOUNCE, // 13 - get/set bounce constant (ms)
|
||||
CMD_AMOUNT // amount of CAN commands
|
||||
} can_cmd;
|
||||
|
||||
|
||||
@ -53,12 +53,16 @@ static const funcdescr funclist[] = {
|
||||
{"adcmul", CMD_ADCMUL, "get/set ADC multipliers 0..3 (*1000)"},
|
||||
{"adcraw", CMD_ADCRAW, "get raw ADC values of channel 0..4"},
|
||||
{"adcv", CMD_ADCV, "get ADC voltage of channel 0..3 (*100V)"},
|
||||
{"bounce", CMD_BOUNCE, "get/set bounce constant (ms)"},
|
||||
{"canid", CMD_CANID, "get/set CAN ID"},
|
||||
{"cansnif", -TCMD_CANSNIF, "get/change sniffer state (0 - normal, 1 - sniffer)"},
|
||||
{"canspeed", CMD_CANSPEED, "get/set CAN speed (bps)"},
|
||||
{"dumpconf", -TCMD_DUMPCONF, "dump current configuration"},
|
||||
{"esw", CMD_GETESW, "anti-bounce read ESW of channel 0 or 1"},
|
||||
{"eswblk", CMD_GETESW_BLK, "blocking read ESW of channel 0 or 1"},
|
||||
{"eraseflash", CMD_ERASESTOR, "erase all flash storage"},
|
||||
{"mcutemp", CMD_MCUTEMP, "get MCU temperature (*10degrC)"},
|
||||
{"relay", CMD_RELAY, "get/set relay state (0 - off, 1 - on)"},
|
||||
{"reset", CMD_RESET, "reset MCU"},
|
||||
{"s", -TCMD_CANSEND, "send CAN message: ID 0..8 data bytes"},
|
||||
{"saveconf", CMD_SAVECONF, "save configuration"},
|
||||
@ -144,7 +148,7 @@ static errcodes cansend(const char *txt){
|
||||
uint32_t Tstart = Tms;
|
||||
while(Tms - Tstart < SEND_TIMEOUT_MS){
|
||||
if(CAN_OK == CAN_send(&canmsg)){
|
||||
USB_sendstr("OK\n");
|
||||
//USB_sendstr("OK\n"); - don't send OK, as after sending might be an error
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
#define BUILD_NUMBER "56"
|
||||
#define BUILD_NUMBER "68"
|
||||
#define BUILD_DATE "2024-01-08"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user