diff --git a/STM32/TSYS_controller/Makefile b/STM32/TSYS_controller/Makefile index 4789ed0..c985cda 100644 --- a/STM32/TSYS_controller/Makefile +++ b/STM32/TSYS_controller/Makefile @@ -8,7 +8,7 @@ MCU = F042x6 # hardware definitions DEFS := -DUSARTNUM=1 -DI2CPINS=67 #DEFS += -DCHECK_TMOUT -DEFS += -DEBUG +#DEFS += -DEBUG # change this linking script depending on particular MCU model, # for example, if you have STM32F103VBT6, you should write: LDSCRIPT = ld/stm32f042k.ld diff --git a/STM32/TSYS_controller/can.c b/STM32/TSYS_controller/can.c new file mode 100644 index 0000000..1783389 --- /dev/null +++ b/STM32/TSYS_controller/can.c @@ -0,0 +1,35 @@ +/* + * geany_encoding=koi8-r + * can.c + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#include "can.h" + +static uint8_t CAN_addr = 0; + +// get CAN address data from GPIO pins +void readCANaddr(){ + CAN_addr = READ_CAN_INV_ADDR(); + CAN_addr = ~CAN_addr & 0x7; +} + +uint8_t getCANaddr(){ + return CAN_addr; +} diff --git a/STM32/TSYS_controller/can.h b/STM32/TSYS_controller/can.h new file mode 100644 index 0000000..eb868d1 --- /dev/null +++ b/STM32/TSYS_controller/can.h @@ -0,0 +1,32 @@ +/* + * geany_encoding=koi8-r + * can.h + * + * Copyright 2018 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ +#pragma once +#ifndef __CAN_H__ +#define __CAN_H__ + +#include "hardware.h" + +void readCANaddr(); +uint8_t getCANaddr(); + +#endif // __CAN_H__ diff --git a/STM32/TSYS_controller/hardware.c b/STM32/TSYS_controller/hardware.c index 206d33d..5ee1a68 100644 --- a/STM32/TSYS_controller/hardware.c +++ b/STM32/TSYS_controller/hardware.c @@ -22,6 +22,7 @@ */ #include "hardware.h" +#include "usart.h" I2C_SPEED curI2Cspeed = LOW_SPEED; @@ -37,13 +38,17 @@ void gpio_setup(void){ GPIO_MODER_MODER10_O | GPIO_MODER_MODER11_O | GPIO_MODER_MODER0_O | GPIO_MODER_MODER1_O | GPIO_MODER_MODER2_O | GPIO_MODER_MODER12_O; - // multiplexer outputs are push-pull: - GPIOB->OTYPER |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 | GPIO_OTYPER_OT_2 | - GPIO_OTYPER_OT_12; + // multiplexer outputs are push-pull, GPIOB->OTYPER = 0 MUL_OFF(); // PA8 - power enable GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER8)) | GPIO_MODER_MODER8_O; + // PA13..15 - CAN address, pullup inputs + GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPDR13 | GPIO_PUPDR_PUPDR14 | + GPIO_PUPDR_PUPDR15) + ) | + GPIO_PUPDR_PUPDR13_0 | GPIO_PUPDR_PUPDR14_0 | + GPIO_PUPDR_PUPDR15_0; pin_set(LED0_port, LED0_pin); // clear LEDs pin_set(LED1_port, LED1_pin); } @@ -54,6 +59,7 @@ void i2c_setup(I2C_SPEED speed){ }else{ curI2Cspeed = speed; } + MSG("setup I2C\n"); I2C1->CR1 = 0; #if I2CPINS == 910 /* diff --git a/STM32/TSYS_controller/hardware.h b/STM32/TSYS_controller/hardware.h index c31660a..fa5913b 100644 --- a/STM32/TSYS_controller/hardware.h +++ b/STM32/TSYS_controller/hardware.h @@ -72,6 +72,9 @@ // check overcurrent (PB3 == 0) #define SENSORS_OVERCURNT() ((1<<3) != (GPIOB->IDR & (1<<3))) +// CAN address - PA13..PA15 +#define READ_CAN_INV_ADDR() ((GPIOA->IDR & (0x7<<13))>>13) + typedef enum{ VERYLOW_SPEED, LOW_SPEED, diff --git a/STM32/TSYS_controller/i2c.c b/STM32/TSYS_controller/i2c.c index 11412df..c5f02cb 100644 --- a/STM32/TSYS_controller/i2c.c +++ b/STM32/TSYS_controller/i2c.c @@ -23,6 +23,7 @@ #include "stm32f0.h" #include "hardware.h" #include "i2c.h" +#include "usart.h" /** * I2C for TSYS01 @@ -51,9 +52,17 @@ static uint32_t cntr; */ uint8_t write_i2c(uint8_t addr, uint8_t data){ cntr = Tms; - while(I2C1->ISR & I2C_ISR_BUSY) if(Tms - cntr > I2C_TIMEOUT) return 0; // check busy + I2C1->ICR = 0x3f38; // clear all errors + while(I2C1->ISR & I2C_ISR_BUSY) if(Tms - cntr > I2C_TIMEOUT){ + MSG("always busy\n"); + return 0; // check busy + } cntr = Tms; - while(I2C1->CR2 & I2C_CR2_START) if(Tms - cntr > I2C_TIMEOUT) return 0; // check start + while(I2C1->CR2 & I2C_CR2_START) if(Tms - cntr > I2C_TIMEOUT){ + MSG("always start\n"); + return 0; // check start + } + //I2C1->ICR = 0x3f38; // clear all errors I2C1->CR2 = 1<<16 | addr | I2C_CR2_AUTOEND; // 1 byte, autoend // now start transfer I2C1->CR2 |= I2C_CR2_START; @@ -61,11 +70,19 @@ uint8_t write_i2c(uint8_t addr, uint8_t data){ while(!(I2C1->ISR & I2C_ISR_TXIS)){ // ready to transmit if(I2C1->ISR & I2C_ISR_NACKF){ I2C1->ICR |= I2C_ICR_NACKCF; + //I2C1->ICR = 0x3f38; + MSG("NACK\n"); + return 0; + } + if(Tms - cntr > I2C_TIMEOUT){ + //I2C1->ICR = 0x3f38; + MSG("Timeout\n"); return 0; } - if(Tms - cntr > I2C_TIMEOUT) return 0; } I2C1->TXDR = data; // send data + // wait for data gone + while(I2C1->ISR & I2C_ISR_BUSY) if(Tms - cntr > I2C_TIMEOUT){break;} return 1; } @@ -76,9 +93,17 @@ uint8_t write_i2c(uint8_t addr, uint8_t data){ uint8_t read_i2c(uint8_t addr, uint32_t *data, uint8_t nbytes){ uint32_t result = 0; cntr = Tms; - while(I2C1->ISR & I2C_ISR_BUSY) if(Tms - cntr > 5) return 0; // check busy + MSG("read_i2c\n"); + while(I2C1->ISR & I2C_ISR_BUSY) if(Tms - cntr > I2C_TIMEOUT){ + MSG("always busy\n"); + return 0; // check busy + } cntr = Tms; - while(I2C1->CR2 & I2C_CR2_START) if(Tms - cntr > 5) return 0; // check start + while(I2C1->CR2 & I2C_CR2_START) if(Tms - cntr > I2C_TIMEOUT){ + MSG("always start\n"); + return 0; // check start + } + // I2C1->ICR = 0x3f38; // clear all errors // read N bytes I2C1->CR2 = (nbytes<<16) | addr | 1 | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN; I2C1->CR2 |= I2C_CR2_START; @@ -88,9 +113,15 @@ uint8_t read_i2c(uint8_t addr, uint32_t *data, uint8_t nbytes){ while(!(I2C1->ISR & I2C_ISR_RXNE)){ // wait for data if(I2C1->ISR & I2C_ISR_NACKF){ I2C1->ICR |= I2C_ICR_NACKCF; + //I2C1->ICR = 0x3f38; + MSG("NACK\n"); + return 0; + } + if(Tms - cntr > I2C_TIMEOUT){ + //I2C1->ICR = 0x3f38; + MSG("Timeout\n"); return 0; } - if(Tms - cntr > 5) return 0; } result = (result << 8) | I2C1->RXDR; } diff --git a/STM32/TSYS_controller/i2c.h b/STM32/TSYS_controller/i2c.h index da481b7..a6ae255 100644 --- a/STM32/TSYS_controller/i2c.h +++ b/STM32/TSYS_controller/i2c.h @@ -21,19 +21,19 @@ * */ -// timeout in ms -#define I2C_TIMEOUT (15) +// timeout of I2C bus in ms +#define I2C_TIMEOUT (100) // CSB=1, address 1110110 #define TSYS01_ADDR0 (0x76 << 1) // CSB=0, address 1110111 #define TSYS01_ADDR1 (0x77 << 1) -// registers: reset, read ADC value, start converstion, sart of PROM +// registers: reset, read ADC value, start converstion, start of PROM #define TSYS01_RESET (0x1E) #define TSYS01_ADC_READ (0x00) #define TSYS01_START_CONV (0x48) #define TSYS01_PROM_ADDR0 (0xA0) -// conversion time = 10ms -#define CONV_TIME (10) +// conversion time (with reserve) +#define CONV_TIME (15) uint8_t read_i2c(uint8_t addr, uint32_t *data, uint8_t nbytes); uint8_t write_i2c(uint8_t addr, uint8_t data); diff --git a/STM32/TSYS_controller/main.c b/STM32/TSYS_controller/main.c index 1d04fc0..e800e4e 100644 --- a/STM32/TSYS_controller/main.c +++ b/STM32/TSYS_controller/main.c @@ -23,6 +23,7 @@ #include "usart.h" #include "i2c.h" #include "sensors_manage.h" +#include "can.h" #pragma message("USARTNUM=" STR(USARTNUM)) #pragma message("I2CPINS=" STR(I2CPINS)) @@ -61,7 +62,7 @@ void iwdg_setup(){ } int main(void){ - uint32_t lastT = 0; + uint32_t lastT = 0, lastS = 0; int16_t L = 0; char *txt; sysreset(); @@ -70,8 +71,11 @@ int main(void){ usart_setup(); i2c_setup(LOW_SPEED); iwdg_setup(); + readCANaddr(); - SEND("Greetings!\n"); + SEND("Greetings! My address is "); + printu(getCANaddr()); + newline(); while (1){ IWDG->KR = IWDG_REFRESH; // refresh watchdog @@ -79,7 +83,10 @@ int main(void){ LED_blink(LED0); lastT = Tms; } - sensors_process(); + if(lastS > Tms || Tms - lastS > 5){ // run sensors proc. once per 5ms + sensors_process(); + lastS = Tms; + } if(usartrx()){ // usart1 received data, store in in buffer L = usart_getline(&txt); char _1st = txt[0]; @@ -89,7 +96,7 @@ int main(void){ case 'C': // 'C' - show coefficients showcoeffs(); break; - case 'D': + case 'O': sensors_on(); break; case 'T': // 'T' - get temperature @@ -111,14 +118,40 @@ int main(void){ i2c_setup(HIGH_SPEED); SEND("High speed\n"); break; + case 'G': + SEND("Can address: "); + printu(getCANaddr()); + newline(); + break; +#ifdef EBUG + case 'd': + case 'g': + case 't': + case 's': + senstest(_1st); + break; + case 'p': + sensors_process(); + break; +#endif default: // help SEND("'C' - show coefficients\n" - "'D' - slave discovery\n" + "'O' - turn On sensors\n" "'T' - get raw temperature\n" "'R' - reinit I2C\n" "'V' - very low speed\n" "'L' - low speed\n" - "'H' - high speed\n"); + "'H' - high speed\n" + "'G' - get CAN address\n" +#ifdef EBUG + "\t\tTEST OPTIONS\n" + "'d' - discovery\n" + "'g' - get coeff\n" + "'t' - measure temper\n" + "'s' - show temper measured\n" + "'p' - sensors_process()\n" +#endif + ); break; } } diff --git a/STM32/TSYS_controller/sensors_manage.c b/STM32/TSYS_controller/sensors_manage.c index febcb5b..9849ae0 100644 --- a/STM32/TSYS_controller/sensors_manage.c +++ b/STM32/TSYS_controller/sensors_manage.c @@ -59,7 +59,7 @@ SensorsState sensors_get_state(){return Sstate;} static uint16_t calc_t(uint32_t t, int i){ uint16_t *coeff = coefficients[curr_mul_addr][i]; if(coeff[0] == 0) return BAD_TEMPERATURE; // what is with coeffs? - if(t < 6500000 || t > 13000000) return BAD_TEMPERATURE; // wrong value - too small or too large + if(t < 600000 || t > 30000000) return BAD_TEMPERATURE; // wrong value - too small or too large int j; double d = (double)t/256., tmp = 0.; // k0*(-1.5e-2) + 0.1*1e-5*val*(1*k1 + 1e-5*val*(-2.*k2 + 1e-5*val*(4*k3 + 1e-5*val*(-2*k4)))) @@ -146,20 +146,46 @@ static uint8_t resetproc(){ static uint8_t getcoefsproc(){ uint8_t i, j; const uint8_t regs[5] = {0xAA, 0xA8, 0xA6, 0xA4, 0xA2}; // commands for coefficients +#ifdef EBUG +MSG("sens_present[0]="); +printu(sens_present[0]); +SEND(", sens_present[1]="); +printu(sens_present[1]); +newline(); +#endif for(i = 0; i < 2; ++i){ if(!(sens_present[i] & (1< MUL_MAX_ADDRESS){ // scan is over curr_mul_addr = 0; return 1; @@ -287,17 +341,21 @@ void sensors_process(){ MSG("init->reset\n"); i2c_setup(CURRENT_SPEED); Sstate = SENS_RESETING; + lastSensT = Tms; + overcurnt_ctr = 0; break; case SENS_RESETING: // reset & discovery procedure - overcurnt_ctr = 0; - if(sensors_scan(resetproc)){ - count_sensors(); // get total amount of sensors - if(Nsens_present){ + if(Tms - lastSensT > POWERUP_TIME){ + overcurnt_ctr = 0; + if(sensors_scan(resetproc)){ + count_sensors(); // get total amount of sensors + if(Nsens_present){ MSG("reset->getcoeff\n"); - Sstate = SENS_GET_COEFFS; - }else{ // no sensors found + Sstate = SENS_GET_COEFFS; + }else{ // no sensors found MSG("reset->off\n"); - Sstate = SENS_OFF; + sensors_off(); + } } } break; @@ -306,8 +364,8 @@ MSG("reset->off\n"); MSG("got coeffs for "); #ifdef EBUG printu(Nsens_present); +SEND(" sensors ->start\n"); #endif -MSG(" sensors ->start\n"); Sstate = SENS_START_MSRMNT; } break; @@ -345,10 +403,44 @@ MSG("sleep->start\n"); } break; case SENS_OVERCURNT: // try to reinit all after overcurrent -MSG("overcurrent occured!\n"); +MSG("try to turn on after overcurrent\n"); sensors_on(); break; default: // do nothing break; } } + +#ifdef EBUG +void senstest(char cmd){ + MUL_OFF(); + SENSORS_ON(); + if(SENSORS_OVERCURNT()){ + SENSORS_OFF(); + SEND("Overcurrent!\n"); + return; + } + curr_mul_addr = 0; + MUL_ADDRESS(0); + MUL_ON(); + switch (cmd){ + case 'd': // discovery once + resetproc(); + count_sensors(); + break; + case 'g': + getcoefsproc(); + break; + case 't': + msrtempproc(); + break; + case 's': + gettempproc(); + showtemperature(); + break; + default: + return; + } + Sstate = SENS_OFF; +} +#endif diff --git a/STM32/TSYS_controller/sensors_manage.h b/STM32/TSYS_controller/sensors_manage.h index b79e081..335bb66 100644 --- a/STM32/TSYS_controller/sensors_manage.h +++ b/STM32/TSYS_controller/sensors_manage.h @@ -26,6 +26,8 @@ #include "hardware.h" +// time for power up procedure (500ms) +#define POWERUP_TIME (500) // time between two readings (3sec) #define SLEEP_TIME (3000) // error in measurement == -300degrC @@ -53,4 +55,8 @@ void sensors_on(); void showcoeffs(); void showtemperature(); +#ifdef EBUG +void senstest(char cmd); +#endif + #endif // __SENSORS_MANAGE_H__ diff --git a/STM32/TSYS_controller/tsys01.bin b/STM32/TSYS_controller/tsys01.bin index c4ea26d..4198438 100755 Binary files a/STM32/TSYS_controller/tsys01.bin and b/STM32/TSYS_controller/tsys01.bin differ diff --git a/STM32/TSYS_controller/usart.h b/STM32/TSYS_controller/usart.h index c34b356..8ecd6d3 100644 --- a/STM32/TSYS_controller/usart.h +++ b/STM32/TSYS_controller/usart.h @@ -34,7 +34,7 @@ #define NEWLINE() do{}while(LINE_BUSY == usart_send_blocking('\n', 1)) #ifdef EBUG -#define MSG(str) SEND(str) +#define MSG(str) do{SEND(__FILE__ " (L" STR(__LINE__) "): " str);}while(0) #else #define MSG(str) #endif