/** AssHeat.c
*
* Created: 25.12.2013 2:29:55
* Author: Alex
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <avr/eeprom.h>
#define CHAN1_INC 0
#define CHAN1_DEC 1
#define CHAN2_INC 2
#define CHAN2_DEC 3
#define MAX_STAGE 3
volatile unsigned char chan1Stage = 0;
volatile unsigned char chan2Stage = 0;
volatile uint32_t channel1StartCount = 0;
volatile uint32_t channel2StartCount = 0;
volatile int chan1HeatMode = 0;
volatile int chan2HeatMode = 0;
volatile int indicatorFlashCounter = 0;
volatile int indicatorFlashState = 0;
volatile int buttonPressTime[4];
volatile char buttonStates[] = {0,0,0,0};
char buttonPins[] = {PB0, PB1, PB6, PB7};
//volatile char btn1State = 0;
//volatile char btn2State = 0;
//volatile char btn3State = 0;
//volatile char btn4State = 0;
volatile char learnMode = 0;
uint32_t heatingTime_ee EEMEM;
volatile uint32_t heatingTime = 0;
char chan1LastStage_ee EEMEM;
char chan2LastStage_ee EEMEM;
char chan1LastStage = 0;
char chan2LastStage = 0;
void startHeat(unsigned char chan)
{
if (1==chan)
{
channel1StartCount = 0;
chan1HeatMode = 1;
}
else if (2==chan)
{
channel2StartCount = 0;
chan2HeatMode = 1;
}
}
void updateStatusLeds()
{
if (chan1HeatMode==0)
{
switch (chan1Stage)
{
case 0:
PORTD &= ~(1 << PD0);
PORTD &= ~(1 << PD1);
break;
case 1:
PORTD &= ~(1 << PD0);
PORTD |= (1 << PD1);
break;
case 2:
PORTD |= (1 << PD0);
PORTD |= (1 << PD1);
break;
case 3:
PORTD |= (1 << PD0);
PORTD &= ~(1 << PD1);
break;
}
}
if (chan2HeatMode==0)
{
switch (chan2Stage)
{
case 0:
PORTD &= ~(1 << PD2);
PORTD &= ~(1 << PD3);
break;
case 1:
PORTD &= ~(1 << PD2);
PORTD |= (1 << PD3);
break;
case 2:
PORTD |= (1 << PD2);
PORTD |= (1 << PD3);
break;
case 3:
PORTD |= (1 << PD2);
PORTD &= ~(1 << PD3);
break;
}
}
}
void strartLearn()
{
learnMode = 1;
}
void stopLearn()
{
heatingTime = channel1StartCount;
eeprom_write_dword(&heatingTime_ee, heatingTime);
learnMode = 0;
chan1HeatMode = 0;
channel1StartCount = 0;
}
void buttonDown(int btn)
{
}
void updateState()
{
updateStatusLeds();
updatePWM();
}
void buttonUp(int btn, int pressTime)
{
_delay_ms(20);
//PORTB |= (1 << PB4);
switch (btn)
{
case CHAN1_INC:
if (pressTime<35)
{
if (0==chan1Stage)
{
startHeat(1);
if (chan1LastStage>0 && chan1LastStage <= MAX_STAGE)
chan1Stage = chan1LastStage;
else
chan1Stage = 1;
}
else if (chan1Stage<MAX_STAGE && chan1HeatMode==0)
{
chan1Stage++;
chan1LastStage = chan1Stage;
eeprom_write_byte(&chan1LastStage_ee, chan1LastStage);
}
}
break;
case CHAN1_DEC:
if (1==learnMode)
{
stopLearn();
if (chan1LastStage>0 && chan1LastStage <= MAX_STAGE)
chan1Stage = chan1LastStage;
else
chan1Stage = 1;
}
else if (pressTime<35)
{
if (chan1Stage>0 && chan1HeatMode==0)
{
chan1Stage--;
if (chan1Stage==0)
chan1HeatMode = 0;
else
{
chan1LastStage = chan1Stage;
eeprom_write_byte(&chan1LastStage_ee, chan1LastStage);
}
}
else if (chan1HeatMode==1)
{
chan1HeatMode = 0;
}
}
break;
case CHAN2_INC:
if (0==chan2Stage)
{
startHeat(2);
if (chan2LastStage > 0 && chan2LastStage <= MAX_STAGE)
chan2Stage = chan2LastStage;
else
chan2Stage = 1;
}
else if (chan2Stage<MAX_STAGE && chan1HeatMode==0)
{
chan2Stage++;
chan2LastStage = chan2Stage;
eeprom_write_byte(&chan2LastStage_ee, chan2Stage);
}
break;
case CHAN2_DEC:
if (pressTime < 35)
{
if (chan2Stage>0 && chan2HeatMode==0)
{
chan2Stage--;
if (chan2Stage==0)
chan2HeatMode = 0;
else
{
chan2LastStage = chan2Stage;
eeprom_write_byte(&chan2LastStage_ee, chan2LastStage);
}
}
else if (chan2HeatMode==1)
{
chan2HeatMode=0;
}
}
break;
}
updateState();
}
//#define Prescaler 0x01 //0x00 - для кварца 4MHz, 0x01 - для кварца 8MHz...
void updatePWM()
{
// fast PWM mode
TCCR0A = (1 << WGM01) | (1 << WGM00);
if (chan1Stage>0 || chan1HeatMode)
{
TCCR0A |= (1 << COM0A1);
}
if (chan2Stage>0 || chan2HeatMode)
{
TCCR0A |= (1 << COM0B1);
}
}
void loadEepromValues()
{
heatingTime = eeprom_read_dword(&heatingTime_ee);
if (0==heatingTime)
heatingTime = 1000;
chan1LastStage = eeprom_read_byte(&chan1LastStage_ee);
chan2LastStage = eeprom_read_byte(&chan2LastStage_ee);
}
int main(void)
{
unsigned char stateValues[] = {255,64,128,254};
DDRB = 0;
DDRD = 0;
DDRB |= (1 << PB2) | (1 << PB4); // PWM output on PB2 - OC0A
DDRD |= (1 << PD5) | (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3); // PWM output on PD5 - OC0B
TCCR0A = (1 << WGM01) | (1 << WGM00);
TCCR0B = (1 << CS02); // clock source = CLK/8, start PWM
TCCR1A = 0;
TCCR1B = (0 << CS12)|(1 << CS11)| (0 << CS10);//|(1 << WGM12); //предделитель clk/1024, режим таймера СТС;
OCR1AH=0x0F; OCR1AL=0x42; // Число N=15625=0x3D09.
TCNT1 = 0;
//OCR1A = 0;//62500/1; // compare match register.
//TCCR1B |= (1 << WGM12); // CTC mode
//TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK |= (1 << OCIE1A); // enable timer compare interrupt
//TIMSK = (TOIE1<<1);
//TCNT1 = 7;
chan1Stage = 0;
chan2Stage = 0;
PORTB &= ~(1 << PB4);
PORTB |= (1 << PB0);
PORTB |= (1 << PB1);
PORTB |= (1 << PB6);
PORTB |= (1 << PB7);
loadEepromValues();
sei();
while(1)
{
OCR0A = chan1HeatMode==0 ? stateValues[chan1Stage] : 254;// PWM_val1; // write new PWM value
OCR0B = chan2HeatMode==0 ? stateValues[chan2Stage] : 254;
for (char btn=0;btn<4;++btn)
{
if ((PINB & (1 << buttonPins[btn]))==0)
{
if (0==buttonStates[btn])
{
buttonDown(btn);
buttonPressTime[btn] = 0;
}
buttonStates[btn] = 1;
}
else
{
if (1==buttonStates[btn])
{
buttonUp(btn, buttonPressTime[btn]);
}
buttonStates[btn] = 0;
}
}
if (buttonStates[CHAN1_DEC]==1 && buttonPressTime[CHAN1_DEC]>35)
{
chan1Stage = 0;
chan1HeatMode = 0;
updateState();
}
if (buttonStates[CHAN2_DEC]==1 && buttonPressTime[CHAN2_DEC]>35)
{
chan2Stage = 0;
chan2HeatMode = 0;
updateState();
}
if (buttonStates[CHAN1_INC]==1 && 0==chan1Stage && buttonPressTime[CHAN1_INC] > 35)
{
startHeat(1);
strartLearn();
updateState();
}
}
}
int state = 0;
ISR (TIMER1_COMPA_vect)
{
TCNT1H=0; TCNT1L=0; // Сброс таймера.
for (char btn=0;btn<4;++btn)
{
if (buttonStates[btn]!=0)
buttonPressTime[btn]++;
}
indicatorFlashCounter++;
if (indicatorFlashCounter > 4)
{
indicatorFlashCounter = 0;
indicatorFlashState = ~ indicatorFlashState;
}
if (chan1HeatMode == 1)
{
channel1StartCount ++;
if (channel1StartCount > heatingTime && learnMode == 0)
{
chan1HeatMode = 0;
updateStatusLeds();
}
else
{
int port = learnMode==0 ? PD0 : PD1;
if (indicatorFlashState==0)
PORTD &= ~ (1 << port);
else
PORTD |= (1 << port);
}
}
if (chan2HeatMode == 1)
{
channel2StartCount ++;
if (channel2StartCount > heatingTime)
{
chan2HeatMode = 0;
updateStatusLeds();
}
else
{
if (indicatorFlashState==0)
PORTD &= ~ (1 << PD2);
else
PORTD |= (1 << PD2);
}
}
}
[свернуть]