Просмотр исходного кода

Now: read, convert and output values from ADC channels.

Vladimir N. Shilov 9 лет назад
Родитель
Сommit
3bef3e716e
5 измененных файлов с 131 добавлено и 42 удалено
  1. 8 1
      Makefile
  2. 24 0
      ReadMe.txt
  3. 8 1
      VAPC-meter.cbp
  4. 71 40
      src/main.c
  5. 20 0
      src/stm8l15x_it.c

+ 8 - 1
Makefile

@@ -13,6 +13,8 @@ CC=$(EWSTM8_BIN)/iccstm8
 ASM=$(EWSTM8_BIN)/iasmstm8
 LINK=$(EWSTM8_BIN)/ilinkstm8
 HEX=$(EWSTM8_BIN)/ielftool
+FLASHTOOL=C:/STMicroelectronics/st_toolset/stvp/STVP_CmdLine.exe
+FLASHOPT=-Device=STM8L051x3
 
 APP_SRC = src
 LIB_SRC = lib
@@ -94,7 +96,7 @@ vpath %.elf .\$(OUT_DIR)
 vpath %.hex .\$(OUT_DIR)
 
 # Compiler/Assembler flags
-CFLAGS = -e -Oh
+CFLAGS = -e -Oh -D USE_STDPERIPH_DRIVER -D USE_RTOS
 CFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
 CFLAGS += --dlib_config "$(EWSTM8_DIR)\lib\$(LIB_MODEL)"
 CFLAGS += -D NDEBUG -D $(PART)
@@ -137,6 +139,7 @@ DBG_LINKFLAGS += --entry __iar_program_start
 # All
 all: $(OUT_DIR) $(PROJ_S19) $(PROJ_HEX)
 Release: all
+flash: all
 
 # Make build/output directory
 $(OUT_DIR):
@@ -172,3 +175,7 @@ clean:
 	rm -rf $(LIST_DIR)
 	rm -rf $(OBJ_DIR)
 	rm -rf $(OUT_DIR)
+
+# Flash
+flash:
+	@$(FLASHTOOL) $(FLASHOPT) -FileProg=$(OUT_DIR)\\$(PROJ_HEX)

+ 24 - 0
ReadMe.txt

@@ -102,4 +102,28 @@ MAX нужно подключать на +5В, а у меня он был на 
 Добился картинки. Похоже тут какой-то бешенный оптимизатор -- выкинул нах 
 похожую функцию. Нужно учесть на будущее.
 
+---
 Пора браться за ADC.
+
+С учётом входного сопротивления канала напряжения в 100 кОм,
+на частоте 16 МГц нужно использовать 384 цикла измерений,
+а на частоте 8 МГц -- 192 цикла.
+
+Формула расчёта (AN2834 стр. 25) = (циклы / (f_adc * C_adc * ln(2^N+1)) - 1 кОм
+ln(2^13) = 9,01091334728
+C_adc = 16 * 10^-12, т.е.:
+циклы/(f_MHz * 0.00016 * 9,01091334728) - 1 == кОм
+
+С канала тока, по идее, можно мерять на любой скорости.
+
+---
+2016.03.25
+
+Factory_VREFINT у меня == 0x7E, т.е. полное значение 0x067E == 1662
+Если это мерялось при 3В, то получается -- 1.218 В
+
+Предварительный успех -- читаю три канала АЦП и ПДП складывает их в 
+память, преобразовываю и вывожу на индикаторы. Запуск АЦП каждые 10 мсек 
+тригером от Т2. Настройка Т2 пока заклинанием -- понимания нету.
+На очереди -- усреднение результатов, вычисление напряжения питания через 
+опорное напряжение.

+ 8 - 1
VAPC-meter.cbp

@@ -6,7 +6,7 @@
 		<Option makefile_is_custom="1" />
 		<Option pch_mode="2" />
 		<Option compiler="null" />
-		<Option virtualFolders="MAX7219\;StdPerphDrv\;StdPerphDrv\sources\;StdPerphDrv\headers\;RTOS\;" />
+		<Option virtualFolders="MAX7219\;StdPerphDrv\;StdPerphDrv\sources\;StdPerphDrv\headers\;RTOS\;ADC\;" />
 		<Build>
 			<Target title="Release">
 				<Option output="bin/Release/VAPC-meter" prefix_auto="1" extension_auto="1" />
@@ -218,6 +218,13 @@
 		</Unit>
 		<Unit filename="inc/stm8l15x_conf.h" />
 		<Unit filename="inc/stm8l15x_it.h" />
+		<Unit filename="lib/adc.c">
+			<Option compilerVar="CC" />
+			<Option virtualFolder="ADC/" />
+		</Unit>
+		<Unit filename="lib/adc.h">
+			<Option virtualFolder="ADC/" />
+		</Unit>
 		<Unit filename="lib/max7219.c">
 			<Option compilerVar="CC" />
 			<Option virtualFolder="MAX7219/" />

+ 71 - 40
src/main.c

@@ -22,6 +22,7 @@
 #include "stm8l15x.h"
 #include "rtos.h"
 #include "max7219.h"
+#include "adc.h"
 
 /** @addtogroup STM8L15x_StdPeriph_Template
   * @{
@@ -74,14 +75,19 @@ static const max7219_sym_t num[16] = {
 };
 
 /* Private variables ---------------------------------------------------------*/
+extern uint16_t Voltage;
+extern uint16_t Current;
+extern uint16_t RefVolt;
+//extern uint16_t Buffer[];
+
 /* Private function prototypes -----------------------------------------------*/
 static void GPIO_Config(void);
 static void CLK_Config(void);
 
 /* RTOS function prototypes -----------------------------------------------*/
-static void OutLed07(void);
-static void OutLed8f(void);
-static void ToggleLed(void);
+static void ShowTopLineV(void);
+static void ShowTopLineC(void);
+static void ShowBotLine(void);
 
 /* Private functions ---------------------------------------------------------*/
 
@@ -101,13 +107,16 @@ void main(void)
   /* RTOS Configuration */
   RTOS_Init();
 
+   /* ADC Configuration and start */
+  Init_ADC();
+
   /* MAX7219 Configuration */
   MAX7219_Init();
 
   /* ROTS tasks */
-  RTOS_SetTask(OutLed8f,0,10000);
-  RTOS_SetTask(OutLed07,5000,10000);
-  RTOS_SetTask(ToggleLed,1000,1000);
+  RTOS_SetTask(ShowTopLineV,100,4000);
+  RTOS_SetTask(ShowTopLineC,2100,4000);
+  RTOS_SetTask(ShowBotLine,101,100);
 
   /* Infinite loop */
   while (1)
@@ -117,44 +126,66 @@ void main(void)
   }
 }
 
