Explorar el Código

Merge branch 'devel' of git.shilov.pp.ua:shiva/VAPC2 into devel

Vladimir Shilov hace 5 años
padre
commit
03dfb6fb1f
Se han modificado 19 ficheros con 1055 adiciones y 624 borrados
  1. 1 0
      .gitignore
  2. 3 3
      Makefile
  3. 20 0
      ReadMe.txt
  4. 13 5
      VAPC2.cbp
  5. 23 0
      inc/board.h
  6. 1 1
      inc/stm8s_conf.h
  7. 0 148
      lib/event-system.c
  8. 0 33
      lib/event-system.h
  9. 36 108
      lib/i2c.c
  10. 8 5
      lib/i2c.h
  11. 69 109
      lib/ina219.c
  12. 26 8
      lib/ina219.h
  13. 0 29
      lib/list_event.h
  14. 25 48
      lib/max7219.c
  15. 50 55
      lib/max7219.h
  16. 2 43
      lib/rtos.c
  17. 7 10
      lib/rtos.h
  18. 761 11
      src/main.c
  19. 10 8
      src/stm8s_it.c

+ 1 - 0
.gitignore

@@ -7,3 +7,4 @@ EWSTM8/Debug
 EWSTM8/Release
 EWSTM8/settings
 EWSTM8/*.dep
+*.log

+ 3 - 3
Makefile

@@ -2,7 +2,7 @@
 # IAR Makefile for STM8S #
 ##########################
 
-PROJECT=VAPC
+PROJECT=VAPC2
 
 # Location of build tools and atomthreads sources
 EWSTM8_DIR=C:\IAR\Embedded Workbench 7.3\stm8
@@ -12,11 +12,11 @@ ASM=$(EWSTM8_BIN)/iasmstm8
 LINK=$(EWSTM8_BIN)/ilinkstm8
 HEX=$(EWSTM8_BIN)/ielftool
 FLASHTOOL=C:/MCU/STMicroelectronics/st_toolset/stvp/STVP_CmdLine.exe
-FLASHOPT=-Device=STM8S003F3
+FLASHOPT=-no_log -no_loop -Device=STM8S003F3
 
 DEFINES = -D USE_STDPERIPH_DRIVER
 DEFINES += -D STM8S003
-#DEFINES += -D USE_RTOS
+DEFINES += -D USE_RTOS
 
 # Sources paths
 APP_SRC = src

+ 20 - 0
ReadMe.txt

@@ -9,3 +9,23 @@
 ===
 2019.01.23
 Ужал плату до размера 42 на 37 мм.
+---
+2019.07.09
+Какая-то ерунда с распинвкой индикаторов - плата и схема сходяться, а по 
+факту - пришлось методом тыка определять на каком бите какой сегмент...
+
+Хотел зелёный индикатор сверху, а красный снизу - запаял наоборот...
+
+Внешний кварц не запускается.
+
+Запустил SPI и MAX7219.
+---
+2019.07.10
+Запустил I2C, INA219, RTOS.
+---
+2019.07.11
+Исправил вычисления тока и мощности - 8 бит накладывают свои ограничения.
+нужно сделать отображение напряжения с шунта -Sh-
+нужно вернуть calculateValues
+попробовать ещё усреднять значения (3 раза за 250 мсек - 68.1 период измерения)
+ненулевой холостой ток...

+ 13 - 5
VAPC2.cbp

@@ -3,22 +3,28 @@
 	<FileVersion major="1" minor="6" />
 	<Project>
 		<Option title="VAPC2" />
+		<Option makefile_is_custom="1" />
 		<Option pch_mode="2" />
-		<Option compiler="iar_stm8_compiler" />
+		<Option compiler="copy_of_iar_stm8_compiler" />
+		<MakeCommands>
+			<Build command="make" />
+			<CompileFile command="" />
+			<Clean command="make clean" />
+			<DistClean command="" />
+			<AskRebuildNeeded command="" />
+			<SilentBuild command="make &gt; $(CMD_NULL)" />
+		</MakeCommands>
 		<Build>
 			<Target title="Release">
 				<Option output="bin/Release/VAPC2" prefix_auto="1" extension_auto="1" />
 				<Option object_output="obj/Release/" />
 				<Option type="1" />
-				<Option compiler="iar_stm8_compiler" />
+				<Option compiler="copy_of_iar_stm8_compiler" />
 				<Compiler>
 					<Add option="-Oh" />
 				</Compiler>
 			</Target>
 		</Build>
-		<Compiler>
-			<Add option="--remarks" />
-		</Compiler>
 		<Unit filename="StdPerphDrv/inc/stm8s.h" />
 		<Unit filename="StdPerphDrv/inc/stm8s_adc1.h" />
 		<Unit filename="StdPerphDrv/inc/stm8s_adc2.h" />
@@ -120,6 +126,7 @@
 		<Unit filename="StdPerphDrv/src/stm8s_wwdg.c">
 			<Option compilerVar="CC" />
 		</Unit>
+		<Unit filename="inc/board.h" />
 		<Unit filename="inc/stm8s_conf.h" />
 		<Unit filename="inc/stm8s_it.h" />
 		<Unit filename="lib/event-system.c">
@@ -153,6 +160,7 @@
 			<code_completion />
 			<envvars />
 			<debugger />
+			<editor_config active="1" use_tabs="0" tab_indents="1" tab_width="2" indent="2" eol_mode="0" />
 		</Extensions>
 	</Project>
 </CodeBlocks_project_file>

+ 23 - 0
inc/board.h

@@ -0,0 +1,23 @@
+#ifndef __BOARD_H
+#define __BOARD_H
+
+/* MACROs for SET, RESET or TOGGLE Output port */
+#define GPIO_HIGH(a,b)    a->ODR |= b
+#define GPIO_LOW(a,b)     a->ODR &= ~b
+#define GPIO_TOGGLE(a,b)  a->ODR ^= b
+
+#define BUTTON_NUM        2
+#define BUTTON1_PORT      GPIOD
+#define BUTTON1_PIN       GPIO_PIN_4
+#define BUTTON2_PORT      GPIOA
+#define BUTTON2_PIN       GPIO_PIN_3
+
+#define SPI_PORT          GPIOC
+#define SPI_SCK           GPIO_PIN_5
+#define SPI_MOSI          GPIO_PIN_6
+#define SPI_PINS          (SPI_SCK | SPI_MOSI)
+
+#define SPI_LOAD_PORT     GPIOD
+#define SPI_LOAD          GPIO_PIN_3
+
+#endif /* __BOARD_H */

+ 1 - 1
inc/stm8s_conf.h

@@ -90,7 +90,7 @@
 /* Exported constants --------------------------------------------------------*/
 /* Uncomment the line below to expanse the "assert_param" macro in the
    Standard Peripheral Library drivers code */
-#define USE_FULL_ASSERT    (1) 
+//#define USE_FULL_ASSERT    (1) 
 
 /* Exported macro ------------------------------------------------------------*/
 #ifdef  USE_FULL_ASSERT

+ 0 - 148
lib/event-system.c

@@ -1,148 +0,0 @@
-//***************************************************************************
-//
-//  Author(s)...: Pashgan    http://ChipEnable.Ru
-//  Target(s)...: любой микроконтроллер mega
-//  Compiler....: IAR 5.11A
-//  Description.: Заготовка для событийной системы на таблицах
-//  Data........: 30.09.12
-//
-//***************************************************************************
-#include "event-system.h"
-
-//функция-заглушка
-static void EmptyFunc(void);
-
-//кольцевой буфер
-static volatile es_event_t cycleBuf[SIZE_BUF];
-static volatile uint8_t tailBuf = 0;
-static volatile uint8_t headBuf = 0;
-static volatile uint8_t countBuf = 0;
-
-static volatile es_state_t _State;
-
-typedef struct {
-    es_state_t startState;
-    es_state_t endState;
-    es_event_t startEvent;
-    es_event_t endEvent;
-    es_state_t nextstate;
-    void (*pStateFunc1)(void);
-    void (*pStateFunc2)(void);
-} table_state_t;
-
-/** таблица состояний */
-const table_state_t table[] = {
-/* STATE from   STATE to     EVENT from       EVENT to         NEXT STATE   STATE_FUNC1   STATE_FUNC2 */
-
-  /* обязательная пустая строка таблицы */
-  {stNoChange, stNoChange, eventNull, eventNull, stNoChange, EmptyFunc, EmptyFunc}
-};
-
-/**
-  * @brief  Take event.
-  * @param  None
-  * @retval Event
-  */
-es_event_t ES_GetEvent(void)
-{
-  es_event_t event;
-  if (countBuf > 0){
-    event = cycleBuf[headBuf];
-    countBuf--;
-    headBuf = (headBuf + 1) & (SIZE_BUF - 1);
-    return event;
-  }
-  return eventNull;
-}
-
-/**
-  * @brief  Place event.
-  * @param  Event
-  * @retval None
-  */
-void ES_PlaceEvent(es_event_t event)
-{
-  if (countBuf < SIZE_BUF){
-      cycleBuf[tailBuf] = event;
-      tailBuf = (tailBuf + 1) & (SIZE_BUF - 1);
-      countBuf++;
-  /* сигнализация переполнения буфера событий */
-  } else {
-      while(1);
-  }
-}
-
-/**
-  * @brief  Initialize event system.
-  * @param  Start Event
-  * @retval None
-  */
-void ES_Init(es_state_t init_state)
-{
-  tailBuf = 0;
-  headBuf = 0;
-  countBuf = 0;
-  _State = init_state;
-}
-
-/**
-  * @brief  Fake function.
-  * @param  None
-  * @retval None
-  */
-static void EmptyFunc(void)
-{
-}
-
-/**
-  * @brief  Dispatcher of event system.
-  * @param  Event
-  * @retval None
-  */
-void ES_Dispatch(es_event_t event)
-{
-    void (*pStateFunc1)(void);
-    void (*pStateFunc2)(void);
-    uint8_t i;
-
-    pStateFunc1 = NULL;
-    pStateFunc2 = NULL;
-
-    //определяем следующее состояние
-    for (i=0; table[i].startEvent || table[i].endEvent; i++)
-    {
-        //если текущее состояние попадает в диапазон
-        if ((_State >= table[i].startState)&&(_State <= table[i].endState)){
-          //если поступившее событие попадает в диапазон
-          if((event >= table[i].startEvent) && (event <= table[i].endEvent)){
-            //меняем состояние если требуется
-            if (table[i].nextstate != stNoChange)
-              _State = table[i].nextstate;
-            pStateFunc1 = table[i].pStateFunc1;
-            pStateFunc2 = table[i].pStateFunc2;
-
-            break;
-          }
-        }
-    }
-    if (pStateFunc1) pStateFunc1();
-    if (pStateFunc2) pStateFunc2();
-}
-
-/**
-  * @brief  Return current state code.
-  * @param  None
-  * @retval Event
-  */
-es_state_t ES_GetState(void) {
-  return _State;
-}
-
-/**
-  * @brief  Set current state to given code .
-  * @param  Event
-  * @retval None
-  */
-void ES_SetState(es_state_t new_state) {
-  _State = new_state;
-}

