add end-switches management

This commit is contained in:
Edward Emelianov 2024-01-08 22:46:25 +03:00
parent 24a270a932
commit 01f6187229
15 changed files with 220 additions and 8 deletions

Binary file not shown.

View File

@ -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) */

View File

@ -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>

View File

@ -6,6 +6,8 @@ commonfunctions.c
commonfunctions.h
flash.c
flash.h
gpio.c
gpio.h
hardware.c
hardware.h
main.c

View File

@ -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},
};

View File

@ -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 \

View File

@ -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
View 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
View 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);

View File

@ -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);

View File

@ -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();

View File

@ -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();
}
}
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -1,2 +1,2 @@
#define BUILD_NUMBER "56"
#define BUILD_NUMBER "68"
#define BUILD_DATE "2024-01-08"