-/* для теста */
-static void OutLed07(void){
-  uint8_t i;
-  for (i=0;i<8;i++) {
-    MAX7219_WriteData(dig[i], num[i]);
-  }
+/*
+ * Output to top indicator line
+ */
+static void ShowTopLineV(void){
+    uint8_t voltage1000 = 0;
+    uint8_t voltage100 = 0;
+    uint8_t voltage10 = 0;
+    uint8_t voltage1 = 0;
+
+    /* Thousands voltage value*/
+    voltage1000 = (uint8_t)(Voltage / 1000);
+    /* Hundreds voltage value */
+    voltage100 = (uint8_t)((Voltage % 1000) / 100);
+    /* Tens voltage value */
+    voltage10 = (uint8_t)((Voltage % 100 ) / 10);
+    /* Ones voltage value */
+    voltage1 = (uint8_t)(Voltage % 10);
+
+    LED_GREEN_ON;
+
+    MAX7219_WriteData(dig[0], num[voltage1000]);
+    MAX7219_WriteData(dig[1], num[voltage100]);
+    MAX7219_WriteData(dig[2], num[voltage10]);
+    MAX7219_WriteData(dig[3], num[voltage1]);
 }
 
-static void OutLed8f(void){
-  uint8_t i;
-  for (i=15;i>7;i--) {
-    MAX7219_WriteData(dig[i-8], num[i]);
-  }
+static void ShowTopLineC(void){
+    LED_GREEN_OFF;
+    uint8_t tmp = Current / 1000;
+    MAX7219_WriteData(dig[0], num[tmp]);
+    tmp = (Current % 1000) / 100;
+    MAX7219_WriteData(dig[1], num[tmp]);
+    tmp = (Current % 100) / 10;
+    MAX7219_WriteData(dig[2], num[tmp]);
+    tmp = Current % 10;
+    MAX7219_WriteData(dig[3], num[tmp]);
 }
 
-static void ToggleLed(void){
-    static uint8_t state=0;
-
-    switch(state){
-    case 0:
-        LED_RED_ON;
-        state = 1;
-        break;
-    case 1:
-        LED_GREEN_ON;
-        state = 2;
-        break;
-    case 2:
-        LED_RED_OFF;
-        state = 3;
-        break;
-    case 3:
-        LED_GREEN_OFF;
-        state = 0;
-        break;
-    default:
-        state = 0;
-    }
+/*
+ * Output to bottom indicator line
+ */
+static void ShowBotLine(void){
+    uint8_t voltage1000 = 0;
+    uint8_t voltage100 = 0;
+    uint8_t voltage10 = 0;
+    uint8_t voltage1 = 0;
+
+    /* Thousands voltage value*/
+    voltage1000 = (uint8_t)(RefVolt / 1000);
+    /* Hundreds voltage value */
+    voltage100 = (uint8_t)((RefVolt % 1000) / 100);
+    /* Tens voltage value */
+    voltage10 = (uint8_t)((RefVolt % 100 ) / 10);
+    /* Ones voltage value */
+    voltage1 = (uint8_t)(RefVolt % 10);
+
+    MAX7219_WriteData(dig[4], num[voltage1000]);
+    MAX7219_WriteData(dig[5], num[voltage100]);
+    MAX7219_WriteData(dig[6], num[voltage10]);
+    MAX7219_WriteData(dig[7], num[voltage1]);
 }
 
 

+ 20 - 0
src/stm8l15x_it.c

@@ -35,8 +35,17 @@
 
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
+/* ADC_RATIO = (( 3.3 * 1000 * 1000 ) + 2048 ) / 4095 */
+#define ADC_RATIO       806UL
+#define ADC_VOLT_RATIO  8864UL
+
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
+extern uint16_t Voltage;
+extern uint16_t Current;
+extern uint16_t RefVolt;
+extern uint16_t Buffer[];
+
 /* Private function prototypes -----------------------------------------------*/
 /* Private functions ---------------------------------------------------------*/
 /* Public functions ----------------------------------------------------------*/
@@ -91,6 +100,17 @@ INTERRUPT_HANDLER(DMA1_CHANNEL0_1_IRQHandler,2)
     /* In order to detect unexpected events during development,
        it is recommended to set a breakpoint on the following instruction.
     */
+
+  /* Calculate voltage value*/
+  Voltage = (Buffer[0] * ADC_VOLT_RATIO) / 1000;
+
+  /* Calculate current value*/
+  Current = (Buffer[1] * ADC_RATIO) / 1000;
+
+  RefVolt = (Buffer[2] * ADC_RATIO) / 1000;
+
+  /* Clear IT Pending Bit */
+  DMA_ClearITPendingBit(DMA1_IT_TC0);
 }
 /**
   * @brief DMA1 channel2 and channel3 Interrupt routine.