+ 0 - 33
lib/event-system.h

@@ -1,33 +0,0 @@
-//***************************************************************************
-//
-//  Author(s)...: Pashgan    http://ChipEnable.Ru
-//  Target(s)...: любой микроконтроллер mega
-//  Compiler....: IAR 5.11A
-//  Description.: Заготовка для событийной системы на таблицах
-//  Data........: 30.09.12
-//
-//***************************************************************************
-
-/* Define to prevent recursive inclusion -------------------------------------*/
-#pragma once
-#ifndef EVENT_SYSTEM_H
-#define EVENT_SYSTEM_H
-
-#include "stm8s.h"
-#include "list_event.h"
-
-/* вместимость буфера очереди событий */
-#define SIZE_BUF 16
-
-void ES_Init(es_state_t init_state);    //инициализация
-es_state_t ES_GetState(void);           //взять код состояния
-void ES_SetState(es_state_t new_state); //установить код состояния
-es_event_t ES_GetEvent(void);           //взять код события
-void ES_PlaceEvent(es_event_t event);   //разместить событие
-void ES_Dispatch(es_event_t event);     //вызов диспетчера
-
-/**
- * ES function prototypes
- */
-
-#endif // EVENT_SYSTEM_H

+ 36 - 108
lib/i2c.c

