ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
27 апреля
721278 Топик полностью
H7H2V (18.12.2016 18:08, просмотров: 301) ответил Evgeny_CD на После лекций Скрипача о важности психологии при программировании только тупой не будет это учитывать. Пока я "отрисовыва карту сущностей".
Основная цель - сделать программу максимально понятной для человека, пусть даже за счет большего размера ОЗУ, ПЗУ и лишних действий МК.  Программа разбивается на блоки взаимодействия с периферией и блок(и), реализующий логику программы, они рисуются на заглавном листе (__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; }
imageimage