change protocol & firmware (to work @250kbaud and in sniffer mode)

This commit is contained in:
2022-01-30 16:23:36 +03:00
parent 2e4cc8c1fe
commit 2213c84773
70 changed files with 12330 additions and 4623 deletions

View File

@@ -11,7 +11,7 @@ DEFS := -DUSARTNUM=1 -DI2CPINS=67
#DEFS += -DEBUG
# change this linking script depending on particular MCU model,
# for example, if you have STM32F103VBT6, you should write:
LDSCRIPT = ld/stm32f042k.ld
LDSCRIPT = stm32f042x6.ld
INDEPENDENT_HEADERS=
@@ -107,9 +107,6 @@ $(OBJDIR)/%.o: %.c
@echo " CC $<"
$(CC) $(CFLAGS) -MD $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
#$(OBJDIR)/%.d: %.c $(OBJDIR)
# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
$(BIN): $(ELF)
@echo " OBJCOPY $(BIN)"
$(OBJCOPY) -Obinary $(ELF) $(BIN)
@@ -125,6 +122,7 @@ $(LIST): $(ELF)
$(ELF): $(OBJDIR) $(OBJS)
@echo " LD $(ELF)"
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
@size $(ELF)
clean:
@echo " CLEAN"

View File

@@ -3,92 +3,124 @@
Make regular scan of 8 sensors' pairs.
USART speed 115200. Code for ../../kicad/stm32
### Serial interface commands (ends with '\n'), small letter for only local processing:
## Serial interface commands (ends with '\n'), small letter for only local processing:
- **0...7** send message to Nth controller, not broadcast (after number should be CAN command)
- **a** get raw ADC values
- **B** send dummy CAN messages to broadcast address
- **c** show coefficients for all thermosensors
- **D** send dummy CAN messages to master (0) address
- **a** get raw ADC values
- **B** send dummy CAN messages to broadcast address
- **b** get/set CAN bus baudrate
- **c** show coefficients for all thermosensors
- **D** send dummy CAN messages to master (0) address
- **d** get current CAN address of device
- **Ee** end temperature scan
- **Ff** turn sensors off
- **g** get last CAN address
- **g** group (sniffer) CAN mode (print to USB terminal all incoming CAN messages with alien IDs)
- **Hh** switch I2C to high speed (100kHz)
- **i** reinit CAN with new address (if changed)
- **Jj** get MCU temperature
- **Kk** get values of U and I
- **Ll** switch I2C to low speed (default, 10kHz)
- **Mm** change master id to 0 (**m**) / broadcast (**M**)
- **Oo** turn onboard diagnostic LEDs **O**n or **o**ff (both commands are local!)
- **P** ping everyone over CAN
- **P** ping everyone over CAN
- **Rr** reinit I2C
- **Ss** start temperature scan
- **s** send CAN message (format: ID data[0..8], dec, 0x - hex, 0b - binary)
- **Tt** start single temperature measurement
- **u** check CAN bus status for errors
- **u** unique ID (default) CAN mode
- **Vv** very low speed
- **Z** get sensors state over CAN
- **Xx** go into temperature scan mode
- **Yy** get sensors state over CAN (data format: 3 - state, 4,5 - presense mask [0,1], 6 - npresent, 7 - ntempmeasured
- **z** check CAN status for errors
The command **M** allows to temporaly change master ID of all
controllers to broadcast ID. So all data they sent will be
accessed @ any controller.
### PINOUT
- I2C: PB6 (SCL) & PB7 (SDA)
- USART1: PA9 (Tx) & PA10 (Rx)
- CAN bus: PB8 (Rx), PB9 (Tx)
- USB bus: PA11 (DM), PA12 (DP)
- I2C multiplexer: PB0..PB2 (0..2 address bits), PB12 (~EN)
- sensors' power: PB3 (in, overcurrent), PA8 (out, enable power)
- signal LEDs: PB10 (LED0), PB11 (LED1)
- ADC inputs: PA0 (V12/4.93), PA1 (V5/2), PA3 (I12 - 1V/A), PA6 (V3.3/2)
- controller CAN address: PA13..PA15 (0..2 bits), PB15 (3rd bit); 0 - master, other address - slave
## PINOUT
- **I2C**: PB6 (SCL) & PB7 (SDA)
- **USART1**: PA9 (Tx) & PA10 (Rx)
- **CAN bus**: PB8 (Rx), PB9 (Tx)
- **USB bus**: PA11 (DM), PA12 (DP)
- **I2C multiplexer**: PB0..PB2 (0..2 address bits), PB12 (~EN)
- **sensors' power**: PB3 (in, overcurrent), PA8 (out, enable power)
- **signal LEDs**: PB10 (LED0), PB11 (LED1)
- **ADC inputs**: PA0 (V12/4.93), PA1 (V5/2), PA3 (I12 - 1V/A), PA6 (V3.3/2)
- **controller CAN address**: PA13..PA15 (0..2 bits), PB15 (3rd bit); 0 - master, other address - slave
### LEDS
## LEDS
- LED0 (nearest to sensors' connectors) - heartbeat
- LED1 (above LED0) - CAN bus OK
### CAN protocol
Variable data length: from 1 to 7 bytes.
## CAN protocol
Variable data length: from 1 to 8 bytes.
First (number zero) byte of every sequence is command mark (0xA5) or data mark (0x5A).
Commands:
- CMD_PING request for PONG cmd
- CMD_START_MEASUREMENT start single temperature measurement
- CMD_SENSORS_STATE get sensors state
- CMD_START_SCAN run scan mode
- CMD_STOP_SCAN stop scan mode
- CMD_SENSORS_OFF turn off power of sensors
- CMD_LOWEST_SPEED lowest I2C speed
- CMD_LOW_SPEED low I2C speed (10kHz)
- CMD_HIGH_SPEED high I2C speed (100kHz)
- CMD_REINIT_I2C reinit I2C with current speed
## Commands
### Common commands
- `CMD_PING` (0) request for PONG cmd
- `CMD_START_MEASUREMENT` (1) start single temperature measurement
- `CMD_SENSORS_STATE` (2) get sensors state
- `CMD_START_SCAN` (3) run scan mode
- `CMD_STOP_SCAN` (4) stop scan mode
- `CMD_SENSORS_OFF` (5) turn off power of sensors
- `CMD_LOWEST_SPEED` (6) lowest I2C speed
- `CMD_LOW_SPEED` (7) low I2C speed (10kHz)
- `CMD_HIGH_SPEED` (8) high I2C speed (100kHz)
- `CMD_REINIT_I2C` (9) reinit I2C with current speed
- `CMD_CHANGE_MASTER_B` (10) change master id to broadcast
- `CMD_CHANGE_MASTER` (11) change master id to 0
- `CMD_GETMCUTEMP` (12) MCU temperature value
- `CMD_GETUIVAL` (13) request to get values of V12, V5, I12 and V3.3
- `CMD_GETUIVAL0` (14) answer with values of V12 and V5
- `CMD_GETUIVAL1` (15) answer with values of I12 and V3.3
Dummy commands for test purposes:
- CMD_DUMMY0 = 0xDA,
- CMD_DUMMY1 = 0xAD
### Dummy commands for test purposes
- `CMD_DUMMY0` = 0xDA,
- `CMD_DUMMY1` = 0xAD
Data format:
### Commands data format
- byte 1 - Controller number
- byte 2 - Command received
- bytes 3..7 - data
Thermal data format:
### Thermal data format
- byte 3 - Sensor number (10*N + M, where N is multiplexer number, M - number of sensor in pair, i.e. 0,1,10,11,20,21...70,71)
- byte 4 - thermal data H
- byte 5 - thermal data L
MCU temperature data format:
### Sensors state data format
- byte 3 - Sstate value:
- - `[SENS_INITING]` = "init"
- - `[SENS_RESETING]` = "reset"
- - `[SENS_GET_COEFFS]` = "getcoeff"
- - `[SENS_SLEEPING]` = "sleep"
- - `[SENS_START_MSRMNT]` = "startmeasure"
- - `[SENS_WAITING]` = "waitresults"
- - `[SENS_GATHERING]` = "collectdata"
- - `[SENS_OFF]` = "off"
- - `[SENS_OVERCURNT]` = "overcurrent"
- - `[SENS_OVERCURNT_OFF]` = "offbyovercurrent"
- byte 4 - `sens_present[0]` value
- byte 5 - `sens_present[1]` value
- byte 6 - `Nsens_present` value
- byte 7 - `Ntemp_measured` value
### MCU temperature data format
- byte 3 - data H
- byte 4 - data L
All temperature is in degrC/100
All temperature is in degrC/100!
### U and I data format
- byte 2 - type of data (`CMD_GETUIVAL0` - V12 and V5, `CMD_GETUIVAL1` - I12 and V3.3)
case CMD_GETUIVAL0
U and I data format:
- byte 2 - type of data (CMD_GETUIVAL0 - V12 and V5, CMD_GETUIVAL1 - I12 and V3.3)
case CMD_GETUIVAL0:
- bytes 3,4 - V12 H/L
- bytes 5,6 - V5 H/L
case CMD_GETUIVAL1:
case CMD_GETUIVAL1
- bytes 3,4 - I12 H/L
- bytes 5,6 - V33 H/L
Voltage is in V/100, Current is in mA

View File

@@ -34,8 +34,11 @@ extern volatile uint32_t Tms;
static CAN_message messages[CAN_INMESSAGE_SIZE];
static uint8_t first_free_idx = 0; // index of first empty cell
static int8_t first_nonfree_idx = -1; // index of first data cell
int8_t cansniffer = 0; // ==1 to listen all CAN ID's
static uint16_t CANID = 0xFFFF;
uint16_t curcanspeed = CAN_SPEED_DEFAULT; // speed of last init
uint16_t CANID = 0xFFFF;
uint8_t Controller_address = 0;
static CAN_status can_status = CAN_STOP;
@@ -78,20 +81,15 @@ void readCANID(){
CANID = (CAN_ID_PREFIX & CAN_ID_MASK) | Controller_address;
}
uint16_t getCANID(){
return CANID;
}
void CAN_reinit(){
void CAN_setup(uint16_t speed){
if(speed == 0) speed = curcanspeed;
else if(speed < CAN_SPEED_MIN) speed = CAN_SPEED_MIN;
else if(speed > CAN_SPEED_MAX) speed = CAN_SPEED_MAX;
curcanspeed = speed;
readCANID();
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
CAN_setup();
}
void CAN_setup(){
if(CANID == 0xFFFF) readCANID();
// Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx
/* (1) Select AF mode (10) on PB8 and PB9 */
/* (2) AF4 for CAN signals */
@@ -105,34 +103,40 @@ void CAN_setup(){
/* (1) Enter CAN init mode to write the configuration */
/* (2) Wait the init mode entering */
/* (3) Exit sleep mode */
/* (4) Loopback mode, set timing to 100kb/s: BS1 = 4, BS2 = 3, prescaler = 60 */
/* (4) Normal mode, set timing to 100kb/s: BS1 = 4, BS2 = 3, prescaler = 6000/speed */
/* (5) Leave init mode */
/* (6) Wait the init mode leaving */
/* (7) Enter filter init mode, (16-bit + mask, filter 0 for FIFO 0) */
/* (8) Acivate filter 0 */
/* (9) Identifier list mode */
/* (8) Acivate filter 0 (1,2) */
/* (9) Identifier mode for bank#0, mask mode for #1 and #2 */
/* (10) Set the Id list */
/* (11) Set the mask list */
/* (12) Leave filter init */
/* (13) Set error interrupts enable */
CAN->MCR |= CAN_MCR_INRQ; /* (1) */
while((CAN->MSR & CAN_MSR_INAK)!=CAN_MSR_INAK) /* (2) */
{
/* add time out here for a robust application */
uint32_t tmout = 16000000;
while((CAN->MSR & CAN_MSR_INAK)!=CAN_MSR_INAK){ /* (2) */
if(--tmout == 0) break;
}
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
CAN->MCR |= CAN_MCR_ABOM;
CAN->BTR |= 2 << 20 | 3 << 16 | 59 << 0; /* (4) */
CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed - 1); /* (4) */
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) /* (6) */
{
/* add time out here for a robust application */
tmout = 16000000;
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK){ /* (6) */
if(--tmout == 0) break;
}
CAN->FMR = CAN_FMR_FINIT; /* (7) */
CAN->FA1R = CAN_FA1R_FACT0; /* (8) */
CAN->FM1R = CAN_FM1R_FBM0; /* (9) */
CAN->sFilterRegister[0].FR1 = CANID << 5 | ((BCAST_ID << 5) << 16); /* (10) */
if(cansniffer){ /* (11) */
CAN->FA1R |= CAN_FA1R_FACT1 | CAN_FA1R_FACT2; // activate 1 & 2
CAN->sFilterRegister[1].FR1 = (1<<21)|(1<<5); // all odd IDs
CAN->sFilterRegister[2].FR1 = (1<<21); // all even IDs
CAN->FFA1R = 2; // filter 1 for FIFO1, filters 0&2 - for FIFO0
}
CAN->FMR &=~ CAN_FMR_FINIT; /* (12) */
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1; /* (13) */
@@ -144,6 +148,18 @@ void CAN_setup(){
can_status = CAN_READY;
}
// add filters for ALL ID's
void CAN_listenall(){
cansniffer = 1;
CAN_setup(0);
}
// listen only packets to self & broadcast - delete filters 1&2
void CAN_listenone(){
cansniffer = 0;
CAN_setup(0);
}
void can_proc(){
// check for messages in FIFO0 & FIFO1
if(CAN->RF0R & CAN_RF0R_FMP0){
@@ -217,8 +233,13 @@ static void can_process_fifo(uint8_t fifo_num){
/* TODO: check filter match index if more than one ID can receive */
CAN_message msg;
uint8_t *dat = msg.data;
uint8_t len = box->RDTR & 0x0f;
{ // set all data to 0
uint32_t *dptr = (uint32_t*)msg.data;
dptr[0] = dptr[1] = 0;
}
uint8_t len = box->RDTR & 0x7;
msg.length = len;
msg.ID = box->RIR >> 21;
if(len){ // message can be without data
uint32_t hb = box->RDHR, lb = box->RDLR;
switch(len){

View File

@@ -37,13 +37,18 @@
// send dummy message to this ID for testing CAN bus status
#define NOONE_ID ((uint16_t)0x7FF)
extern uint16_t curcanspeed;
extern uint16_t CANID;
extern int8_t cansniffer;
typedef struct{
uint8_t data[8];
uint8_t length;
uint16_t ID; // ID of receiver
} CAN_message;
typedef enum{
CAN_NOTMASTER, // can't send command - not a mastar
CAN_NOTMASTER, // can't send command - not a master
CAN_STOP, // CAN stopped
CAN_READY, // ready to send
CAN_BUSY, // bus is busy
@@ -55,10 +60,10 @@ typedef enum{
CAN_status CAN_get_status();
void readCANID();
uint16_t getCANID();
void CAN_reinit();
void CAN_setup();
void CAN_setup(uint16_t speed);
void CAN_listenall();
void CAN_listenone();
void can_proc();
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id);

View File

@@ -86,8 +86,21 @@ void can_messages_proc(){
}
newline();
#endif
uint8_t *data = can_mesg->data, b[2];
uint8_t *data = can_mesg->data, b[6];
b[0] = data[1];
// show received message in sniffer mode
if(cansniffer){
printu(Tms);
SEND(" #");
printuhex(can_mesg->ID);
for(int ctr = 0; ctr < len; ++ctr){
SEND(" ");
printuhex(can_mesg->data[ctr]);
}
newline(); sendbuf();
}
// don't process alien messages
if(can_mesg->ID != CANID || can_mesg->ID != BCAST_ID) return;
int16_t t;
if(data[0] == COMMAND_MARK){ // process commands
if(len < 2) return;
@@ -102,8 +115,12 @@ void can_messages_proc(){
can_send_data(b, 1);
break;
case CMD_SENSORS_STATE:
b[1] = sensors_get_state();
can_send_data(b, 2);
b[1] = Sstate;
b[2] = sens_present[0];
b[3] = sens_present[1];
b[4] = Nsens_present;
b[5] = Ntemp_measured;
can_send_data(b, 6);
break;
case CMD_START_MEASUREMENT:
sensors_start();
@@ -143,22 +160,35 @@ void can_messages_proc(){
break;
}
}else if(data[0] == DATA_MARK){ // process received data
char Ns = '0' + data[1];
if(len < 3) return;
switch(data[2]){
case CMD_PING:
SEND("PONG");
bufputchar('0' + data[1]);
bufputchar(Ns);
break;
case CMD_SENSORS_STATE:
SEND("SSTATE");
bufputchar('0' + data[1]);
bufputchar(Ns);
bufputchar('=');
printu(data[3]);
SEND(sensors_get_statename(data[3]));
SEND("\nNSENS");
bufputchar(Ns);
bufputchar('=');
printu(data[6]);
SEND("\nSENSPRESENT");
bufputchar(Ns);
bufputchar('=');
printu(data[4] | (data[5]<<8));
SEND("\nNTEMP");
bufputchar(Ns);
bufputchar('=');
printu(data[7]);
break;
case CMD_START_MEASUREMENT: // temperature
if(len != 6) return;
bufputchar('T');
bufputchar('0' + data[1]);
bufputchar(Ns);
bufputchar('_');
printu(data[3]);
bufputchar('=');
@@ -171,7 +201,7 @@ void can_messages_proc(){
break;
case CMD_GETMCUTEMP:
addtobuf("TMCU");
bufputchar('0' + data[1]);
bufputchar(Ns);
bufputchar('=');
t = data[3]<<8 | data[4];
if(t < 0){

View File

@@ -32,8 +32,8 @@
// 8-bit commands sent by master
typedef enum{
CMD_PING, // request for PONG cmd
CMD_START_MEASUREMENT, // start thermal measurement
CMD_SENSORS_STATE, // reply data with sensors state
CMD_START_MEASUREMENT, // start thermal measurement (and turn ON sensors if was OFF)
CMD_SENSORS_STATE, // reply data with sensors state (data: 0 - SState, 1,2 - sens_present0, 3 - Nsens_presend, 4 - Ntemp_measured)
CMD_START_SCAN, // run scan mode @ all controllers
CMD_STOP_SCAN, // stop scan mode
CMD_SENSORS_OFF, // turn off power of sensors

View File

@@ -26,6 +26,10 @@
#include "stm32f0.h"
#define CAN_SPEED_DEFAULT (250)
#define CAN_SPEED_MIN (12)
#define CAN_SPEED_MAX (1000)
// LED0
#define LED0_port GPIOB
#define LED0_pin (1<<10)

View File

@@ -75,10 +75,10 @@ int main(void){
adc_setup();
usart_setup();
i2c_setup(LOW_SPEED);
CAN_setup();
CAN_setup(0); // setup with default 250kbaud
/*
SEND("Greetings! My address is ");
printuhex(getCANID());
printuhex(CANID);
newline();
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
@@ -87,8 +87,11 @@ int main(void){
if(RCC->CSR & RCC_CSR_SFTRSTF){ // software reset occured
SEND("SOFTRESET=1\n");
}
*/
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
USB_setup();
readCANID();
if(CANID == MASTER_ID) cansniffer = 1; // MASTER in sniffer mode by default
iwdg_setup();
while (1){
@@ -97,7 +100,7 @@ int main(void){
if(!noLED) LED_blink(LED0);
lastT = Tms;
// send dummy command to noone to test CAN bus
can_send_cmd(NOONE_ID, CMD_DUMMY0);
//can_send_cmd(NOONE_ID, CMD_DUMMY0);
}
if(lastS > Tms || Tms - lastS > 5){ // run sensors proc. once per 5ms
sensors_process();
@@ -109,11 +112,11 @@ int main(void){
SEND("CAN bus fifo overrun occured!\n");
}else if(stat == CAN_ERROR){
if(!noLED) LED_off(LED1);
CAN_setup();
CAN_setup(0);
canerror = 1;
}
can_messages_proc();
if(SENS_SLEEPING == sensors_get_state()){ // show temperature @ each sleeping occurence
if(SENS_SLEEPING == Sstate){ // show temperature @ each sleeping occurence
if(!gotmeasurement){
gotmeasurement = 1;
showtemperature();
@@ -137,4 +140,3 @@ int main(void){
}
return 0;
}

View File

@@ -117,6 +117,84 @@ static inline void showUIvals(){
newline();
}
static char *omit_spaces(char *buf){
while(*buf){
if(*buf > ' ') break;
++buf;
}
return buf;
}
static inline void setCANbrate(char *str){
if(!str || !*str) return;
int32_t spd = 0;
str = omit_spaces(str);
char *e = getnum(str, &spd);
if(e == str){
SEND("BAUDRATE=");
printu(curcanspeed);
newline();
return;
}
if(spd < CAN_SPEED_MIN || spd > CAN_SPEED_MAX){
SEND("Wrong speed\n");
return;
}
CAN_setup(spd);
SEND("OK\n");
}
// parse `txt` to CAN_message
static CAN_message *parseCANmsg(char *txt){
static CAN_message canmsg;
int32_t N;
char *n;
int ctr = -1;
canmsg.ID = 0xffff;
do{
txt = omit_spaces(txt);
n = getnum(txt, &N);
if(txt == n) break;
txt = n;
if(ctr == -1){
if(N > 0x7ff){
SEND("ID should be 11-bit number!\n");
return NULL;
}
canmsg.ID = (uint16_t)(N&0x7ff);
ctr = 0;
continue;
}
if(ctr > 7){
SEND("ONLY 8 data bytes allowed!\n");
return NULL;
}
if(N > 0xff){
SEND("Every data portion is a byte!\n");
return NULL;
}
canmsg.data[ctr++] = (uint8_t)(N&0xff);
}while(1);
if(canmsg.ID == 0xffff){
SEND("NO ID given, send nothing!\n");
return NULL;
}
SEND("Message parsed OK\n");
sendbuf();
canmsg.length = (uint8_t) ctr;
return &canmsg;
}
// send command, format: ID (hex/bin/dec) data bytes (up to 8 bytes, space-delimeted)
static void sendCANcommand(char *txt){
CAN_message *msg = parseCANmsg(txt);
if(!msg) return;
uint32_t N = 1000;
while(CAN_BUSY == can_send(msg->data, msg->length, msg->ID)){
if(--N == 0) break;
}
}
/**
* @brief cmd_parser - command parsing
* @param txt - buffer with commands & data
@@ -129,19 +207,12 @@ void cmd_parser(char *txt, uint8_t isUSB){
sendbuf();
if(_1st >= '0' && _1st < '8'){ // send command to Nth controller, not broadcast
if(L == 3){ // with '\n' at end!
/*if(_1st == '0'){
bufputchar(txt[1]);
_1st = txt[1] + 'a' - 'A'; // change network command to local
bufputchar('\n');
}else */
{
ID = (CAN_ID_PREFIX & CAN_ID_MASK) | (_1st - '0');
_1st = txt[1];
}
ID = (CAN_ID_PREFIX & CAN_ID_MASK) | (_1st - '0');
_1st = txt[1];
}else{
_1st = '?'; // show help
}
}else if(L != 2) _1st = '?';
}
switch(_1st){
case 'a':
showADCvals();
@@ -149,12 +220,20 @@ void cmd_parser(char *txt, uint8_t isUSB){
case 'B':
CANsend(ID, CMD_DUMMY0, _1st);
break;
case 'b':
setCANbrate(txt + 1);
break;
case 'c':
showcoeffs();
break;
case 'D':
CANsend(MASTER_ID, CMD_DUMMY1, _1st);
break;
case 'd':
SEND("Can address: ");
printuhex(CANID);
newline();
break;
case 'E':
CANsend(ID, CMD_STOP_SCAN, _1st);
break;
@@ -168,9 +247,8 @@ void cmd_parser(char *txt, uint8_t isUSB){
sensors_off();
break;
case 'g':
SEND("Can address: ");
printuhex(getCANID());
newline();
SEND("Group ID (sniffer) CAN mode\n");
CAN_listenall();
break;
case 'H':
CANsend(ID, CMD_HIGH_SPEED, _1st);
@@ -178,12 +256,6 @@ void cmd_parser(char *txt, uint8_t isUSB){
case 'h':
i2c_setup(HIGH_SPEED);
break;
case 'i':
CAN_reinit();
SEND("Can address: ");
printuhex(getCANID());
newline();
break;
case 'J':
CANsend(ID, CMD_GETMCUTEMP, _1st);
break;
@@ -227,11 +299,8 @@ void cmd_parser(char *txt, uint8_t isUSB){
case 'r':
i2c_setup(CURRENT_SPEED);
break;
case 'S':
CANsend(ID, CMD_START_SCAN, _1st);
break;
case 's':
sensors_scan_mode = 1;
sendCANcommand(txt+1);
break;
case 'T':
CANsend(ID, CMD_START_MEASUREMENT, _1st);
@@ -239,14 +308,9 @@ void cmd_parser(char *txt, uint8_t isUSB){
case 't':
if(!sensors_scan_mode) sensors_start();
break;
break;
case 'u':
SEND("CANERROR=");
if(canerror){
canerror = 0;
bufputchar('1');
}else bufputchar('0');
newline();
SEND("Unique ID CAN mode\n");
CAN_listenone();
break;
case 'V':
CANsend(ID, CMD_LOWEST_SPEED, _1st);
@@ -254,12 +318,32 @@ void cmd_parser(char *txt, uint8_t isUSB){
case 'v':
i2c_setup(VERYLOW_SPEED);
break;
case 'Z':
case 'X':
CANsend(ID, CMD_START_SCAN, _1st);
break;
case 'x':
sensors_scan_mode = 1;
break;
case 'Y':
CANsend(ID, CMD_SENSORS_STATE, _1st);
break;
case 'z':
case 'y':
SEND("SSTATE0=");
printu(sensors_get_state());
SEND(sensors_get_statename(Sstate));
SEND("\nNSENS0=");
printu(Nsens_present);
SEND("\nSENSPRESENT0=");
printu(sens_present[0] | (sens_present[1]<<8));
SEND("\nNTEMP0=");
printu(Ntemp_measured);
newline();
break;
case 'z':
SEND("CANERROR=");
if(canerror){
canerror = 0;
bufputchar('1');
}else bufputchar('0');
newline();
break;
default: // help
@@ -268,13 +352,14 @@ void cmd_parser(char *txt, uint8_t isUSB){
"0..7 - send command to given controller (0 - this) instead of broadcast\n"
"a - get raw ADC values\n"
"B - send broadcast CAN dummy message\n"
"b - get/set CAN bus baudrate\n"
"c - show coefficients (current)\n"
"d - get last CAN address\n"
"D - send CAN dummy message to master\n"
"Ee- end themperature scan\n"
"Ff- turn oFf sensors\n"
"g - get last CAN address\n"
"g - group (sniffer) CAN mode\n"
"Hh- high I2C speed\n"
"i - reinit CAN (with new address)\n"
"Jj- get MCU temperature\n"
"Kk- get U/I values\n"
"Ll- low I2C speed\n"
@@ -282,11 +367,13 @@ void cmd_parser(char *txt, uint8_t isUSB){
"Oo- turn onboard diagnostic LEDs *O*n or *o*ff (both commands are local)\n"
"P - ping everyone over CAN\n"
"Rr- reinit I2C\n"
"Ss- Start themperature scan\n"
"s - send CAN message\n"
"Tt- start temperature measurement\n"
"u - check CAN status for errors\n"
"u - unique ID (default) CAN mode\n"
"Vv- very low I2C speed\n"
"Z - get sensors state over CAN\n"
"Xx- Start themperature scan\n"
"Yy- get sensors state over CAN\n"
"z - check CAN status for errors\n"
);
break;
}
@@ -321,3 +408,78 @@ void printuhex(uint32_t val){
}
}
}
// THERE'S NO OVERFLOW PROTECTION IN NUMBER READ PROCEDURES!
// read decimal number
static char *getdec(const char *buf, int32_t *N){
int32_t num = 0;
int positive = TRUE;
if(*buf == '-'){
positive = FALSE;
++buf;
}
while(*buf){
char c = *buf;
if(c < '0' || c > '9'){
break;
}
num *= 10;
num += c - '0';
++buf;
}
*N = (positive) ? num : -num;
return (char *)buf;
}
// read hexadecimal number (without 0x prefix!)
static char *gethex(const char *buf, int32_t *N){
uint32_t num = 0;
while(*buf){
char c = *buf;
uint8_t M = 0;
if(c >= '0' && c <= '9'){
M = '0';
}else if(c >= 'A' && c <= 'F'){
M = 'A' - 10;
}else if(c >= 'a' && c <= 'f'){
M = 'a' - 10;
}
if(M){
num <<= 4;
num += c - M;
}else{
break;
}
++buf;
}
*N = (int32_t)num;
return (char *)buf;
}
// read binary number (without 0b prefix!)
static char *getbin(const char *buf, int32_t *N){
uint32_t num = 0;
while(*buf){
char c = *buf;
if(c < '0' || c > '1'){
break;
}
num <<= 1;
if(c == '1') num |= 1;
++buf;
}
*N = (int32_t)num;
return (char *)buf;
}
/**
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
* @param buf - buffer with number and so on
* @param N - the number read
* @return pointer to first non-number symbol in buf (if it is == buf, there's no number)
*/
char *getnum(char *txt, int32_t *N){
if(*txt == '0'){
if(txt[1] == 'x' || txt[1] == 'X') return gethex(txt+2, N);
if(txt[1] == 'b' || txt[1] == 'B') return getbin(txt+2, N);
}
return getdec(txt, N);
}

View File

@@ -45,5 +45,6 @@ void bufputchar(char ch);
void printu(uint32_t val);
void printuhex(uint32_t val);
void sendbuf();
char *getnum(char *txt, int32_t *N);
#endif // __PROTO_H__

View File

@@ -28,12 +28,12 @@
extern volatile uint32_t Tms;
uint8_t sensors_scan_mode = 0; // infinite scan mode
static uint32_t lastSensT = 0;
static SensorsState Sstate = SENS_OFF; // turn on sensors only by request
SensorsState Sstate = SENS_OFF; // turn on sensors only by request
static uint8_t curr_mul_addr = 0; // current sensors pair address @ multiplexer
static uint8_t overcurnt_ctr = 0; // if this counter > 32 go to OFF state
uint8_t sens_present[2] = {0,0}; // bit flag: Nth bit == 1 if sensor[s] on given channel found
static uint8_t Nsens_present = 0; // total amount of sensors found
static uint8_t Ntemp_measured = 0; // total amount of themperatures measured
uint8_t Nsens_present = 0; // total amount of sensors found
uint8_t Ntemp_measured = 0; // total amount of themperatures measured
// 8 - amount of pairs, 2 - amount in pair, 5 - amount of Coef.
static uint16_t coefficients[MUL_MAX_ADDRESS+1][2][5]; // Coefficients for given sensors
@@ -43,7 +43,23 @@ int16_t Temperatures[MUL_MAX_ADDRESS+1][2];
// pair addresses
static const uint8_t Taddr[2] = {TSYS01_ADDR0, TSYS01_ADDR1};
SensorsState sensors_get_state(){return Sstate;}
static const char *statenames[] = {
[SENS_INITING] = "init"
,[SENS_RESETING] = "reset"
,[SENS_GET_COEFFS] = "getcoeff"
,[SENS_SLEEPING] = "sleep"
,[SENS_START_MSRMNT] = "startmeasure"
,[SENS_WAITING] = "waitresults"
,[SENS_GATHERING] = "collectdata"
,[SENS_OFF] = "off"
,[SENS_OVERCURNT] = "overcurrent"
,[SENS_OVERCURNT_OFF] = "offbyovercurrent"
};
const char *sensors_get_statename(SensorsState x){
if(x >= SENS_STATE_CNT) return "wrongstate";
return statenames[x];
}
/**
* Get temperature & calculate it by polinome
@@ -110,6 +126,7 @@ void sensors_start(){
Sstate = SENS_START_MSRMNT;
break;
case SENS_OFF:
overcurnt_ctr = 0;
sensors_on();
break;
default:
@@ -162,7 +179,6 @@ static uint8_t getcoefsproc(){
}else break;
}
if(err){ // restart all procedures if we can't get coeffs of present sensor
sensors_on();
return 1;
}
}
@@ -173,7 +189,13 @@ static uint8_t getcoefsproc(){
static uint8_t msrtempproc(){
uint8_t i, j;
for(i = 0; i < 2; ++i){
if(!(sens_present[i] & (1<<curr_mul_addr))) continue; // no sensors @ given line
if(!(sens_present[i] & (1<<curr_mul_addr))){ // no sensors @ given line - try to find it
resetproc();
if(sens_present[i] & (1<<curr_mul_addr)){ // found!
if(getcoefsproc()) continue; // error
else count_sensors(); // refresh Nsens_present
}else continue; // not found - continue
}
for(j = 0; j < 5; ++j){
if(write_i2c(Taddr[i], TSYS01_START_CONV)) break;
if(!write_i2c(Taddr[i], TSYS01_RESET)) i2c_setup(CURRENT_SPEED); // maybe I2C restart will solve the problem?

View File

@@ -35,10 +35,6 @@
// no sensor on given channel
#define NO_SENSOR (-31000)
extern uint8_t sensors_scan_mode;
extern int16_t Temperatures[MUL_MAX_ADDRESS+1][2];
extern uint8_t sens_present[2];
typedef enum{
SENS_INITING // 0 power on
,SENS_RESETING // 1 discovery sensors resetting them
@@ -50,9 +46,17 @@ typedef enum{
,SENS_OFF // 7 sensors' power is off by external command
,SENS_OVERCURNT // 8 overcurrent detected @ any stage
,SENS_OVERCURNT_OFF // 9 sensors' power is off due to continuous overcurrent
,SENS_STATE_CNT
} SensorsState;
SensorsState sensors_get_state();
extern uint8_t sensors_scan_mode;
extern int16_t Temperatures[MUL_MAX_ADDRESS+1][2];
extern uint8_t sens_present[2];
extern SensorsState Sstate;
extern uint8_t Nsens_present;
extern uint8_t Ntemp_measured;
const char *sensors_get_statename(SensorsState x);
void sensors_process();
void sensors_off();

Binary file not shown.