@@ -57,8 +57,7 @@ void i2c_master_init(void) {
 /**
  * @brief Запись регистра slave-устройства
  */
-t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, \
-                        const uint8_t * data, uint8_t length) {
+t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, uint16_t data) {
 
   //Ждем освобождения шины I2C
   wait_event((I2C->SR3 & I2C_SR3_BUSY), 10);
@@ -83,12 +82,14 @@ t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, \
   I2C->DR = reg_addr;
 
   //Отправка данных
-  while(length --) {
-    //Ждем освобождения регистра данных
-    wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
-    //Отправляем адрес регистра
-    I2C->DR = *data++;
-  }
+  //Ждем освобождения регистра данных
+  wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
+  //Отправляем адрес регистра
+  I2C->DR = (uint8_t)(data >> 8);
+  //Ждем освобождения регистра данных
+  wait_event(!(I2C->SR1 & I2C_SR1_TXE), 1);
+  //Отправляем адрес регистра
+  I2C->DR = (uint8_t)data;
 
   //Ловим момент, когда DR освободился и данные попали в сдвиговый регистр
   wait_event(!((I2C->SR1 & I2C_SR1_TXE) && (I2C->SR1 & I2C_SR1_BTF)), 1);
@@ -105,8 +106,7 @@ t_i2c_status i2c_wr_reg(uint8_t address, uint8_t reg_addr, \
  * @brief Чтение регистра slave-устройства
  * @note Start -> Slave Addr -> Reg. addr -> Restart -> Slave Addr <- data ... -> Stop
  */
-t_i2c_status i2c_rd_reg(uint8_t address, uint8_t reg_addr, \
-                        uint8_t * data, uint8_t length) {
+t_i2c_status i2c_rd_reg(uint8_t address, uint8_t reg_addr, uint16_t * data) {
 
   //Ждем освобождения шины I2C
   wait_event((I2C->SR3 & I2C_SR3_BUSY), 10);
@@ -143,104 +143,32 @@ t_i2c_status i2c_rd_reg(uint8_t address, uint8_t reg_addr, \
   //в режим чтения (установкой младшего бита в 1)
   I2C->DR = address | 0x01;
 
-  //Дальше алгоритм зависит от количества принимаемых байт
-  //N=1
-  if(length == 1){
-    //Запрещаем подтверждение в конце посылки
-    I2C->CR2 &= ~I2C_CR2_ACK;
-    //Ждем подтверждения передачи адреса
-    wait_event(!(I2C->SR1 & I2C_SR1_ADDR), 1);
-
-    //Заплатка из Errata
-    disableInterrupts();
-    //Очистка бита ADDR чтением регистра SR3
-    I2C->SR3;
-
-    //Устанавлием бит STOP
-    I2C->CR2 |= I2C_CR2_STOP;
-    //Заплатка из Errata
-    enableInterrupts();
-
-    //Ждем прихода данных в RD
-    wait_event(!(I2C->SR1 & I2C_SR1_RXNE), 1);
-
-    //Читаем принятый байт
-    *data = I2C->DR;
-  }
-  //N=2
-  else if(length == 2){
-    //Бит который разрешает NACK на следующем принятом байте
-    I2C->CR2 |= I2C_CR2_POS;
-    //Ждем подтверждения передачи адреса
-    wait_event(!(I2C->SR1 & I2C_SR1_ADDR), 1);
-    //Заплатка из Errata
-    disableInterrupts();
-    //Очистка бита ADDR чтением регистра SR3
-    I2C->SR3;
-    //Запрещаем подтверждение в конце посылки
-    I2C->CR2 &= (uint8_t)(~I2C_CR2_ACK);
-    //Заплатка из Errata
-    enableInterrupts();
-    //Ждем момента, когда первый байт окажется в DR,
-    //а второй в сдвиговом регистре
-    wait_event(!(I2C->SR1 & I2C_SR1_BTF), 1);
-
-    //Заплатка из Errata
-    disableInterrupts();
-    //Устанавлием бит STOP
-    I2C->CR2 |= I2C_CR2_STOP;
-    //Читаем принятые байты
-    *data++ = I2C->DR;
-    //Заплатка из Errata
-    enableInterrupts();
-    *data = I2C->DR;
-  }
-  //N>2
-  else if(length > 2){
-    //Ждем подтверждения передачи адреса
-    wait_event(!(I2C->SR1 & I2C_SR1_ADDR), 1);
-
-    //Заплатка из Errata
-    disableInterrupts();
-
-    //Очистка бита ADDR чтением регистра SR3
-    I2C->SR3;
-
-    //Заплатка из Errata
-    enableInterrupts();
-
-    I2C_timeout = 10; // 10 ms ???
-    while (length-- > 3 && I2C_timeout) {
-      //Ожидаем появления данных в DR и сдвиговом регистре
-      wait_event(!(I2C->SR1 & I2C_SR1_BTF), 1);
-      //Читаем принятый байт из DR
-      *(data++) = I2C->DR;
-    }
-    //Время таймаута вышло
-    if(!I2C_timeout) return I2C_TIMEOUT;
-
-    //Осталось принять 3 последних байта
-    //Ждем, когда в DR окажется N-2 байт, а в сдвиговом регистре
-    //окажется N-1 байт
-    wait_event(!(I2C->SR1 & I2C_SR1_BTF), 1);
-    //Запрещаем подтверждение в конце посылки
-    I2C->CR2 &= (uint8_t)(~I2C_CR2_ACK);
-    //Заплатка из Errata
-    disableInterrupts();
-    //Читаем N-2 байт из RD, тем самым позволяя принять в сдвиговый
-    //регистр байт N, но теперь в конце приема отправится посылка NACK
-    *(data++) = I2C->DR;
-    //Посылка STOP
-    I2C->CR2 |= I2C_CR2_STOP;
-    //Читаем N-1 байт
-    *(data++) = I2C->DR;
-    //Заплатка из Errata
-    enableInterrupts();
-    //Ждем, когда N-й байт попадет в DR из сдвигового регистра
-    wait_event(!(I2C->SR1 & I2C_SR1_RXNE), 1);
-    //Читаем N байт
-    *(data++) = I2C->DR;
-  }
+  //Отправка двух байт данных
+  //Бит который разрешает NACK на следующем принятом байте
+  I2C->CR2 |= I2C_CR2_POS;
+  //Ждем подтверждения передачи адреса
+  wait_event(!(I2C->SR1 & I2C_SR1_ADDR), 1);
+  //Заплатка из Errata
+  disableInterrupts();
+  //Очистка бита ADDR чтением регистра SR3
+  I2C->SR3;
+  //Запрещаем подтверждение в конце посылки
+  I2C->CR2 &= (uint8_t)(~I2C_CR2_ACK);
+  //Заплатка из Errata
+  enableInterrupts();
+  //Ждем момента, когда первый байт окажется в DR,
+  //а второй в сдвиговом регистре
+  wait_event(!(I2C->SR1 & I2C_SR1_BTF), 1);
+
+  //Заплатка из Errata
+  disableInterrupts();
+  //Устанавлием бит STOP
+  I2C->CR2 |= I2C_CR2_STOP;
+  //Читаем принятые байты
+  *data = I2C->DR << 8;
+  //Заплатка из Errata
+  enableInterrupts();
+  *data |= I2C->DR;
 
   //Ждем отправки СТОП посылки
   wait_event((I2C->CR2 & I2C_CR2_STOP), 1);

+ 8 - 5
lib/i2c.h

@@ -4,10 +4,16 @@
 
 #include "stm8s.h"
 
+#define I2C_FAST        1
 #define F_MASTER_MHZ    16UL
 #define F_MASTER_HZ     16000000UL
+#ifdef I2C_FAST
+//400 кГц
+#define F_I2C_HZ        400000UL
+#else
 //100 кГц
 #define F_I2C_HZ        100000UL
+#endif // I2C_FAST
 
 //Результат выполнения операции с i2c
 typedef enum {
@@ -20,11 +26,8 @@ typedef enum {
 extern void i2c_master_init(void);
 
 // Запись регистра slave-устройства
-extern t_i2c_status  i2c_wr_reg(uint8_t address, uint8_t reg_addr, \
-                                const uint8_t * data, uint8_t length);
+extern t_i2c_status  i2c_wr_reg(uint8_t address, uint8_t reg_addr, uint16_t data);
 
 // Чтение регистра slave-устройства
-extern t_i2c_status  i2c_rd_reg(uint8_t address, uint8_t reg_addr, \
-                                uint8_t * data, uint8_t length);
-
+extern t_i2c_status  i2c_rd_reg(uint8_t address, uint8_t reg_addr, uint16_t * data);
 #endif // I2C_H

+ 69 - 109
lib/ina219.c

@@ -21,117 +21,46 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "INA219.h"
 #include "i2c.h"
 
-static uint8_t inaAddress;
-static uint16_t currentLSB, powerLSB;
-static uint16_t vShuntMax;
-static uint16_t vBusMax;
-static uint16_t Rshunt;
+static uint16_t vShuntMax; // millivolt
+static uint16_t vBusMax; // millivolt
+static uint16_t rShunt; // milliohms
 
-/**
-  * Configure I2C, INA219
-  */
-void INA219_Config(INA219_InitTypeDef * INA219_InitStruct) {
-  uint16_t config;
-
-  /** INA219 configure */
-  config  = INA219_InitStruct->INA219_RST;
-  config |= INA219_InitStruct->INA219_BVR;
-  config |= INA219_InitStruct->INA219_PG;
-  config |= INA219_InitStruct->INA219_BADC;
-  config |= INA219_InitStruct->INA219_SADC;
-  config |= INA219_InitStruct->INA219_MODE;
-
-  inaAddress = INA219_InitStruct->INA219_Addr;
-
-  switch(INA219_InitStruct->INA219_BVR) {
-  case INA219_RANGE_32V:
-    vBusMax = 32000;
-    break;
-  case INA219_RANGE_16V:
-    vBusMax = 16000;
-    break;
-  }
-
-  switch(INA219_InitStruct->INA219_PG) {
-  case INA219_GAIN_320MV:
-    vShuntMax = 320;
-    break;
-  case INA219_GAIN_160MV:
-    vShuntMax = 160;
-    break;
-  case INA219_GAIN_80MV:
-    vShuntMax = 80;
-    break;
-  case INA219_GAIN_40MV:
-    vShuntMax = 40;
-    break;
-  }
-
-  I2C_Write_Transaction(inaAddress, INA219_REG_CONFIG, config);
-}
+static uint8_t flagCNVR; // Conversion Ready
+static uint8_t flagOVF; // Math Overflow Flag
 
-/**
-  * @brief  Fills each INA219_InitStruct member with its default value.
-  * @param  INA219_InitStruct: pointer to a INA219_InitTypeDef structure which will
-  *         be initialized.
-  * @retval None
-  */
-void INA219_StructInit(INA219_InitTypeDef * INA219_InitStruct) {
-  /* Reset INA219 init structure parameters values */
-  INA219_InitStruct->INA219_Addr = INA219_ADDRESS;
-  INA219_InitStruct->INA219_RST  = INA219_RESET_OFF;
-  INA219_InitStruct->INA219_BVR  = INA219_RANGE_32V;
-  INA219_InitStruct->INA219_PG   = INA219_GAIN_320MV;
-  INA219_InitStruct->INA219_BADC = INA219_BUS_RES_12BIT;
-  INA219_InitStruct->INA219_SADC = INA219_SHUNT_RES_12BIT;
-  INA219_InitStruct->INA219_MODE = INA219_MODE_SHUNT_BUS_CONT;
-}
+static t_i2c_status status = I2C_SUCCESS;
 
 /**
-  * Calculate calibration values.
-  * rShuntValue in miliohms, iMaxExpected in miliampers.
-  */
-void INA219_Calibrate(void) {
-  uint16_t calibrationValue;
-  /* uint64_t tmp; */
-
-  Rshunt = CURRENT_SHUNT_RESISTENCE; // in milli ohms
-
-  /*
-  tmp = iMaxExpected * 1000UL;
-  currentLSB = (uint16_t)((tmp + 16384) / 32768); // uA
-  powerLSB = (uint16_t)(((tmp * 20) + 16384) / 32768); // uW
-
-  tmp = ((tmp * rShuntValue * 1000UL) + 16384) / 32768UL;
-  calibrationValue = (uint16_t)((40960000000UL + (tmp >> 1)) / tmp);
+  * Configure I2C, INA219
   */
+void INA219_Config(void) {
+  uint16_t config;
 
-  /**
-   * Íàõåð òàêèå ðàñ÷¸òû...
-   * ôîðìóëû èç ìàíóàëà:
-   * Current_LSB = Maximum Expected Current / 2^15
-   * Power_LSB = 20 * Current_LSB
-   * Calibration_Value = trunc( 0.04096 / (Current_LSB * Rshunt) )
-   */
+  vBusMax = 32000; // !!! Maximum input voltage only 26V !!!
+  vShuntMax = 80; // !! for shunt 10 mOhm and maximum 8A input current
+  rShunt = CURRENT_SHUNT_RESISTANCE; // in mOhm
 
-  /* íàãðóçêà 50Âò, ìàêñ òîê 4, øóíò ó íàñ 20 ìÎ,
-     Çíà÷åíèÿ LSB â ìèêðîàìïåðàõ è ìèêðîâàòàõ äëÿ äàëüíåéøèõ ðàñ÷¸òîâ */
-  currentLSB = 122; // 4000000 uA / 32768
-  powerLSB = 2440;
+  /** INA219 configure */
+  config  = INA219_RESET_OFF; // INA219_RST
+  config |= INA219_RANGE_32V; // INA219_BVR
+  config |= INA219_GAIN_80MV; // INA219_PG
+  config |= INA219_BUS_RES_12BIT_128S; // INA219_BADC
+  config |= INA219_SHUNT_RES_12BIT_128S; //INA219_SADC
+  config |= INA219_MODE_SHUNT_BUS_CONT; //INA219_MODE
 
-  calibrationValue = 16777; // 0.04096 / ((4/32768) * 0.02)
+  i2c_wr_reg(INA219_ADDRESS, INA219_REG_CONFIG, config);
 
-  I2C_Write_Transaction(inaAddress, INA219_REG_CALIBRATION, calibrationValue);
+  i2c_wr_reg(INA219_ADDRESS, INA219_REG_CALIBRATION, CALIBRATION_VALUE);
 }
 
 /** */
 uint16_t getMaxPossibleCurrent(void) {
-  return (((1000 * vShuntMax) + (Rshunt>>1)) / Rshunt);
+  return (((1000 * vShuntMax) + (rShunt>>1)) / rShunt);
 }
 
 /** */
 uint16_t getMaxCurrent(void) {
-  uint16_t maxCurrent = ((currentLSB * 32767) + 500) / 1000;
+  uint16_t maxCurrent = ((CURRENT_LSB * 32767) + 500) / 1000;
   uint16_t maxPossible = getMaxPossibleCurrent();
 
   if (maxCurrent > maxPossible) {
@@ -143,7 +72,7 @@ uint16_t getMaxCurrent(void) {
 
 /** */
 uint16_t getMaxShuntVoltage(void) {
-  uint16_t maxVoltage = ((getMaxCurrent() * Rshunt) + 500) / 1000;
+  uint16_t maxVoltage = ((getMaxCurrent() * rShunt) + 500) / 1000;
 
   if (maxVoltage >= vShuntMax) {
     return vShuntMax;
@@ -159,23 +88,36 @@ uint32_t getMaxPower(void) {
 
 /** */
 uint16_t readBusCurrent(void) {
-  uint16_t current;
+  uint32_t current;;
   int16_t tmp;
 
-  I2C_Read_Transaction(inaAddress, INA219_REG_CURRENT, (uint16_t *)&tmp);
+  status = i2c_rd_reg(INA219_ADDRESS, INA219_REG_CURRENT, (uint16_t *)&tmp);
+  if (status != I2C_SUCCESS) {
+    return 9999;
+  }
+
   if (tmp < 0) {
     tmp = - tmp;
   }
-  current = (uint16_t)(((tmp * currentLSB) + 500) / 1000);
+  current = tmp;
+  current *= CURRENT_LSB;
+  current += 500;
+  current /= 1000;
 
-  return current;
+  return (uint16_t)current;
 }
 
 /** */
 uint32_t readBusPower(void) {
-  uint16_t power;
-  I2C_Read_Transaction(inaAddress, INA219_REG_POWER, &power);
-  return (((power * powerLSB) + 500) / 1000);
+  uint32_t power;
+  uint16_t tmp;
+
+  i2c_rd_reg(INA219_ADDRESS, INA219_REG_POWER, &tmp);
+  power = tmp;
+  power *= POWER_LSB;
+  power += 500;
+  power /= 1000;
+  return power;
 }
 
 /**
@@ -183,7 +125,10 @@ uint32_t readBusPower(void) {
   */
 int16_t readShuntVoltage(void) {
   uint16_t shvolt;
-  I2C_Read_Transaction(inaAddress, INA219_REG_SHUNTVOLTAGE, &shvolt);
+  status = i2c_rd_reg(INA219_ADDRESS, INA219_REG_SHUNTVOLTAGE, &shvolt);
+  if (status != I2C_SUCCESS) {
+    return 999;
+  }
   return shvolt;
 }
 
@@ -192,14 +137,29 @@ int16_t readShuntVoltage(void) {
   */
 uint16_t readBusVoltage(void) {
   uint16_t volt;
-  I2C_Read_Transaction(inaAddress, INA219_REG_BUSVOLTAGE, &volt);
+
+  flagCNVR = 0;
+  flagOVF = 0;
+
+  status = i2c_rd_reg(INA219_ADDRESS, INA219_REG_BUSVOLTAGE, &volt);
+  if (status != I2C_SUCCESS) {
+    return 65535;
+  }
+
+  if ((volt & 0x0001) != 0) {
+    flagOVF = 1;
+  }
+  if ((volt & 0x0002) != 0) {
+    flagCNVR = 1;
+  }
+
   return ((volt >> 3) * 4);
 }
 
 ina219_bvr_t getRange(void) {
   uint16_t value;
 
-  I2C_Read_Transaction(inaAddress, INA219_REG_CONFIG, &value);
+  i2c_rd_reg(INA219_ADDRESS, INA219_REG_CONFIG, &value);
   value &= 0x2000;
   value >>= 13;
 
@@ -209,7 +169,7 @@ ina219_bvr_t getRange(void) {
 ina219_pg_t getGain(void) {
   uint16_t value;
 
-  I2C_Read_Transaction(inaAddress, INA219_REG_CONFIG, &value);
+  i2c_rd_reg(INA219_ADDRESS, INA219_REG_CONFIG, &value);
   value &= 0x1800;
   value >>= 11;
 
@@ -219,7 +179,7 @@ ina219_pg_t getGain(void) {
 ina219_badc_t getBusRes(void) {
   uint16_t value;
 
-  I2C_Read_Transaction(inaAddress, INA219_REG_CONFIG, &value);
+  i2c_rd_reg(INA219_ADDRESS, INA219_REG_CONFIG, &value);
   value &= 0x0780;
   value >>= 7;
 
@@ -229,7 +189,7 @@ ina219_badc_t getBusRes(void) {
 ina219_sadc_t getShuntRes(void) {
   uint16_t value;
 
-  I2C_Read_Transaction(inaAddress, INA219_REG_CONFIG, &value);
+  i2c_rd_reg(INA219_ADDRESS, INA219_REG_CONFIG, &value);
   value &= 0x0078;
   value >>= 3;
 
@@ -239,7 +199,7 @@ ina219_sadc_t getShuntRes(void) {
 ina219_mode_t getMode(void) {
   uint16_t value;
 
-  I2C_Read_Transaction(inaAddress, INA219_REG_CONFIG, &value);
+  i2c_rd_reg(INA219_ADDRESS, INA219_REG_CONFIG, &value);
   value &= 0x0007;
 
   return (ina219_mode_t)value;

+ 26 - 8
lib/ina219.h

@@ -21,12 +21,25 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef INA219_h
 #define INA219_h
 
-#include "stm32f0xx.h"
+#include "stm8s.h"
 
-#define CURRENT_SHUNT_RESISTENCE    20
-#define INA219_ADDRESS              (uint8_t)(0x40<<1)
+#define CURRENT_SHUNT_RESISTANCE    10
+#define INA219_ADDRESS              (uint8_t)(0x40 << 1)
 #define INA219_ADDR_RD              (INA219_ADDRESS | 0x01)
 
+/**
+ * Calibration value -- ôîðìóëû èç ìàíóàëà:
+ * Current_LSB = Maximum Expected Current / 2^15
+ * Power_LSB = 20 * Current_LSB
+ * Calibration_Value = trunc( 0.04096 / (Current_LSB * Rshunt) )
+ */
+// 8000000 uA / 32768
+#define CURRENT_LSB                 244
+#define POWER_LSB                   4880
+// 0.04096 / ((8 A/32768) * 0.01 Ohm)
+#define CALIBRATION_VALUE           16777
+
+
 /* INA219 Registers */
 #define INA219_REG_CONFIG           0x00
 #define INA219_REG_SHUNTVOLTAGE     0x01
@@ -60,7 +73,15 @@ typedef enum
   INA219_BUS_RES_9BIT         = 0x0000,
   INA219_BUS_RES_10BIT        = 0x0080,
   INA219_BUS_RES_11BIT        = 0x0100,
-  INA219_BUS_RES_12BIT        = 0x0180
+  INA219_BUS_RES_12BIT        = 0x0180,
+  INA219_BUS_RES_12BIT_1S     = 0x0400,
+  INA219_BUS_RES_12BIT_2S     = 0x0480,
+  INA219_BUS_RES_12BIT_4S     = 0x0500,
+  INA219_BUS_RES_12BIT_8S     = 0x0580,
+  INA219_BUS_RES_12BIT_16S    = 0x0600,
+  INA219_BUS_RES_12BIT_32S    = 0x0680,
+  INA219_BUS_RES_12BIT_64S    = 0x0700,
+  INA219_BUS_RES_12BIT_128S   = 0x0780
 } ina219_badc_t;
 
 typedef enum
@@ -104,10 +125,7 @@ typedef struct {
   ina219_mode_t   INA219_MODE; /* Operating Mode */
 } INA219_InitTypeDef;
 
-void INA219_Config(INA219_InitTypeDef * INA219_InitStruct);
-void INA219_StructInit(INA219_InitTypeDef * INA219_InitStruct);
-
-void INA219_Calibrate(void);
+void INA219_Config(void);
 
 ina219_bvr_t getRange(void);
 ina219_pg_t getGain(void);

+ 0 - 29
lib/list_event.h

@@ -1,29 +0,0 @@
-#pragma once
-#ifndef EVENT_LIST_H
-#define EVENT_LIST_H
-
-/* коды событий */
-typedef enum {
-  eventNull = 0x00,
-  evRTCinterrupt,
-  evButton1Pressed,
-  evButton2Pressed,
-  evButtonAllPressed,
-  evButton1Holded,
-  evButton2Holded,
-  evButtonAllHolded,
-  evMenuWDT
-} es_event_t;
-
-/* коды состояний */
-typedef enum {
-  stNoChange = 0x00,
-  // end
-  stLastState
-} es_state_t;
-
-#ifndef NULL
-  #define NULL ((void*)0)
-#endif
-
-#endif //EVENT_LIST_H

+ 25 - 48
lib/max7219.c

@@ -12,56 +12,33 @@
 
 #include "max7219.h"
 
-#define SPI_PORT        GPIOB
-#define SPI_CS          GPIO_Pin_4
-#define SPI_SCK         GPIO_Pin_5
-#define SPI_MOSI        GPIO_Pin_6
-#define SPI_PINS        (SPI_SCK|SPI_MOSI)
-
 void MAX7219_Config(void) {
-    SPI_DeInit(SPI1);
-    /* Enable clock for SPI */
-    CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, ENABLE);
-    /* Set the MOSI,MISO and SCK at high level */
-    GPIO_ExternalPullUpConfig(SPI_PORT, SPI_PINS, ENABLE);
-    /* Configure LOAD pin */
-    GPIO_Init(SPI_PORT, SPI_CS, GPIO_Mode_Out_PP_High_Fast);
-    GPIO_SetBits(SPI_PORT, SPI_CS);
-    /* Init SPI */
-    SPI_Init(SPI1, SPI_FirstBit_MSB, SPI_BaudRatePrescaler_2, SPI_Mode_Master,
-             SPI_CPOL_High, SPI_CPHA_2Edge, SPI_Direction_1Line_Tx, SPI_NSS_Soft, 0x00);
-    /* SPI Enable */
-    SPI_Cmd(SPI1, ENABLE);
-
-    /* Настройка MAX71219 */
-	MAX7219_WriteData(RegDecodeMode, 0x00);            // все без BCD декодирования
-	MAX7219_WriteData(RegScanLimit, MAX7219_DIGITS);   // сколько цифр используем
-	MAX7219_WriteData(RegIntensity, MAX7219_BRIGHT);   // яркость из 16
-	MAX7219_WriteData(RegPower, MAX7219_ON);           // включили питание
+  /* Настройка MAX71219 */
+  MAX7219_WriteData(RegDecodeMode, 0x00);            // все без BCD декодирования
+  MAX7219_WriteData(RegScanLimit, MAX7219_DIGITS);   // сколько цифр используем
+  MAX7219_WriteData(RegIntensity, MAX7219_BRIGHT);   // яркость из 16
+  MAX7219_WriteData(RegPower, MAX7219_ON);           // включили питание
 
 }
 
-void MAX7219_WriteData(max7219_reg_t reg, uint8_t data)
-{
-    /*!< Wait wait until the completion of the transfer. */
-    while (SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY) == SET) {}
-    /* Down LOAD pin */
-    GPIO_ResetBits(SPI_PORT, SPI_CS);
-
-    /*!< Wait until the transmit buffer is empty */
-    while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET) {}
-    /* Send the register where the data will be stored */
-    //SPI_SendData(SPI1, reg);
-    SPI1->DR = reg; /* Write in the DR register the data to be sent*/
-
-    /*!< Wait until the transmit buffer is empty */
-    while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET) {}
-    /* Send the data to be stored */
-    //SPI_SendData(SPI1, data);
-    SPI1->DR = data; /* Write in the DR register the data to be sent*/
-
-    /*!< Wait wait until the completion of the transfer. */
-    while (SPI_GetFlagStatus(SPI1, SPI_FLAG_BSY) == SET) {}
-    /* Up LOAD pin */
-    GPIO_SetBits(SPI_PORT, SPI_CS);
+void MAX7219_WriteData(max7219_reg_t reg, uint8_t data) {
+  /*!< Wait wait until the completion of the transfer. */
+  while ((SPI->SR & 0x80) != RESET);
+  /* Down LOAD pin */
+  SPI_LOAD_PORT->ODR &= ~(SPI_LOAD);
+
+  /*!< Wait until the transmit buffer is empty */
+  while ((SPI->SR & 0x02) == RESET);
+  /* Send the register where the data will be stored */
+  SPI->DR = reg; /* Write in the DR register the data to be sent*/
+
+  /*!< Wait until the transmit buffer is empty */
+  while ((SPI->SR & 0x02) == RESET);
+  /* Send the data to be stored */
+  SPI->DR = data; /* Write in the DR register the data to be sent*/
+
+  /*!< Wait wait until the completion of the transfer. */
+  while ((SPI->SR & 0x80) != RESET);
+  /* Up LOAD pin */
+  SPI_LOAD_PORT->ODR |= SPI_LOAD;
 }

+ 50 - 55
lib/max7219.h

@@ -17,17 +17,12 @@
 
 /* Includes ------------------------------------------------------------------*/
 #include "stm8s.h"
+#include "board.h"
 
 /* Exported defines ----------------------------------------------------------*/
-#define SYM_DOT   0x10
-
-// symbols Для BCD
-#define MAX7219_CHAR_BLANK	0x0F
-#define MAX7219_CHAR_FULL	  0x88
-
-#define MAX7219_ON			0x01
-#define MAX7219_OFF			0x00
-#define MAX7219_BRIGHT	0x08
+#define MAX7219_ON      0x01
+#define MAX7219_OFF     0x00
+#define MAX7219_BRIGHT  0x08
 
 // used LED digits - 1
 #define MAX7219_DIGITS  7
@@ -35,14 +30,14 @@
 /* Exported types ------------------------------------------------------------*/
 typedef enum _max7219_reg {
   RegNoOp        = 0x00,
-  RegDigit0      = 0x03,
-  RegDigit1      = 0x08,
-  RegDigit2      = 0x02,
-  RegDigit3      = 0x01,
-  RegDigit4      = 0x07,
+  RegDigit0      = 0x01,
+  RegDigit1      = 0x07,
+  RegDigit2      = 0x03,
+  RegDigit3      = 0x06,
+  RegDigit4      = 0x05,
   RegDigit5      = 0x04,
-  RegDigit6      = 0x06,
-  RegDigit7      = 0x05,
+  RegDigit6      = 0x08,
+  RegDigit7      = 0x02,
   RegDecodeMode  = 0x09,
   RegIntensity   = 0x0A,
   RegScanLimit   = 0x0B,
@@ -52,49 +47,49 @@ typedef enum _max7219_reg {
 
 // соответсвие бит сегментам
 typedef enum _max7219_seg {
-  SegA    = 1,
-  SegB    = 3,
-  SegC    = 2,
-  SegD    = 5,
-  SegE    = 6,
-  SegF    = 0,
-  SegG    = 7,
-  SegDP   = 4,
+  SegA  = (uint8_t)(1 << 2),
+  SegB  = (uint8_t)(1 << 6),
+  SegC  = (uint8_t)(1 << 5),
+  SegD  = (uint8_t)(1 << 7),
+  SegE  = (uint8_t)(1 << 3),
+  SegF  = (uint8_t)(1 << 4),
+  SegG  = (uint8_t)(1 << 1),
+  SegDP = (uint8_t)(1 << 0),
 } max7219_seg_t;
 
 // symbols без кодирования
 typedef enum _max7219_sym {
-  Sym_0       = 0x6F,
-  Sym_1       = 0x0C,
-  Sym_2       = 0xEA,
-  Sym_3       = 0xAE,
-  Sym_4       = 0x8D,
-  Sym_5       = 0xA7,
-  Sym_6       = 0xE7,
-  Sym_7       = 0x0E,
-  Sym_8       = 0xEF,
-  Sym_9       = 0xAF,
-  Sym_A       = 0xCF,
-  Sym_b       = 0xE5,
-  Sym_c       = 0xE0,
-  Sym_C       = 0x63,
-  Sym_d       = 0xEC,
-  Sym_E       = 0xE3,
-  Sym_F       = 0xC3,
-  Sym_h       = 0xC5,
-  Sym_H       = 0xCD,
-  Sym_P       = 0xCB,
-  Sym_t       = 0xE1,
-  Sym_u       = 0x64,
-  Sym_U       = 0x6D,
-  Sym_Gradus	= 0x8B,
-  Sym_LGradus	= 0xE4,
-  Sym_Temp	  = 0xE1,
-  Sym_Minus	  = 0x80,
-  Sym_Plus	  = 0xD1,
-  Sym_BLANK	  = 0x00,
-  Sym_FULL	  = 0xFF,
-  Sym_Dot     = 0x10
+  Sym_0       = SegA | SegB | SegC | SegD | SegE | SegF,
+  Sym_1       = SegB | SegC,
+  Sym_2       = SegA | SegB | SegD | SegE | SegG,
+  Sym_3       = SegA | SegB | SegC | SegD | SegG,
+  Sym_4       = SegB | SegC | SegF | SegG,
+  Sym_5       = SegA | SegC | SegD | SegF | SegG,
+  Sym_6       = SegA | SegC | SegD | SegE | SegF | SegG,
+  Sym_7       = SegA | SegB | SegC,
+  Sym_8       = SegA | SegB | SegC | SegD | SegE | SegF | SegG,
+  Sym_9       = SegA | SegB | SegC | SegD | SegF | SegG,
+  Sym_A       = SegA | SegB | SegC | SegE | SegF | SegG,
+  Sym_b       = SegC | SegD | SegE | SegF | SegG,
+  Sym_c       = SegD | SegE | SegG,
+  Sym_C       = SegA | SegD | SegE | SegF,
+  Sym_d       = SegB | SegC | SegD | SegE | SegG,
+  Sym_E       = SegA | SegD | SegE | SegF | SegG,
+  Sym_F       = SegA | SegE | SegF | SegG,
+  Sym_i       = SegC,
+  Sym_h       = SegC | SegE | SegF | SegG,
+  Sym_H       = SegB | SegC | SegE | SegF | SegG,
+  Sym_n       = SegC | SegE | SegG,
+  Sym_o       = SegC | SegD | SegE | SegG,
+  Sym_P       = SegA | SegB | SegE | SegF | SegG,
+  Sym_t       = SegD | SegE | SegF | SegG,
+  Sym_u       = SegC | SegD | SegE,
+  Sym_U       = SegB | SegC | SegD | SegE | SegF,
+  Sym_Gradus  = SegA | SegB | SegF | SegG,
+  Sym_Minus   = SegG,
+  Sym_BLANK   = 0x00,
+  Sym_FULL    = 0xFF,
+  Sym_Dot     = SegDP
 } max7219_sym_t;
 
 /* Exported constants --------------------------------------------------------*/

+ 2 - 43
lib/rtos.c

@@ -146,24 +146,6 @@ void RTOS_DispatchTask(void)
    }
 }
 
-/******************************************************************************************
- * Òàéìåðíàÿ ñëóæáà ÐÒÎÑ (ïðåðûâàíèå àïïàðàòíîãî òàéìåðà)
- */
-/*
-static void RTOS_Timer(void)
-{
-   uint8_t i;
-
-   for (i=0; i<arrayTail; i++)         // ïðîõîäèì ïî ñïèñêó çàäà÷
-   {
-      if  (TaskArray[i].delay == 0) {  // åñëè âðåìÿ äî âûïîëíåíèÿ èñòåêëî
-         TaskArray[i].run = 1;         // âçâîäèì ôëàã çàïóñêà,
-      } else {
-         TaskArray[i].delay--;         // èíà÷å óìåíüøàåì âðåìÿ
-      }
-   }
-}
-*/
 /**
   * @brief  Inserts a delay time.
   * @param  nTime: specifies the delay time length, in milliseconds.
@@ -178,29 +160,6 @@ void Delay(__IO uint16_t nTime)
   }
 }
 
-/**
-  * @brief  Decrements the TimingDelay variable.
-  * @note   This function should be called in the
-  *         TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler in the stm8l15x_it.c file.
-  *
-  *       // INTERRUPT_HANDLER(TIM2_UPD_OVF_TRG_BRK_USART2_TX_IRQHandler, 19)
-  *       // {
-  *           // TimingDelay_Decrement();
-  *           // TIM2_ClearITPendingBit(TIM2_IT_Update);
-  *
-  *       // }
-  * @param  None
-  * @retval None
-  */
-/*
-static void TimingDelay_Decrement(void)
-{
-  if (TimingDelay != 0x00)
-  {
-    TimingDelay--;
-  }
-}
-*/
 /**
   * @brief TIM4 Update/Overflow/Trigger Interrupt routine.
   * @param  None
@@ -216,12 +175,12 @@ INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler,23)
     I2C_timeout --;
    }
 
-   /* TimingDelay_Decrement() */
+   /* Decrements the TimingDelay variable */
    if (TimingDelay > 0) {
       TimingDelay --;
    }
 
-   /* RTOS_Timer() */
+   /* Òàéìåðíàÿ ñëóæáà ÐÒÎÑ */
    uint8_t i;
    for (i=0; i<arrayTail; i++) {       // ïðîõîäèì ïî ñïèñêó çàäà÷
       if  (TaskArray[i].delay == 0) {  // åñëè âðåìÿ äî âûïîëíåíèÿ èñòåêëî

+ 7 - 10
lib/rtos.h

@@ -30,32 +30,29 @@
 #define  ENABLE_INTERRUPT enableInterrupts()
 #define DISABLE_INTERRUPT disableInterrupts()
 
-/******************************************************************************************
+/**
  * Ñòðóêòóðà çàäà÷è
  */
 typedef struct task
 {
-   void (*pFunc) (void); // óêàçàòåëü íà ôóíêöèþ
-   uint16_t delay;       // çàäåðæêà ïåðåä ïåðâûì çàïóñêîì çàäà÷è
-   uint16_t period;      // ïåðèîä çàïóñêà çàäà÷è
-   uint8_t run;          // ôëàã ãîòîâíîñòè çàäà÷è ê çàïóñêó
+  void (*pFunc) (void); // óêàçàòåëü íà ôóíêöèþ
+  uint16_t delay;       // çàäåðæêà ïåðåä ïåðâûì çàïóñêîì çàäà÷è
+  uint16_t period;      // ïåðèîä çàïóñêà çàäà÷è
+  uint8_t run;          // ôëàã ãîòîâíîñòè çàäà÷è ê çàïóñêó
 } task;
 
-/******************************************************************************************
+/**
  * Ïåðåìåííûå
  */
-#define USE_RTOS  1
 
-/******************************************************************************************
+/**
  * Ïðîòîòèïû ôóêíöèé
  */
 void RTOS_Init (void);
 void RTOS_SetTask (void (*taskFunc)(void), uint16_t taskDelay, uint16_t taskPeriod);
 void RTOS_DeleteTask (void (*taskFunc)(void));
 void RTOS_DispatchTask (void);
-//void RTOS_Timer(void);
 
 void Delay(__IO uint16_t nTime);
-//void TimingDelay_Decrement(void);
 
 #endif /* __RTOS_H */

+ 761 - 11
src/main.c

@@ -1,9 +1,9 @@
 /**
   ******************************************************************************
-  * @file    Project/main.c 
+  * @file    Project/main.c
   * @author  "Vladimir N. Shilov" <shilow@ukr.net>
-  * @version V0.0.1
-  * @date    18-December-2018
+  * @version v.0.4
+  * @date    08-July-2019
   * @brief   Main program body
    ******************************************************************************
   * @attention
@@ -14,27 +14,777 @@
   * this stuff is worth it, you can buy me a beer in return.   Shilov V.N.
   *
   ******************************************************************************
-  */ 
+  */
 
 
 /* Includes ------------------------------------------------------------------*/
 #include "stm8s.h"
+#include "board.h"
+#include "rtos.h"
+#include "max7219.h"
+#include "i2c.h"
+#include "ina219.h"
+
+/* Private define ------------------------------------------------------------*/
+// кнопка считается нажатой через BTN_FACTOR * BTN_SCAN_PERIOD ms
+#define BTN_SCAN_PERIOD 10
+#define BTN_FACTOR      5
+
+/* Private typedef -----------------------------------------------------------*/
+typedef enum _mode_led {
+  dispNoState = 0x00,
+  displayV,
+  displayI,
+  displayP,
+  displayCI,
+  displayCP,
+  displaySh,
+  displayT
+} mode_led_t;
+
+typedef enum _events {
+  eventNoEvent  = 0x00,
+  eventShortPress,
+  eventLongPress
+} event_t;
+
+typedef enum _button_name {
+  S1 = 0x00,
+  S2 = 0x01
+} button_name;
+
+typedef struct _button_pin {
+  GPIO_TypeDef *    port;
+  GPIO_Pin_TypeDef  pin;
+} button_t;
+
+/* Private constants ---------------------------------------------------------*/
+// перевод числа 0-7 в номер индикатора
+const static max7219_reg_t digitPosition[8] = {
+  RegDigit0, RegDigit1, RegDigit2, RegDigit3,
+  RegDigit4, RegDigit5, RegDigit6, RegDigit7
+};
+// перевод значения 0x00 - 0x0F в код индикатора
+const static max7219_sym_t digitValue[16] = {
+  Sym_0, Sym_1, Sym_2, Sym_3, Sym_4, Sym_5, Sym_6, Sym_7,
+  Sym_8, Sym_9, Sym_A, Sym_b, Sym_c, Sym_d, Sym_E, Sym_F
+};
+// определения пинов кнопок
+const static button_t Button[BUTTON_NUM] = {
+  {BUTTON1_PORT, BUTTON1_PIN},
+  {BUTTON2_PORT, BUTTON2_PIN},
+};
+
+/* Private variables ---------------------------------------------------------*/
+static uint16_t Voltage;
+static int16_t  ShuntV;
+static uint16_t Current;
+static uint32_t Power;
+static uint32_t CapacityAH = 0;
+static uint32_t CapacityWH = 0;
+static struct _timer {
+  uint8_t hh;
+  uint8_t mm;
+  uint8_t ss;
+} Timer;
+
+static uint8_t btn1Cnt;
+static uint8_t btn2Cnt;
+
+static mode_led_t modeTopLine, modeBotLine;
 
-/* Private defines -----------------------------------------------------------*/
 /* Private function prototypes -----------------------------------------------*/
-/* Private functions ---------------------------------------------------------*/
+static void boardInit(void);
+
+static void showValue(uint32_t val, uint8_t pos);
+static void showU(uint8_t pos);
+static void showI(uint8_t pos);
+static void showP(uint8_t pos);
+static void showCI(uint8_t pos);
+static void showCP(uint8_t pos);
+static void showSH(uint8_t pos);
+static void showT(uint8_t pos);
+
+static void showLabelU(uint8_t pos);
+static void showLabelI(uint8_t pos);
+static void showLabelP(uint8_t pos);
+static void showLabelAH(uint8_t pos);
+static void showLabelWH(uint8_t pos);
+static void showLabelSH(uint8_t pos);
+static void showLabelT(uint8_t pos);
+
+static void displayMode(mode_led_t * disp, event_t event, uint8_t pos);
+
+static void blankLine(uint8_t pos);
+
+/* RTOS function prototypes -----------------------------------------------*/
+static void readINAValues(void);
+static void calculateValues(void);
+static void showTopLineU(void);
+static void showTopLineI(void);
+static void showTopLineP(void);
+static void showTopLineAH(void);
+static void showTopLineWH(void);
+static void showTopLineSH(void);
+static void showTopLineT(void);
+static void showBotLineU(void);
+static void showBotLineI(void);
+static void showBotLineP(void);
+static void showBotLineAH(void);
+static void showBotLineWH(void);
+static void showBotLineSH(void);
+static void showBotLineT(void);
+
+static void blankTopLine(void);
+static void blankBotLine(void);
+
+static void btnScan(void);
+static void btnTest(button_t const *btn, uint8_t *pressCount, void (*taskShortPress)(void), void (*taskLongPress)(void));
+static void btn1Short(void);
+static void btn1Long(void);
+static void btn2Short(void);
+static void btn2Long(void);
 
 void main(void)
 {
+  /* Board Configuration */
+  boardInit();
+
+  /* RTOS Configuration */
+  RTOS_Init();
+  enableInterrupts();
+
+  /* MAX7219 Configuration */
+  MAX7219_Config();
+  blankTopLine();
+  blankBotLine();
+
+  /* I2C Configuration */
+  i2c_master_init();
+
+  /* INA219 Configuration */
+  INA219_Config();
+
+  /* ROTS tasks */
+  RTOS_SetTask(btnScan, 0, BTN_SCAN_PERIOD);
+  RTOS_SetTask(readINAValues, 69, 250);
+  RTOS_SetTask(calculateValues, 70, 1000);
+  RTOS_SetTask(showTopLineU, 71, 250);
+  RTOS_SetTask(showBotLineI, 72, 250);
+
+  modeTopLine = displayV;
+  modeBotLine = displayI;
+
   /* Infinite loop */
-  while (1)
-  {
+  while (1) {
+    RTOS_DispatchTask();
+    wfi();
   }
-  
+
 }
 
-#ifdef USE_FULL_ASSERT
+/* Private functions ---------------------------------------------------------*/
+static void boardInit(void) {
+  /* Насколько я понял, для частот выше 16МГц нужно вводить задержку при работе с FLASH:
+    - Before using the HSE clock make sure that the "Flash_Wait_States" is set to 1.
+    - To do so :
+     - with STVD (menu: Debug Instrument -> MCU configuration -> Options)
+     - with EWSTM8 (menu: ST-LINK -> Option bytes ->Flash_Wait_States: 1)
+  */
+
+  ErrorStatus status = ERROR;
+
+  /* Initialization of the clock to 16MHz */
+  CLK->CKDIVR = 0x00;
+
+  /* Disable clock of unused peripherial */
+  CLK->PCKENR1 = (uint8_t)(~CLK_PCKENR1_UART1);
+  CLK->PCKENR2 = (uint8_t)(~(CLK_PCKENR2_CAN | CLK_PCKENR2_ADC | CLK_PCKENR2_AWU));
+
+  /* Configure the system clock to use HSE clock source and to run at Crystal Mhz */
+  status = CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSE, DISABLE, CLK_CURRENTCLOCKSTATE_DISABLE);
+  if (status == ERROR) {
+    /* Configure the system clock to use HSI clock source and to run at 16Mhz */
+    // set FLAG for
+  }
+
+  /* Configure GPIO used for buttons */
+  BUTTON1_PORT->DDR &= (uint8_t)(~(BUTTON1_PIN)); // Input Mode
+  BUTTON1_PORT->CR1 |= (uint8_t)BUTTON1_PIN; // Pull-Up
+  BUTTON1_PORT->CR2 &= (uint8_t)(~(BUTTON1_PIN)); // No Interrupt
+
+  BUTTON2_PORT->DDR &= (uint8_t)(~(BUTTON2_PIN)); // Input Mode
+  BUTTON2_PORT->CR1 |= (uint8_t)BUTTON2_PIN; // Pull-Up
+  BUTTON2_PORT->CR2 &= (uint8_t)(~(BUTTON2_PIN)); // No Interrupt
+
+  /* Init GPIO */
+  /* Set the MOSI,MISO and SCK at high level */
+  SPI_PORT->ODR |= SPI_MOSI;
+  SPI_PORT->DDR |= SPI_PINS;
+  SPI_PORT->CR1 |= SPI_PINS;
+  SPI_PORT->CR2 |= SPI_PINS;
+
+  /* Configure LOAD pin to Push-Pull, High, Fast*/
+  SPI_LOAD_PORT->ODR |= SPI_LOAD;
+  SPI_LOAD_PORT->DDR |= SPI_LOAD;
+  SPI_LOAD_PORT->CR1 |= SPI_LOAD;
+  SPI_LOAD_PORT->CR2 |= SPI_LOAD;
+
+  /* Init SPI */
+  /* SPI_MODE_MASTER, SPI_FIRSTBIT_MSB, SPI_BAUDRATEPRESCALER_2, SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE */
+  SPI->CR1 = 0x04;
+  /* SPI_DATADIRECTION_1LINE_TX, SPI_NSS_SOFT */
+  SPI->CR2 = 0xC0 | 0x02 | 0x01;
+  /* SPI Enable */
+  SPI->CR1 |= SPI_CR1_SPE;
+}
+
+static void btnScan(void) {
+  btnTest(&Button[S1], &btn1Cnt, btn1Short, btn1Long);
+  btnTest(&Button[S2], &btn2Cnt, btn2Short, btn2Long);
+}
+
+/** проверка конкретной кнопки */
+static void btnTest(button_t const *btn, uint8_t *pressCount, void (*taskShortPress)(void), void (*taskLongPress)(void)) {
+  if ((btn->port->IDR & btn->pin) == 0) {
+    if (*pressCount < 255) {
+      *pressCount = *pressCount + 1;
+    }
+/*
+    if (*pressCount ==  BTN_FACTOR) {
+         // short
+      } else if(*pressCount == (BTN_FACTOR * 10)) {
+         // long
+      }
+*/
+  } else {
+    if (*pressCount >= (BTN_FACTOR * 10)) {
+      RTOS_SetTask(taskLongPress, 1, 0); // вызов функции при длительном нажатии
+    } else if (*pressCount >= BTN_FACTOR) {
+      RTOS_SetTask(taskShortPress, 1, 0); // вызов функции при коротком нажатии
+    }
+    *pressCount = 0;
+  }
+}
+
+/** переключение режимов отображения */
+static void displayMode(mode_led_t * disp, event_t event, uint8_t pos) {
+  if (pos != 0) {
+    pos = 4;
+  }
+
+  if (event == eventShortPress) {
+    switch (*disp) {
+    case dispNoState:
+      showLabelU(pos);
+      if (pos == 0) {
+        RTOS_SetTask(showTopLineU, 1000, 250);
+      } else {
+        RTOS_SetTask(showBotLineU, 1000, 250);
+      }
+      *disp = displayV;
+      break;
+    case displayV:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineU);
+        RTOS_SetTask(showTopLineI, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineU);
+        RTOS_SetTask(showBotLineI, 1000, 250);
+      }
+      showLabelI(pos);
+      *disp = displayI;
+      break;
+    case displayI:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineI);
+        RTOS_SetTask(showTopLineP, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineI);
+        RTOS_SetTask(showBotLineP, 1000, 250);
+      }
+      showLabelP(pos);
+      *disp = displayP;
+      break;
+    case displayP:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineP);
+        RTOS_SetTask(showTopLineAH, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineP);
+        RTOS_SetTask(showBotLineAH, 1000, 250);
+      }
+      showLabelAH(pos);
+      *disp = displayCI;
+      break;
+    case displayCI:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineAH);
+        RTOS_SetTask(showTopLineWH, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineAH);
+        RTOS_SetTask(showBotLineWH, 1000, 250);
+      }
+      showLabelWH(pos);
+      *disp = displayCP;
+      break;
+    case displayCP:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineWH);
+        RTOS_SetTask(showTopLineSH, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineWH);
+        RTOS_SetTask(showBotLineSH, 1000, 250);
+      }
+      showLabelSH(pos);
+      *disp = displaySh;
+      break;
+    case displaySh:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineSH);
+        RTOS_SetTask(showTopLineT, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineSH);
+        RTOS_SetTask(showBotLineT, 1000, 250);
+      }
+      showLabelT(pos);
+      *disp = displayT;
+      break;
+    case displayT:
+      if (pos == 0) {
+        RTOS_DeleteTask(showTopLineT);
+        RTOS_SetTask(showTopLineU, 1000, 250);
+      } else {
+        RTOS_DeleteTask(showBotLineT);
+        RTOS_SetTask(showBotLineU, 1000, 250);
+      }
+      showLabelU(pos);
+      *disp = displayV;
+      break;
+    }
+  } else if (event == eventLongPress) {
+    /* КА долгих нажатий */
+    switch (*disp) {
+    case displayCI:
+      if (pos == 0) {
+        RTOS_SetTask(blankTopLine, 0, 500);
+        RTOS_SetTask(showTopLineAH, 250, 500);
+      } else {
+        RTOS_SetTask(blankBotLine, 0, 500);
+        RTOS_SetTask(showBotLineAH, 250, 500);
+      }
+      showLabelAH(pos);
+      break;
+    case displayCP:
+      if (pos == 0) {
+        RTOS_SetTask(blankTopLine, 0, 500);
+        RTOS_SetTask(showTopLineWH, 250, 500);
+      } else {
+        RTOS_SetTask(blankBotLine, 0, 500);
+        RTOS_SetTask(showBotLineWH, 250, 500);
+      }
+      showLabelWH(pos);
+      break;
+    case displayT:
+      if (pos == 0) {
+        RTOS_SetTask(blankTopLine, 0, 500);
+        RTOS_SetTask(showTopLineT, 250, 500);
+      } else {
+        RTOS_SetTask(blankBotLine, 0, 500);
+        RTOS_SetTask(showBotLineT, 250, 500);
+      }
+      showLabelT(pos);
+      break;
+    }
+  }
+}
+
+/** обработчик короткого нажатия первой кнопки */
+static void btn1Short(void) {
+  displayMode(&modeTopLine, eventShortPress, 0);
+}
+
+/** обработчик длинного нажатия первой кнопки */
+static void btn1Long(void) {
+  displayMode(&modeTopLine, eventLongPress, 0);
+}
+
+/** обработчик короткого нажатия второй кнопки */
+static void btn2Short(void) {
+  displayMode(&modeBotLine, eventShortPress, 4);
+}
+
+/** обработчик длинного нажатия второй кнопки */
+static void btn2Long(void) {
+  Timer.ss = 0;
+  Timer.mm = 0;
+  Timer.hh = 0;
+  CapacityAH = 0;
+  CapacityWH = 0;
+  displayMode(&modeBotLine, eventLongPress, 4);
+}
+
+/** Get values from INA219 and store to local variables. */
+static void readINAValues(void) {
+  Voltage = readBusVoltage();
+  ShuntV = readShuntVoltage();
+  Current = readBusCurrent();
+  Power = readBusPower();
+}
 
+/**
+  * Calculate Time, Capacitance AH and WH.
+  */
+static void calculateValues(void) {
+  if (Current != 0) {
+
+    // millivolt * milliamper = microwatt, convert it to milliwatt
+    //Power = ((uint32_t)(v * c) + 500) / 1000;
+
+    CapacityAH += Current;
+    CapacityWH += Power;
+
+    Timer.ss ++;
+    if (Timer.ss > 59) {
+      Timer.ss = 0;
+      Timer.mm ++;
+      if (Timer.mm > 59) {
+        Timer.mm = 0;
+        Timer.hh ++;
+      }
+    }
+  }
+
+}
+
+/**
+  * вывод инфы на верхнем индикаторе
+  */
+static void showTopLineU(void) {
+  showU(0);
+}
+
+static void showTopLineI(void) {
+  showI(0);
+}
+
+static void showTopLineP(void) {
+  showP(0);
+}
+
+static void showTopLineAH(void) {
+  showCI(0);
+}
+
+static void showTopLineWH(void) {
+  showCP(0);
+}
+
+static void showTopLineSH(void) {
+  showSH(0);
+}
+
+static void showTopLineT(void) {
+  showT(0);
+}
+
+static void blankTopLine(void) {
+  blankLine(0);
+}
+
+/**
+  * вывод инфы на нижнем индикаторе
+  */
+static void showBotLineU(void) {
+  showU(4);
+}
+
+static void showBotLineI(void) {
+  showI(4);
+}
+
+static void showBotLineP(void) {
+  showP(4);
+}
+
+static void showBotLineAH(void) {
+  showCI(4);
+}
+
+static void showBotLineWH(void) {
+  showCP(4);
+}
+
+static void showBotLineSH(void) {
+  showSH(4);
+}
+
+static void showBotLineT(void) {
+  showT(4);
+}
+
+static void blankBotLine(void) {
+  blankLine(4);
+}
+
+/**
+  * Output given value to given indicator
+  * param1: value to show, from '0.000' to '999.9'
+  * param2: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showValue(uint32_t val, uint8_t pos) {
+  uint8_t tmp;
+
+  if (val >= 100000) { // 000.0
+    tmp = (uint8_t)(val / 100000);
+    val %= 100000;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+    tmp = (uint8_t)(val / 10000);
+    val %= 10000;
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+    tmp = (uint8_t)(val / 1000);
+    val %= 1000;
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], (digitValue[tmp] | Sym_Dot));
+
+    tmp = (uint8_t)(val / 100);
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+  } else if (val >= 10000) { // 00.00
+    tmp = (uint8_t)(val / 10000);
+    val %= 10000;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+    tmp = (uint8_t)(val / 1000);
+    val %= 1000;
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], (digitValue[tmp] | Sym_Dot));
+
+    tmp = (uint8_t)(val / 100);
+    val %= 100;
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+    tmp = (uint8_t)(val / 10);
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+  } else { // 0.000
+    tmp = (uint8_t)(val / 1000);
+    val %= 1000;
+    MAX7219_WriteData(digitPosition[pos], (digitValue[tmp] | Sym_Dot));
+
+    tmp = (uint8_t)(val / 100);
+    val %= 100;
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+    tmp = (uint8_t)(val / 10);
+    val %= 10;
+    pos ++;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+
+    pos ++;
+    tmp = val;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+  }
+
+}
+
+/**
+  * fill line by blank symbol
+  */
+void blankLine(uint8_t pos) {
+  uint8_t i = pos;
+  for (i=0; i<pos+4; i++) {
+    MAX7219_WriteData(digitPosition[i], Sym_BLANK);
+  }
+}
+
+/**
+  * Output voltage values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showU(uint8_t pos) {
+  showValue(Voltage, pos);
+}
+
+/**
+  * Output current values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showI(uint8_t pos) {
+  showValue(Current, pos);
+}
+
+/**
+  * Output power values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showP(uint8_t pos) {
+  showValue(Power, pos);
+}
+
+/**
+  * Output current capacity values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showCI(uint8_t pos) {
+  showValue(((CapacityAH + 1800) / 3600), pos);
+}
+
+/**
+  * Output power capacity values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showCP(uint8_t pos) {
+  showValue(((CapacityWH + 1800) / 3600), pos);
+}
+
+/**
+  * Output shunt voltage values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  * LSB = 10 uV, may be negative!!!
+  */
+static void showSH(uint8_t pos) {
+  uint32_t val;
+
+  if (ShuntV < 0) {
+    val = - ShuntV;
+  } else {
+    val = ShuntV;
+  }
+  val *= 10;
+  showValue(val, pos);
+}
+
+/**
+  * Output time values to given indicator
+  * param: starting position -- 0 for top
+  * any other for bottom.
+  */
+static void showT(uint8_t pos) {
+  static uint8_t old_sek = 0;
+  uint8_t tmp;
+
+  if (Timer.hh > 0) {
+    tmp = Timer.hh / 10;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+    pos ++;
+    tmp = Timer.hh % 10;
+    if (old_sek == Timer.ss) {
+      MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+    } else {
+      MAX7219_WriteData(digitPosition[pos], (digitValue[tmp] | Sym_Dot));
+    }
+    pos ++;
+    tmp = Timer.mm / 10;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+    pos ++;
+    tmp = Timer.mm % 10;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+  } else {
+    tmp = Timer.mm / 10;
+    MAX7219_WriteData(digitPosition[pos], digitValue[Timer.mm >> 4]);
+    pos ++;
+    tmp = Timer.mm % 10;
+    MAX7219_WriteData(digitPosition[pos], (digitValue[tmp] | Sym_Dot));
+    pos ++;
+    tmp = Timer.ss / 10;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+    pos ++;
+    tmp = Timer.ss % 10;
+    MAX7219_WriteData(digitPosition[pos], digitValue[tmp]);
+  }
+
+  old_sek = Timer.ss;
+}
+
+/**
+  * show label for selected mode
+  */
+static void showLabelU(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_U);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_BLANK);
+}
+
+static void showLabelI(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_1);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_BLANK);
+}
+
+static void showLabelP(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_P);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_BLANK);
+}
+
+static void showLabelAH(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_A);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_H);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+}
+
+static void showLabelWH(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_P);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_H);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+}
+
+static void showLabelSH(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_5);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_h);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+}
+
+static void showLabelT(uint8_t pos) {
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_t);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_Minus);
+  pos ++;
+  MAX7219_WriteData(digitPosition[pos], Sym_BLANK);
+}
+
+#ifdef USE_FULL_ASSERT
 /**
   * @brief  Reports the name of the source file and the source line number
   *   where the assert_param error has occurred.
@@ -43,7 +793,7 @@ void main(void)
   * @retval : None
   */
 void assert_failed(u8* file, u32 line)
