Основная цель - сделать программу максимально понятной для человека, пусть даже за счет большего размера ОЗУ, ПЗУ и лишних действий МК. Программа разбивается на блоки взаимодействия с периферией и блок(и), реализующий логику программы, они рисуются на заглавном листе (__Balancer.pdf). Обмен информацией между ними производится через данные и флаги (данные и флаги - глобальные переменные). Данные выделяются красным цветом, флаги - синим и зелёным. Зелёным цветом выделяются флаги, которые сбрасываются отправителем, они, как правило, индицируют режим работы, синим - флаги, которые сбрасываются получателем, индицируют наступление какого-либо события. Данные располагаются между блоками, флаги – на теле блока. При работе с блоком на его рабочий лист копируются все используемые данные и флаги.
Для данных используются Длинные_Мнемоничные_Имена, имена флагов начинаются с fl_ например fl_SystemTick_Balancer_Routine. Если у флага несколько получателей (например, тик от системного таймера), то для каждого получателя будет свой флаг (fl_SystemTick_Получатель_1, fl_SystemTick_Получатель_2, fl_SystemTick_Получатель_3 и т.д.). Это сделано для изолирования работы одного блока от другого.
Слева находятся блоки входов (АЦП, кнопки и т.д.), справа блоки выходов (СИД, ЦАП и т.д.), двунаправленные блоки (UART, SPI) рисуются в удобном для юзера месте.
Направление потока данных и флагов (кто устанавливает, а кто получает) задается стрЕлками.
Блоки периферии реализуют обмен с внешними устройствами и преобразование полученной информации в понятный для человека вид, т.е. не массив вида DevPar[], а отдельные переменные Diagnostic, External_Temperature. Формат переменных любой, главное – понятные имена переменных.
На рабочий лист помещается вся необходимая информация, чтобы не надо было заглядывать ни в какие другие документы.
Логика работы реализуется конечными автоматами.
Кодирование.
Создаются файлы global_variables.c , global_variables.h , в них описываются данные и флаги.
Каждый блок кодируется в своем файле, имя которого совпадает с названием блока, например Low_Chip_UART.c . В этом же файле находятся все функции, относящиеся к блоку, в том числе инициализация.
Итого:
main.c выглядит так
#include "stm32f10x.h"
#include "includes.h"
void main(void)
{
Clk_Initialisation();
Init_ADC();
Ext_UART_Init();
Low_Chip_UART_Init();
High_Chip_UART_Init();
System_Tick_Init ();
LEDs_Init();
Chager_Low_Init();
Chager_High_Init();
Init_Power_Switch();
// MCO_Init();
// Debug_Timer_Init();
while(2,71)
{
LEDs_Routine();
Ext_UART_Routine();
Low_Chip_UART_Routine(); // Debud_Low_Chip_UART_Routine();
High_Chip_UART_Routine();
Chager_Low_Routine();
Chager_High_Routine();
MainCycle();
Power_Switch_Routine();
ADC_Routine();
}
}
Файл Balancer_Low_chip.c выглядит так
#include "stm32f10x.h"
#include <intrinsics.h>
#include "includes.h"
char Low_Chip_Packet[30];
char LTC300_Packet[10];
char Low_Chip_Read_Packet[30];
char Low_Chip_Write_Packet[10];
// ***** Prototypes of local functions *******
void Write_Mode_Low_Chip (char Cell, char Mode);
void Write_Command_Low_Chip (char Command);
char Low_Chip_PEC_Calculation (int Byte);
void Balancer_low_chip_subroutine_1 (void);
void Status_low_chip_routine (void);
void Write_Low_Chip_State (void);
void Low_Chip_Aux_Routine (void);
int Low_Chip_State;
char Busy;
int tmpCommandByte;
char Balancer_Errors_Counter;
int Balancer_MS_Counter;
void Balancer_Low_Chip_Routine (void)
{
static volatile int Balancer_low_chip_routine_state = 0;
switch (Balancer_low_chip_routine_state)
{
case 0: {
Balancer_low_chip_routine_state = 1;
// fl_Balancing_Is_On = 1;
break;
}
case 1: { if ( 1 == fl_Balancer_On)
{ Balancer_low_chip_routine_state = 2;
}
if ( (fl_New_Low_Chip_Mode == 1) && (0 == Busy ) )
{fl_New_Low_Chip_Mode = 0;
// Модифицировать Low_Chip_State
tmpCommandByte = ( (Low_Chip_Cell_Mode << 10) >> (Low_Chip_Cell_Number*2 - 2) );
Low_Chip_State &= ~ ( ( (3 << 10) >> (Low_Chip_Cell_Number*2 - 2) ) ); // обнулить нужные биты
Low_Chip_State |= tmpCommandByte;
}
break;
}
case 2: {
Balancer_low_chip_subroutine_1 ();
if ( 0 == fl_Balancer_On)
{ Balancer_low_chip_routine_state = 1;
Write_Command_Low_Chip(Stop_Balance); // Записать в Low_Chip пакет с некорректным битом чётности - остановить работу
}
break;
}
default: {;}
}
;
}
// static volatile int Balancer_MS_Counter;
void Balancer_low_chip_subroutine_1 (void)
{
static volatile int Balancer_low_chip_subroutine_1_state = 0;
Low_Chip_Aux_Routine();
switch (Balancer_low_chip_subroutine_1_state)
{
case 0: { Balancer_Errors_Counter = 0;
fl_Balancer_Chip_Error = 0;;
Busy = 0;
SPI_Balancer_Low_Chip_Init();
Balancer_low_chip_subroutine_1_state = 1;
break;
}
case 1: {
if ( (fl_New_Low_Chip_Mode == 1) && (0 == Busy ) )
{ fl_New_Low_Chip_Mode = 0 ;
// Модифицировать Low_Chip_State
tmpCommandByte = ( (Low_Chip_Cell_Mode << 10) >> (Low_Chip_Cell_Number*2 - 2) );
Low_Chip_State &= ~ ( ( (3 << 10) >> (Low_Chip_Cell_Number*2 - 2) ) ); // обнулить нужные биты
Low_Chip_State |= tmpCommandByte;
Write_Low_Chip_State(); // Записать Low_Chip_State
}
if ( (fl_New_Low_Chip_Command == 1) && (0 == Busy ) )
{fl_New_Low_Chip_Command = 0;
Write_Command_Low_Chip(Low_Chip_Command);
// Write_Mode_Low_Chip(Low_Chip_Cell_Number, Low_Chip_Cell_Mode );
Balancer_low_chip_subroutine_1_state = 2;
}
if ( (100 <= Balancer_MS_Counter) && (0 == Busy ) )
{Balancer_MS_Counter = 0;
Write_Command_Low_Chip (Readback_Balance); // отослать в чип команду на получение readback
Balancer_low_chip_subroutine_1_state = 10;
}
break;
}
case 2: { if ( 0 == Busy )
{Balancer_low_chip_subroutine_1_state = 3;
Write_Command_Low_Chip(Low_Chip_Command);
}
break;
}
case 3: { if ( 0 == Busy )
{Balancer_low_chip_subroutine_1_state = 4;
Write_Command_Low_Chip(Read_Balance_Status);
}
break;
}
case 4: { if ( 0 == Busy )
{Balancer_low_chip_subroutine_1_state = 5;
Write_Command_Low_Chip(Read_Balance_Status);
}
break;
}
case 5: { if ( 0 == Busy )
{ Readback_Balancer_Low = (Low_Chip_Read_Packet[1] << 8) + Low_Chip_Read_Packet[2];// записать полученный ответ в Readback_Balancer_Low
Balancer_low_chip_subroutine_1_state = 6;
}
break;
}
case 6: { if ( Readback_Balancer_Low == Low_Chip_State )
{ Balancer_low_chip_subroutine_1_state = 1;
}
else { Balancer_Errors_Counter ++;
Balancer_low_chip_subroutine_1_state = 7;
}
break;
}
case 7: { if ( Balancer_Errors_Counter >= 3)
{ fl_Balancer_Chip_Error = 1;
Balancer_low_chip_subroutine_1_state = 1;
}
else { Balancer_low_chip_subroutine_1_state = 2; }
break;
}
case 10: { if ( 0 == Busy )
{ Status_Balancer_Low = (Low_Chip_Read_Packet[1] << 8) + Low_Chip_Read_Packet[2] ; // записать полученный ответ в Status_Balancer_Low ;
Balancer_low_chip_subroutine_1_state = 1;
}
break;
}
default: {Balancer_low_chip_subroutine_1_state = 0;}
}
}
void Low_Chip_Aux_Routine (void)
{
if (1 == fl_SystemTick.Balancer_Low_Chip)
{fl_SystemTick.Balancer_Low_Chip = 0;
Balancer_MS_Counter ++;
}
}
void Write_Low_Chip_State (void) { … }
void Write_Mode_Low_Chip (char Cell, char Mode) { … }
void Write_Command_Low_Chip (char Command) { … }
void SPI3_IRQHandler(void) { … }
char Low_Chip_PEC_Calculation (int Byte) { … }
void SPI_Balancer_Low_Chip_Init (void)
{
////////////////////////////////
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// /////////////////////////////
AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; // SCK
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init( GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // MOSI
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init( GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // MISO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, DISABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // CS
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init( GPIOD, &GPIO_InitStructure);
///////////////////////////////
///////////////////////////
/* SPI1 configuration ------------------------------------------------------*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE);
SPI_I2S_DeInit (SPI3);
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI3, &SPI_InitStructure);
// SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_RXNE, ENABLE);
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
SPI_Cmd(SPI3, ENABLE);
}
Файл System_tick.c выглядит так
#include "stm32f10x.h"
#include <intrinsics.h>
#include "includes.h"
void System_Tick_Init (void)
{
// SysTick end of count event each 0.5s with input clock equal to 9MHz (HCLK/8, default)
// SysTick_Config(4500000);
// SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
SysTick->LOAD=35999;
SysTick->VAL=35999;
SysTick->CTRL= SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/////// ********* Interrupt config **************
NVIC_InitTypeDef NVIC_InitStructure;
// Enable the TIM2 global Interrupt
NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void SysTick_Handler(void)
{
fl_SystemTick.Monitor_chip = 1;
fl_SystemTick.Balancer_Low_Chip = 1;
fl_SystemTick.Main_Cycle = 1;
fl_SystemTick.Leds = 1;
fl_SystemTick_Balancer_Routine = 1;
}
-
- Вставлю свои две копейки: бомж(650 знак., 18.12.2016 20:51)
- Главная проблема всех "графических построителей программ" (и вы опять же на те же грабли) в том, что они создают экземпляры объектов, а нужно создавать типы. =AlexD=(477 знак., 18.12.2016 19:03)