Код: Выделить всё
/*
* BESTV424V.cpp
* Created: 21.05.2018
* Author: Plotnikov Andrei.
*/
#define F_CPU 8000000UL //Частота CPU МК.
#include <avr/io.h> //Инклуд для работы с МК.
#include <util/delay.h> //Инклуд для использования задержек _delay_ms(x);
#include <avr/interrupt.h> //Инклуд для работы с прерываниями.
#include <avr/pgmspace.h> //Инклуд для работы с флэш памятью.
#include <avr/eeprom.h> //Инклуд для работы с ЭСППЗУ памятью.
/*_________________BEGIN_TARGET_DEFINE______*/
#define ENABLE_TIM1 TIMSK|= (1<<2)
#define DISABLE_TIM1 TIMSK&= ~(1<<2)
#define ENABLE_POWER PORTC|= (1<<0)
#define DISABLE_POWER PORTC&= ~(1<<0)
#define ENABLE_SM PORTC|= (1<<1)
#define DISABLE_SM PORTC&= ~(1<<1)
#define ENABLE_SB PORTC|= (1<<2)
#define DISABLE_SB PORTC&= ~(1<<2)
#define ENABLE_PW PORTC|= (1<<3)
#define DISABLE_PW PORTC&= ~(1<<3)
#define ENABLE_OW PORTC|= (1<<4)
#define DISABLE_OW PORTC&= ~(1<<4)
/******************Описание DEFINE SPI**********************/
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_MISO 6
#define SPI_MOSI 5
#define SPI_SCK 7
#define SPI_SS 4
/*********Кодировка семи сегментного индикатора.*************/
//________________________*/
#define SEG_PORT TwoOUT.Byte
//__________________Катоды____________________*/
#define SEGA 0
#define SEGB 1
#define SEGC 2
#define SEGD 3
#define SEGE 4
#define SEGF 5
#define SEGG 6
#define SEGH 7
//__________________Аноды_____________________*/
#define ANOD1 OneOUT.Bits.DO0
#define ANOD2 OneOUT.Bits.DO1
#define ANOD3 OneOUT.Bits.DO2
#define ANOD4 OneOUT.Bits.DO3
#define ANOD5 OneOUT.Bits.DO4
#define ANOD6 OneOUT.Bits.DO5
#define DISPLAY_MOD_TIM OneOUT.Bits.DO7
#define DISPLAY_MOD_JOB OneOUT.Bits.DO6
/*****************SETING_DEFINE_BTN_AND_GRC*****************/
#define BTN_LOCK_TIME 100 //время фиксации дребезга
#define BTN_LONG_TIME 2000 //время фиксации длинного нажатия
//**__________________порт чтения кнопок___________________*/
#define BTN_PORT1 PORTA
#define BTN_DDR1 DDRA
#define BTN_PIN1 PINA
#define BTN_PORT2 PORTD
#define BTN_DDR2 DDRD
#define BTN_PIN2 PIND
#define BTN_PORT3 PORTC
#define BTN_DDR3 DDRC
#define BTN_PIN3 PINC
//**________________пины чтения кнопок___________________*/
//________PORTA_____________*/
#define BTN_LINE_RA (1<<0) //Режим РУЧ/АВТ (PA)
#define BTN_LINE_ST (1<<1) //Режим СЧЕТЧИК/ТАЙМЕР
#define BTN_LINE_PR (1<<2) //MOD PROGRAMMING
#define BTN_LINE_EN (1<<3) //BTN_ENTER
#define BTN_LINE_UP (1<<4) //BTN_UP
#define BTN_LINE_DN (1<<5) //BTN_DOWN
#define BTN_LINE_SM (1<<6) //BTN_SW_СМЫКАНИЕ
#define BTN_LINE_SB (1<<7) //BTN_SW_ШТОК_БАРЫ
//________PORTD_____________*/
#define BTN_LINE_S1 (1<<0) //BTN_START_1 (PD)
#define BTN_LINE_S2 (1<<1) //BTN_START_2
#define GRK_LINE_SM (1<<2) //ГЕРКОН_СМЫКАНИЕ
#define BTN_LINE_PW (1<<3) //BTN_ПРЕД_ВЫДУВ
#define BTN_LINE_OW (1<<4) //BTN_ОСНОВНОЙ_ВЫДУВ
#define GRK_LINE_ZM_IP (1<<5) //ГЕРКОН_ЗАМОК_ИСХ.ПОЛОЖЕНИЕ
#define GRK_LINE_ZM_RP (1<<6) //ГЕРКОН_ЗАМОК_РАБ.ПОЛОЖЕНИЕ
#define BTN_LINE_ZM (1<<7) //BTN_SWITCH_ЗАМОК
//________PORTC_____________*/
#define DAT_LINE_PWR (1<<6) //ДАТЧИК_PWR (POWER)
#define BTN_LINE_MOD (1<<7) //BTN_MOD_ZM/NO_ZM
//_______Биты короткого нажатия -> BtnFlags_1_____________*/
#define BTN_SHRT_RA (1<<0) //Режим РУЧ/АВТ
#define BTN_SHRT_ST (1<<1) //Режим СЧЕТЧИК/ТАЙМЕР
#define BTN_SHRT_PR (1<<2) //MOD PROGRAMMING
#define BTN_SHRT_EN (1<<3) //BTN_ENTER
#define BTN_SHRT_UP (1<<4) //BTN_UP
#define BTN_SHRT_DN (1<<5) //BTN_DOWN
#define BTN_SHRT_SM (1<<6) //BTN_SW_СМЫКАНИЕ
#define BTN_SHRT_SB (1<<7) //BTN_SW_ШТОК_БАРЫ
//_______Биты короткого нажатия -> BtnFlags_2______________*/
#define BTN_SHRT_S1 (1<<0) //BTN_START_1
#define BTN_SHRT_S2 (1<<1) //BTN_START_2
#define GRK_SHRT_SM (1<<2) //ГЕРКОН_СМЫКАНИЕ
#define BTN_SHRT_PW (1<<3) //BTN_ПРЕД_ВЫДУВ
#define BTN_SHRT_OW (1<<4) //BTN_ОСНОВНОЙ_ВЫДУВ
#define GRK_SHRT_ZM_IP (1<<5) //ГЕРКОН_ЗАМОК_ИСХ.ПОЛОЖЕНИЕ
#define GRK_SHRT_ZM_RP (1<<6) //ГЕРКОН_ЗАМОК_РАБ.ПОЛОЖЕНИЕ
#define BTN_SHRT_ZM (1<<7) //BTN_SWITCH_ЗАМОК
//_______Биты короткого нажатия -> BtnFlags_3______________*/
//#define DAT_SHRT_PWR (1<<0) //ДАТЧИК_PWR
#define BTN_SHRT_MOD (1<<1) //BTN_MOD_ZM/NO_ZM
//_______Биты длинного нажатия */
#define BTN_LONG_PR (1<<10) //BTN_LONG_PR
#define BTN_LONG_UP (1<<12) //BTN_UP_LONG
#define BTN_LONG_DN (1<<13) //BTN_DOWN_LONG
/*_________________END_TARGET_DEFINE________*/
/***********************************************************/
//________________(глобальные переменные)___________________*/
///////////////////________EEPROM________/////////////////////
uint16_t eepTimeToStartPW EEMEM = 50; //Time*10 = T1 ms
uint16_t eepTimeToStopPW EEMEM = 50; //Time*10 = T2 ms
uint16_t eepTimeOW EEMEM = 50; //Time*10 = T3 ms
uint16_t eepTimeReturn EEMEM = 50; //Time*10 = T4 ms
//uint16_t eepCountProduct EEMEM = 0; //50 это дефолтное значения равное 0.5с.
volatile uint16_t TimeToStartPW=50; //Time*10 = T1 ms
volatile uint16_t TimeToStopPW=50; //Time*10 = T2 ms
volatile uint16_t TimeOW=50; //Time*10 = T3 ms
volatile uint16_t TimeReturn=50; //Time*10 = T4 ms
volatile uint16_t TimeSumm=0; //(Сумма Т1..Т4)*10 = Т5 ms
volatile uint16_t CountProduct=0; // Счетчик циклов(продукции)
volatile uint16_t SetProgProduct=0;
volatile uint8_t FlagOverflowProduct=0; //Флаг Отвечающий за переполннение - (CountProduct > SetProgProduct)
volatile uint16_t BtnFlags_1=0;
volatile uint16_t BtnFlags_2=0;
volatile uint16_t BtnFlags_3=0;
volatile uint8_t AnodCount=0; //Счетчик Анодов Сем.Сег.Идникатора.
volatile uint8_t ModTimer = 0x00; //Режим работы таймера. 0 -> Режим работы таймеров Т1..T4
// 1 -> Режим работы счетчика.
volatile uint16_t CountMS=0; //Переменная счетчик MS
volatile uint8_t FlagsEnDiplay=1; //Флаг для работы с Сем.Сег.Идникатором.
volatile uint8_t ModDebug=0xFF; //Ручной режим работы (отладка)(включен по дефолту)
volatile uint8_t ModAuto=0x00; //Автоматический режим работы (Отключен по дефолту)
volatile uint8_t ModProgramming=0x00; //Режим программирования таймеров.
void InitTimer0_OVF()
{
TCNT0=120; //Прерывания настроено на 1.25ms
TIMSK|=(1<<TOIE0);//Разрешить прерывание по переполнению таймера 0.
TCCR0|=(0<<CS02)|(1<<CS01)|(1<<CS00); //Настройка пред делителя. 100 .clk\256
}
void InitTimer1_OVF()
{
TCCR1B|=(1<<CS12)|(0<<CS11)|(0<<CS10); //Пред делитель
TIMSK|=(1<<TOIE1); //Разрешить прерывание по переполнению таймера 1
//TCNT1=65521;
TCNT1=65505 ; //Начальное значение таймера
}
void SPI_Init(void)
{
/*настройка портов ввода-вывода все выводы, кроме MISO выходы*/
SPI_DDR |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
SPI_PORT |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPCR = (1<<SPE)|(0<<DORD)|(1<<MSTR)|(0<<CPOL)|(0<<CPHA)|(0<<SPR1)|(1<<SPR0);
SPSR = (0<<SPI2X);
}
//--------------------------------------------------------------------------------------------------------------------
//Функции чтения данных о нажатии кнопок
uint16_t MaskGetOne (void)
{
cli();
uint16_t temp1 = BtnFlags_1;
BtnFlags_1 = 0;
sei();
return temp1;
}
uint16_t MaskGetTwo (void)
{
cli();
uint16_t temp2 = BtnFlags_2;
BtnFlags_2 = 0;
sei();
return temp2;
}
uint16_t MaskGetThree (void)
{
cli();
uint16_t temp3 = BtnFlags_3;
BtnFlags_3 = 0;
sei();
return temp3;
}
//-----------------------------------------------------------------------------------------------------------------------
//ФУНКЦИЯ ОБРАБОТКИ НАЖАТИЙ КЛАВИШ (вызывать в прерывании)
//короткое нажатие устанавливает бит BTN_SHRT_X глобальной переменной BtnFlags
//длинное нажатие устанавливает бит BTN_LONG_X глобальной переменной BtnFlags
volatile uint8_t BtPW=0;
volatile uint8_t BtOW=0;
volatile uint8_t BtS1=0;
volatile uint8_t BtS2=0;
volatile uint8_t GrKSM=0;
volatile uint8_t DatPWR=0;
void BtnExe (void)
{
static uint8_t BtnLockBit; //защелка (защита от дребезга)
static uint8_t BtnLockCoun; //счетчик защелки (защита от дребезга)
static uint8_t BtnLongCoun; //счетчик длинного нажатия
static uint8_t BtnLastState_1; //последнее состояние кнопок перед отпусканием
static uint8_t BtnLastState_2; //последнее состояние кнопок перед отпусканием
static uint8_t BtnLastState_3; //последнее состояние кнопок перед отпусканием
uint8_t mask_1 = 0;
uint8_t mask_2 = 0;
uint8_t mask_3 = 0;
if (!(BTN_PIN1 & BTN_LINE_RA)) mask_1 = BTN_SHRT_RA;
if (!(BTN_PIN1 & BTN_LINE_ST)) mask_1 = BTN_SHRT_ST;
if (!(BTN_PIN1 & BTN_LINE_PR)) mask_1 = BTN_SHRT_PR;
if (!(BTN_PIN1 & BTN_LINE_EN)) mask_1 = BTN_SHRT_EN;
if (!(BTN_PIN1 & BTN_LINE_UP)) mask_1 = BTN_SHRT_UP;
if (!(BTN_PIN1 & BTN_LINE_DN)) mask_1 = BTN_SHRT_DN;
if (!(BTN_PIN1 & BTN_LINE_SM)) mask_1 = BTN_SHRT_SM;
if (!(BTN_PIN1 & BTN_LINE_SB)) mask_1 = BTN_SHRT_SB;
if(!(BTN_PIN2 & BTN_LINE_S1)) mask_2 = BTN_SHRT_S1;
if(!(BTN_PIN2 & BTN_LINE_S2)) mask_2 = BTN_SHRT_S2;
if(!(BTN_PIN2 & GRK_LINE_SM)) mask_2 = GRK_SHRT_SM;
if(!(BTN_PIN2 & BTN_LINE_PW)) mask_2 = BTN_SHRT_PW;
if(!(BTN_PIN2 & BTN_LINE_OW)) mask_2 = BTN_SHRT_OW;
if(!(BTN_PIN2 & GRK_LINE_ZM_IP)) mask_2 = GRK_SHRT_ZM_IP;
if(!(BTN_PIN2 & GRK_LINE_ZM_RP)) mask_2 = GRK_SHRT_ZM_RP;
if(!(BTN_PIN2 & BTN_LINE_ZM)) mask_2 = BTN_SHRT_ZM;
//if(!(BTN_PIN3 & DAT_LINE_PWR)) mask_3 = DAT_SHRT_PWR;
if(!(BTN_PIN3 & BTN_LINE_MOD)) mask_3 = BTN_SHRT_MOD;
if((mask_1)||(mask_2)||(mask_3)) //опрос состояния кнопки
{
if (BtnLockCoun < (BTN_LOCK_TIME/10)) //клавиша нажата
{
BtnLockCoun++;
return; //защелка еще не досчитала - возврат
}
BtnLastState_1 = mask_1;
BtnLastState_2 = mask_2;
BtnLastState_3 = mask_3;
BtnLockBit =1;
if ((BtnLockBit)&&(!(BTN_PIN3 & DAT_LINE_PWR))) DatPWR=1;
if ((BtnLockBit)&&(!(BTN_PIN2 & BTN_LINE_PW))) BtPW=1;
if ((BtnLockBit)&&(!(BTN_PIN2 & BTN_LINE_OW))) BtOW=1;
if ((BtnLockBit)&&(!(BTN_PIN2 & BTN_LINE_S1))) BtS1=1;
if ((BtnLockBit)&&(!(BTN_PIN2 & BTN_LINE_S2))) BtS2=1;
if ((BtnLockBit)&&(!(BTN_PIN2 & GRK_LINE_SM))) GrKSM=1;
//нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME/10))
{
return; //возврат, т.к. счетчик длин.нажат. досчитал до максимума еще раньше
}
if (++BtnLongCoun >= (BTN_LONG_TIME/10))
{
if (mask_1)
{
BtnFlags_1|= (BtnLastState_1<<8); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
}
if (mask_2)
{
BtnFlags_2 |= (BtnLastState_2<<8);
}
if (mask_3)
{
BtnFlags_3 |= (BtnLastState_3<<8);
}
}
}
else //клавиша отжата
{
if (BTN_PIN2 & BTN_LINE_PW) BtPW=0;
if (BTN_PIN2 & BTN_LINE_OW) BtOW=0;
if (BTN_PIN2 & BTN_LINE_S1) BtS1=0;
if (BTN_PIN2 & BTN_LINE_S2) BtS2=0;
if (BTN_PIN2 & GRK_LINE_SM) GrKSM=0;
if (BtnLockCoun)
{
BtnLockCoun --;
return; //защелка еще не обнулилась - возврат
}
if (! BtnLockBit) return; //СТАТИЧЕСКИЙ ВОЗВРАТ
BtnLockBit =0; //отжатие зафиксировано
if (BtnLongCoun < (BTN_LONG_TIME/10))
{
if(!(mask_1))
{
BtnFlags_1 |= BtnLastState_1;
} //установка бита короткого нажатия
if (!(mask_2))
{
BtnFlags_2 |= BtnLastState_2;
}
if (!(mask_3))
{
BtnFlags_3 |= BtnLastState_3;
}
}
BtnLongCoun = 0; //сброс счетчика длительности нажатия
}
}
struct UnionBits
{
unsigned DO0: 1;
unsigned DO1: 1;
unsigned DO2: 1;
unsigned DO3: 1;
unsigned DO4: 1;
unsigned DO5: 1;
unsigned DO6: 1;
unsigned DO7: 1;
};
union Byte {
uint8_t Byte;
struct UnionBits Bits;
};
union Byte OneOUT; //аноды
union Byte TwoOUT; //Катоды
union Byte Flags; //Объеденнение битов(флагов) разрешающих мигающих разрядов.
uint8_t SPI_UpdataByte(uint8_t data)
{
uint8_t report;
SPDR = data;
while(!(SPSR & (1<<SPIF)));
report = SPDR;
return report;
}
void SpiUpdateRegister()
{
SPI_PORT &= ~(1<<SPI_SS);
SPI_UpdataByte(OneOUT.Byte);
SPI_UpdataByte(TwoOUT.Byte);
SPI_PORT |= (1<<SPI_SS);
}
void StartInitIO()
{
OneOUT.Byte=0xFF;
TwoOUT.Byte=0x00;
Flags.Byte=0x00;
DISPLAY_MOD_JOB=1;
DISPLAY_MOD_TIM=0;
}
//Функция вывода символов
static void PrintChar (uint8_t Number)
{
switch (Number)
{
case 0:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 1:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 2:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 3:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 4:
SEG_PORT=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 5:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 6:
SEG_PORT=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 7:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
case 8:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 9:
SEG_PORT=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG)|(1<<SEGH);break;
case 99: //OFF Все сегменты
SEG_PORT=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG)|(1<<SEGH);break;
}
if ((ModTimer == 0)&&(AnodCount == 3))
{
SEG_PORT &=~(1<<SEGH);
}
}
volatile uint8_t data[6]={0};
//Функция вывода динамической индикации.
void PrintNumber(uint16_t NeberChar,uint8_t NumberTimers,union Byte FlagsBlink)
{
uint8_t TempResult =0;
for (int i = 0; i < 5; i++)
{
TempResult = NeberChar % 10;
NeberChar = NeberChar / 10;
data[i]=TempResult;
}
AnodCount++;
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
switch (AnodCount)
{
case 1:
if(FlagsBlink.Bits.DO0!=1) //Если флаг == 0, то выводим символ
{
ANOD1=0;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data[0]);
} else
{
if (FlagsBlink.Bits.DO6==1)
{
ANOD1=0;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data[0]);
} else PrintChar(99);
}
break;
case 2:
if (((data[1]+data[2]+data[3]+data[4])!=0)||(ModTimer == 0)||(ModProgramming&&ModTimer))
{
if(FlagsBlink.Bits.DO1!=1)
{
ANOD1=1;ANOD2=0;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data[1]);
}
else
{
if (FlagsBlink.Bits.DO6==1)
{
ANOD1=1;ANOD2=0;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data[1]);
} else PrintChar(99);
}
} else PrintChar(99);
break;
case 3:
if (((data[2]+data[3]+data[4])!=0)|| (ModTimer == 0)||(ModProgramming&&ModTimer))
{
if(FlagsBlink.Bits.DO2!=1)
{
ANOD1=1;ANOD2=1;ANOD3=0;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data[2]);
}
else
{
if (FlagsBlink.Bits.DO6==1)
{
ANOD1=1;ANOD2=1;ANOD3=0;ANOD4=1;ANOD5=1;ANOD6=1;
PrintChar(data[2]);
} else PrintChar(99);
}
} else PrintChar(99);
break;
case 4:
if (((data[3]+data[4])!=0)||(ModProgramming&&ModTimer))
{
if(FlagsBlink.Bits.DO3!=1)
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=0;ANOD5=1;ANOD6=1;
PrintChar(data[3]);
}
else
{
if (FlagsBlink.Bits.DO6==1)
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=0;ANOD5=1;ANOD6=1;
PrintChar(data[3]);
} else PrintChar(99);
}
} else PrintChar(99);
break;
case 5:
if ((data[4]!=0)||(ModProgramming&&ModTimer))
{
if(FlagsBlink.Bits.DO4!=1)
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=0;ANOD6=1;
PrintChar(data[4]);
}
else
{
if (FlagsBlink.Bits.DO6==1)
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=0;ANOD6=1;
PrintChar(data[4]);
} else PrintChar(99);
}
} else PrintChar(99);
break;
case 6:
if (NumberTimers)
{
if(FlagsBlink.Bits.DO5!=1)
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=0;
PrintChar(NumberTimers);
}
else
{
if (FlagsBlink.Bits.DO6==1)
{
ANOD1=1;ANOD2=1;ANOD3=1;ANOD4=1;ANOD5=1;ANOD6=0;
PrintChar(NumberTimers);
} else PrintChar(99);
}
} else PrintChar(99);
AnodCount=0;
break;
}
}
void InitIO_MC(void)
{
DDRA|=0x00; // Config InPut
PORTA|=0x00;
DDRB|=0xFF; // Config OutPut
PORTB=0x00;
DDRC|=(0<<PC7)|(0<<PC6)|(1<<PC5)|(1<<PC4)|(1<<PC3)|(1<<PC2)|(1<<PC1)|(1<<PC0);
PORTC|=0x00;
DDRD|=0x00; // Config IntPut
PORTD|=0x00;
}
volatile uint8_t CountDiv10=200;
volatile uint8_t tempx=3; /////////////////////////////////////////////////
ISR (TIMER0_OVF_vect)
{
TCNT0 =120;
SpiUpdateRegister();
if (tempx==0) {BtnExe();tempx=3;}
tempx--;
if (CountDiv10==0)
{
Flags.Bits.DO6=~Flags.Bits.DO6; //переменная отвечающая за частоту моргания.
CountDiv10=200;
}
CountDiv10--;
FlagsEnDiplay=1;
}
uint8_t FlagOnCountToNULL=0;
//ф() Производит обратный отсчет преременной.
uint8_t ClkCount=10; // переменная делитель отсчета ,при 1 clk=1,
uint16_t CountToNULL(uint16_t TimeVariable) // при 10 clk=10.
{
if (FlagOnCountToNULL)
{
ClkCount--;
if (TimeVariable&&(ClkCount==0))
{
TimeVariable=TimeVariable-1;
ClkCount=10;
}
FlagOnCountToNULL=0;
}
return TimeVariable;
}
ISR (TIMER1_OVF_vect)
{
TCNT1=65505;
FlagOnCountToNULL=1;
}
uint8_t FlagSM=0;
uint8_t FlagBtnSM=0;
uint8_t FlagSB=0;
uint8_t FlagBtnSB=0;
uint8_t FlagBtnPW=0;
uint8_t FlagBtnOW=0;
volatile uint8_t StepDebug = 0;
volatile uint8_t StepAuto = 0;
// Функция проверки РП на исходное(начальное) положение.
uint8_t CheckOriginalPosition()
{
static uint8_t State=0;
if ((BtOW||BtPW||FlagSB||FlagSM)||(BtS1||BtS2||GrKSM)) //Оптимизировать и внести правки.
{
State=0;
} else State=1;
return State;
}
volatile uint8_t FlangSetLongBtPR=0;
volatile uint8_t FlangSetShortBtPR=0;
volatile uint8_t LevelModProg=0;
volatile uint8_t TimerActive=1;
void UpdateEEPROM()
{
eeprom_update_word(&eepTimeToStartPW,TimeToStartPW);
eeprom_update_word(&eepTimeToStopPW,TimeToStopPW);
eeprom_update_word(&eepTimeOW,TimeOW);
eeprom_update_word(&eepTimeReturn,TimeReturn);
//eeprom_update_word(&eepCountProduct,CountProduct);
}
//Функция изменения заддоного разряда(NuberDidgit) в числе(OriginalValue) на +/-(1).
uint16_t ReplaceDigitValue(uint16_t OriginalValue,uint8_t NuberDidgit,uint8_t UpDown)
{
uint16_t LevelDig=1;
uint8_t ValueDidgit[5]={0};
uint8_t TempResult =0;
uint16_t ReturnValue=0;
for (uint8_t i = 0; i < 5; i++)
{
TempResult =OriginalValue % 10;
OriginalValue =OriginalValue / 10;
ValueDidgit[i] =TempResult;
}
if((UpDown==0)&&(ValueDidgit[NuberDidgit-1]>0)) {ValueDidgit[NuberDidgit-1]--;}
if((UpDown==1)&&(ValueDidgit[NuberDidgit-1]<9)&&(NuberDidgit<5))
{
ValueDidgit[NuberDidgit-1]++;
}
else if((UpDown==1)&&(ValueDidgit[NuberDidgit-1]<5)&&(NuberDidgit=5))
{
ValueDidgit[NuberDidgit-1]++;
}
for(uint8_t i = 0; i<5;i++)
{
ReturnValue=ReturnValue+ValueDidgit[i]*LevelDig;
if(i<4) LevelDig=LevelDig*10;
}
return ReturnValue;
}
volatile uint8_t CountDidgitNumber=1;
void InputMaskUpdate(uint16_t InputOne,uint16_t InputTwo,uint16_t InputThree)
{
switch(InputOne)
{
case BTN_SHRT_RA:
ModAuto=~ModAuto;
ModDebug=~ModDebug;
if (!(ModAuto)) DISPLAY_MOD_JOB=1; else DISPLAY_MOD_JOB=0;
break;
case BTN_SHRT_ST:
ModTimer=~ModTimer;
if (ModTimer==0)
{
DISPLAY_MOD_TIM=0;
}else DISPLAY_MOD_TIM=1;
break;
case BTN_SHRT_PR:
FlangSetShortBtPR=1;
if (ModProgramming)
{
FlangSetLongBtPR=0;
ModProgramming=0;
}
break;
case BTN_LONG_PR:
FlangSetLongBtPR=1;
break;
case BTN_SHRT_EN:
if (ModProgramming)
{
if(ModTimer!=0)
{
CountDidgitNumber++;
if (CountDidgitNumber > 5)
{
CountDidgitNumber=1;
}
}
}
if (ModProgramming)
{
if (LevelModProg==0)
{
LevelModProg=1;
break;
}
if (LevelModProg==1)
{
LevelModProg=0;
break;
}
}
break;
case BTN_SHRT_UP:
if ((ModProgramming)&&(ModTimer==0))
{
if (LevelModProg == 0)
{
TimerActive++;
if(TimerActive==5) TimerActive=1;
}
if (LevelModProg == 1)
{
switch(TimerActive)
{
case 1:TimeToStartPW++;break;
case 2:TimeToStopPW++;break;
case 3:TimeOW++;break;
case 4:TimeReturn++;break;
}
UpdateEEPROM();
}
}
if (ModProgramming&&(ModTimer!=0))
{
SetProgProduct=ReplaceDigitValue(SetProgProduct,CountDidgitNumber,1);break;
}
break;
case BTN_SHRT_DN:
if ((ModProgramming)&&(ModTimer==0))
{
if (LevelModProg==0)
{
TimerActive--;
if(TimerActive==0) TimerActive=4;
}
if (LevelModProg==1)
{
switch(TimerActive)
{
case 1:TimeToStartPW--;break;
case 2:TimeToStopPW--;break;
case 3:TimeOW--;break;
case 4:TimeReturn--;break;
}
UpdateEEPROM();
}
}
if (ModProgramming&&(ModTimer!=0))
{
SetProgProduct=ReplaceDigitValue(SetProgProduct,CountDidgitNumber,0);break;
}
break;
case BTN_LONG_UP:
break;
case BTN_LONG_DN:
if(ModTimer) CountProduct=0;
break;
case BTN_SHRT_SM:
FlagBtnSM=~FlagBtnSM;
break;
case BTN_SHRT_SB:
FlagBtnSB=~FlagBtnSB;
break;
default:break;
}
switch(InputTwo)
{
case BTN_SHRT_S1:
break;
case BTN_SHRT_S2:
break;
case GRK_SHRT_SM:
break;
case BTN_SHRT_PW:
FlagBtnPW=~FlagBtnPW;
break;
case BTN_SHRT_OW:
FlagBtnOW=~FlagBtnOW;
break;
case GRK_SHRT_ZM_IP:
break;
case GRK_SHRT_ZM_RP:
break;
case BTN_SHRT_ZM:
break;
default:break;
}
switch(InputThree)
{
/*
case DAT_SHRT_PWR: Датчик не работает в связи с
break; Запаздалой реакцией PC817
*/
case BTN_SHRT_MOD:
break;
default:break;
}
}
uint8_t StartCycleWork(uint8_t Bt1,uint8_t bt2)
{
uint8_t StartCycle=0;
if (Bt1&&bt2)
{
StartCycle = 1;
}
if ((BTN_PIN2 & BTN_LINE_S1)||(BTN_PIN2 & BTN_LINE_S2))
{
StartCycle=0;
}
return StartCycle;
}
uint8_t OneEnablePower=1;
void LoadEEPROM()
{
TimeToStartPW = eeprom_read_word(&eepTimeToStartPW);
TimeToStopPW = eeprom_read_word(&eepTimeToStopPW);
TimeOW = eeprom_read_word(&eepTimeOW);
TimeReturn = eeprom_read_word(&eepTimeReturn);
//if(OneEnablePower) CountProduct = eeprom_read_word(&eepCountProduct);
}
//Функция проверки исполнительных устройств на исходное положение.
int main(void)
{
InitIO_MC(); //Иницилизация портов.
LoadEEPROM();
StartInitIO();
SPI_Init();
SpiUpdateRegister();
_delay_ms(100);
InitTimer1_OVF();
InitTimer0_OVF();
ENABLE_POWER;
volatile uint8_t FlagOriginalPosition = 0;
if (OneEnablePower) OneEnablePower=0;
sei();
while(1)
{
InputMaskUpdate(MaskGetOne(),MaskGetTwo(),MaskGetThree());
if (FlagsEnDiplay) //Проверка флага разрешения вывода информации
{
if((CountProduct >= SetProgProduct)&&(SetProgProduct!=0))
{
FlagOverflowProduct=1;
} else {
FlagOverflowProduct=0;
}
if((!(ModTimer))&&(ModProgramming==0)) //Если режим таймера = 0 , то выводим Т1..Т4
{
TimeSumm=TimeToStartPW+TimeToStopPW+TimeOW+TimeReturn;
switch(StepAuto)
{
case 0: //Ожидания начала цикла(Ожидания старта от StartCycleWork() )
PrintNumber((TimeSumm),0,Flags); //Выводим Сумму Т1..Т4
break;
case 1: //Обработка Т1
PrintNumber((TimeToStartPW),StepAuto,Flags);
break;
case 2: //Обработка Т2
PrintNumber((TimeToStopPW),StepAuto,Flags);
break;
case 3: //Обработка Т3
PrintNumber((TimeOW),StepAuto,Flags);
break;
case 4: //Обработка Т4
PrintNumber((TimeReturn),StepAuto,Flags);
break;
}
}
if ((ModTimer)&&(ModProgramming==0)) //Если режим таймера = 1, то выводим счетчик.
{
if(FlagOverflowProduct==0){
PrintNumber((CountProduct),0,Flags);
}
else{
PrintNumber((CountProduct),0,Flags);
}
}
//Если выбран режим программирования.
if(ModProgramming)
{
if (ModTimer==0) //Отображение программирования режима таймера.
{
if (LevelModProg==0)
{
Flags.Bits.DO0=0;
Flags.Bits.DO1=0;
Flags.Bits.DO2=0;
Flags.Bits.DO3=0;
Flags.Bits.DO5=1;
}
if (LevelModProg==1)
{
Flags.Bits.DO0=1;
Flags.Bits.DO1=1;
Flags.Bits.DO2=1;
Flags.Bits.DO3=1;
Flags.Bits.DO5=0;
}
switch(TimerActive)
{
case 1:
PrintNumber((TimeToStartPW),TimerActive,Flags);
break;
case 2: // Т2
PrintNumber((TimeToStopPW),TimerActive,Flags);
break;
case 3: // Т3
PrintNumber((TimeOW),TimerActive,Flags);
break;
case 4: // Т4
PrintNumber((TimeReturn),TimerActive,Flags);
break;
default: break;
}
}
if (ModTimer!=0) //Отображение программирования режима счетчика.
{
switch(CountDidgitNumber)
{
case 1:
Flags.Bits.DO0=1;
Flags.Bits.DO1=0;
Flags.Bits.DO2=0;
Flags.Bits.DO3=0;
Flags.Bits.DO4=0;
PrintNumber(SetProgProduct,0,Flags);
break;
case 2:
Flags.Bits.DO0=0;
Flags.Bits.DO1=1;
Flags.Bits.DO2=0;
Flags.Bits.DO3=0;
Flags.Bits.DO4=0;
PrintNumber(SetProgProduct,0,Flags);
break;
case 3:
Flags.Bits.DO0=0;
Flags.Bits.DO1=0;
Flags.Bits.DO2=1;
Flags.Bits.DO3=0;
Flags.Bits.DO4=0;
PrintNumber(SetProgProduct,0,Flags);
break;
case 4:
Flags.Bits.DO0=0;
Flags.Bits.DO1=0;
Flags.Bits.DO2=0;
Flags.Bits.DO3=1;
Flags.Bits.DO4=0;
PrintNumber(SetProgProduct,0,Flags);
break;
case 5:
Flags.Bits.DO0=0;
Flags.Bits.DO1=0;
Flags.Bits.DO2=0;
Flags.Bits.DO3=0;
Flags.Bits.DO4=1;
PrintNumber(SetProgProduct,0,Flags);
break;
default:break;
}
}
} else Flags.Byte=0;
FlagsEnDiplay=0; // Обнуляем Флаг разрешения. (Включается в прерывание таймера 0)
}
if(FlangSetLongBtPR)
{
ModProgramming=1;
}
//Алгоритм работы выходных MosFet ключей в ручном режиме(Режиме отладки).
if ((ModDebug!=0)&&(ModAuto == 0)&&(ModProgramming==0))
{
ENABLE_POWER;
if (BtPW)
{
ENABLE_PW;
} else DISABLE_PW;
if (BtOW)
{
ENABLE_OW;
} else DISABLE_OW;
if ((FlagBtnSM)&&(StepDebug!=2))
{
FlagSM=1;
StepDebug=1;
ENABLE_SM;
} else if (FlagSB==0)
{
DISABLE_SM;
FlagSM=0;
}
if (FlagBtnSB)
{
FlagSB=1;
StepDebug=2;
ENABLE_SB;
}
else {
DISABLE_SB;
FlagSB=0;
StepDebug=0;
}
}
//Алгоритм работы выходных MosFet ключей в режиме цикла.(Автоматический режим).
if ((ModAuto!=0)&&(ModDebug == 0)&&(ModProgramming==0))
{
switch(StepAuto)
{
case 0:
switch(FlagOriginalPosition)
{
case 0:
DISABLE_POWER;
FlagOriginalPosition=CheckOriginalPosition();
break;
case 1:
FlagOriginalPosition=2;
break;
case 2:
if (StartCycleWork(BtS1,BtS2))
{
ENABLE_POWER;
ENABLE_SM;
if (GrKSM) StepAuto=1;
}
else
{
DISABLE_SM;
DISABLE_POWER;
}
break;
}
break;
case 1:
FlagOriginalPosition=0;
ENABLE_SB;
TimeToStartPW=CountToNULL(TimeToStartPW);
if (TimeToStartPW==0) StepAuto=2;
break;
case 2:
ENABLE_PW;
TimeToStopPW=CountToNULL(TimeToStopPW);
if (TimeToStopPW==0)
{
DISABLE_PW;
StepAuto=3;
}
break;
case 3:
ENABLE_OW;
TimeOW=CountToNULL(TimeOW);
if (TimeOW==0)
{
DISABLE_OW;
StepAuto=4;
}
break;
case 4:
TimeReturn=CountToNULL(TimeReturn);
if (TimeReturn==0)
{
;
DISABLE_SB;
//Подумать о добавлении задержки 100-200ms.
DISABLE_SM;
if (CheckOriginalPosition())
{
LoadEEPROM();
CountProduct++;
StepAuto=0;
}
}
break;
}
}
}
return 0;
}