-{ 
+{
   /* User can add his own implementation to report the file name and line number,
      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 

+ 10 - 8
src/stm8s_it.c

@@ -5,7 +5,7 @@
   * @version V2.3.0
   * @date    16-June-2017
   * @brief   Main Interrupt Service Routines.
-  *          This file provides template for all peripherals interrupt service 
+  *          This file provides template for all peripherals interrupt service
   *          routine.
    ******************************************************************************
   * @attention
@@ -18,14 +18,14 @@
   *
   *        http://www.st.com/software_license_agreement_liberty_v2
   *
-  * Unless required by applicable law or agreed to in writing, software 
-  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   ******************************************************************************
-  */ 
+  */
 
 /* Includes ------------------------------------------------------------------*/
 #include "stm8s_it.h"
@@ -167,7 +167,7 @@ INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7)
   */
 }
 
-#if defined (STM8S903) || defined (STM8AF622x) 
+#if defined (STM8S903) || defined (STM8AF622x)
 /**
   * @brief External Interrupt PORTF Interrupt routine.
   * @param  None
@@ -255,7 +255,7 @@ INTERRUPT_HANDLER(TIM1_CAP_COM_IRQHandler, 12)
      it is recommended to set a breakpoint on the following instruction.
   */
  }
- 
+
 /**
   * @brief Timer5 Capture/Compare Interrupt routine.
   * @param  None
@@ -455,7 +455,7 @@ INTERRUPT_HANDLER(I2C_IRQHandler, 19)
   * @brief ADC1 interrupt routine.
   * @par Parameters:
   * None
-  * @retval 
+  * @retval
   * None
   */
  INTERRUPT_HANDLER(ADC1_IRQHandler, 22)
@@ -484,12 +484,14 @@ INTERRUPT_HANDLER(TIM6_UPD_OVF_TRG_IRQHandler, 23)
   * @param  None
   * @retval None
   */
+  #ifndef USE_RTOS
  INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
  {
   /* In order to detect unexpected events during development,
      it is recommended to set a breakpoint on the following instruction.
   */
  }
+ #endif // USE_RTOS
 #endif /* (STM8S903) || (STM8AF622x)*/
 
 /**
@@ -509,4 +511,4 @@ INTERRUPT_HANDLER(EEPROM_EEC_IRQHandler, 24)
   */
 
 
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/