В общем код написан для секундомера для лабораторной установки в универе.
Заранее извиняюсь, что такой большой код кинул на страницу, но файл не загрузило
CODE
/************ ПРИМЕЧАНИЕ К ПРОГРАММЕ *****************
**
** Последнее изменение: 12.02.2010
** Микроконтроллер: ATtiny2313
** Частота: Кварц внешний, 4.0 МГц
**
*******************************************************/
#include "common.h" ;присоединение файла common.h
#include "cntr.h" ;присоединение файла cntr.h
#include "iotiny2313.h" ;присоединение файла iotiny2313.h файл описания для микроконтроллера
#define DOUT PORTB_Bit6 // определение переменных PB6 (PORT - сконфигурировать порт на вывод)
#define SCK PORTB_Bit5 // для портов PB5 вывод
#define STR PORTB_Bit7 // вывода информации PB7 вывод
#define OE PORTB_Bit4 // на индикаторы PB4 вывод
#define REL1 PORTB_Bit2 // опредление переменных для магнита №1 PB2 вывод
#define REL2 PORTB_Bit3 // -||- PB3 вывод
#define IN1 PINB_Bit0 // опредление переменной для запуска счетчика PB0 (PIN-сконфигурировать порт на ввод)
#define IN2 PINB_Bit1 // опредление переменной для стопа счетчика PB1 ввод
#define BUZER PORTD_Bit1 // опредление переменной для пищалки PD1 вывод
#define RELAY PIND_Bit2 // опредление переменной для кнопки ЭМ PD2 ввод
#define START PIND_Bit3 // опредление переменной для кнопки пуск PD3 ввод
#define STOP PIND_Bit4 // опредление переменной для кнопки стоп PD4 ввод
#define RESET PIND_Bit5 // опредление переменной для кнопки сброс PD5 ввод
#define Relay_Start_Time 6000 // 60 сек (6000 * 10 мс)
#define Relay_Pause_Time 20 // 0.2 сек (20 * 0.01 с)
#define Relay_Stop_Time 200 // 2 сек (200 * 0.01 с)
#define Buzer_Time 60 // 60 мс (60 * 1 мс)
#define Relay_Poll_Time 200 // 2 сек (300 * 0.01 с)
__no_init __regvar struct // объявление бит
{
unsigned char dynamic : 1; // флаг динамической индикации
unsigned char timer : 1; // unsigned char 0...255 (только полож. числа)
unsigned char start : 1; //
unsigned char parity : 1;
unsigned char reseted : 1;
unsigned char relay : 1;
unsigned char result : 1;
}@15;
__no_init __regvar struct // объявление бит
{
unsigned char relay_keep : 1;
unsigned char relay_repeat : 1;
}@14;
union
{
struct
{
unsigned char millisecond[5];
unsigned char period[2];
};
unsigned char digit[7];
};
__no_init __regvar unsigned char dynamic_cntr@13;
__no_init __regvar unsigned char relay_pause_tmr@12;
__no_init __regvar unsigned char timer_cntr@11;
__no_init __regvar unsigned char buzer_tmr@10;
unsigned char segment;
unsigned char segment_register;
unsigned char anode_register;
unsigned int relay_tmr;
unsigned int relay_poll_cntr;
__flash unsigned char anode_code[] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF};
__flash unsigned char segment_code[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
void main(void) // основная программа (главная функция)
{
_WDR();
WDTCR = (1 << WDCE) | (1 << WDE); // начать изменения WDT
WDTCR = (1 << WDE); // программирование WDT на 16ms
DDRD = 0x02;
PORTD = 0xFD;
DDRB = 0xFC;
PORTB = 0x03;
dynamic_cntr = 0;
relay_pause_tmr = 0;
timer_cntr = 0;
buzer_tmr = 0;
dynamic = timer = start = parity = reseted = result = relay = 0;
#ifdef CNTR_01 // если счетчик СЭ-01
relay_repeat = 0;
#else
relay_repeat = 1;
#endif
relay_keep = 0;
OCR1A = 499; // период таймера 1 мс
TCCR1A = 0x00;
TCCR1B = (1 << WGM12) | (1 << CS11); // очищать таймер 1 по переполнению, делитель на 8
TIMSK = (1 << OCIE1A); // разрешить прерывание по сравнению таймера 1
wait_pcint0();
GIMSK = (1 << PCIE);
buzer_on();
_SEI();
while(1)
{
if(dynamic)
{
dynamic = 0;
if(segment == 0)
{
#ifdef CNTR_02 // если счетчик СЭ-02
segment = 5;
#else
segment = 7;
#endif
}
segment--;
segment_register = segment_code[digit[segment]];
#ifdef CNTR_02 // если счетчик СЭ-02
if(segment == 1)
segment_register &= 0x7F;
#else
if(segment == 2)
segment_register &= 0x7F;
#endif
anode_register = anode_code[segment];
write_register(((signed int)anode_register << 8) | segment_register);
}
}
}
#pragma vector=PCIN1_vect
__interrupt void PCIN1_interrupt(void)
{
#ifdef CNTR_02
if(start) // если запущен счетчик
{
if(!timer)
{
timer = 1;
buzer_on(); // пищит пищалка
wait_pcint1();
}
else
{
timer = 0; // остановить миллисекундомер
start = 0;
buzer_on(); // пищит пищалка
wait_pcint0();
if(relay_repeat)
relay_pause_tmr = 20; // запустить паузу на 200 ms и повторное включение реле
relay_repeat = 1;
}
}
#else // иначе счетчик СЭ-01
if(IN1) // если положительный фронт
{
parity = ~parity;
if(timer)
{
if(!parity)
{
inc_period();
buzer_on(); // пищит пищалка
}
}
if(start)
{
if(!timer)
{
parity = 0;
timer = 1;
buzer_on(); // пищит пищалка
}
}
else
{
if(timer)
{
if(!parity)
{
timer = 0;
result = 1;
buzer_on(); // пищит пищалка
if(relay_repeat)
{
relay_pause_tmr = Relay_Pause_Time; // запустить паузу и потом включить реле
//relay_repeat = 0;
}
}
}
}
}
#endif
}
#pragma vector=TIMER1_COMPA_vect
__interrupt void TIMER1_COMPA_interrupt(void)
{
if(++dynamic_cntr > 2)
{
dynamic_cntr = 0;
dynamic = 1;
}
if(buzer_tmr > 0)
if(!--buzer_tmr)
BUZER = 0;
#ifdef CNTR_02
if(timer) // если запущен таймер
inc_tmr();
#endif
if(++timer_cntr > 9) // период 10 мс
{
timer_cntr = 0;
_WDR();
#ifdef CNTR_01 // если счетчик СЭ-01
if(timer) // если запущен таймер
inc_tmr();
#endif
if(relay_tmr > 0)
{
if(!--relay_tmr)
{
relay = 0;
REL1 = 0;
REL2 = 0; // выключить реле 1 и 2
}
}
if(relay_pause_tmr > 0)
{
if(!--relay_pause_tmr)
{
relay_on(); // включить реле для торможения
relay_tmr = Relay_Stop_Time;
}
}
if(!RELAY) // нажата кнопка магнит
{
if(++relay_poll_cntr > Relay_Poll_Time)
{
if(!relay_keep)
{
relay_keep = 1;
#ifdef CNTR_01
relay_repeat = 1;
#else
relay_repeat = 0;
#endif
buzer_on(); // пищит пищалка
}
}
if(!result)
{
if(!relay)
{
if(!start)
{
buzer_on(); // пищит пищалка
relay_on();
relay_tmr = Relay_Start_Time; // запустить таймер
relay = 1;
reseted = 0;
}
}
}
}
else
{
relay_poll_cntr = 0;
relay_keep = 0;
if(!START) // нажата кнопка старт
{
if(!result)
{
if(!start)
{
start = 1;
reseted = 0;
#ifdef CNTR_01
timer = 0;
null_cntr();
#endif
buzer_on(); // пищит пищалка
relay_off();
relay = 0;
wait_pcint0(); // ожидание прерывания со входа 0
}
}
}
else if(!STOP) // нажата кнопка стоп
{
if(start)
{
start = 0;
buzer_on(); // пищит пищалка
}
}
else if(!RESET) // нажата кнопка сброс
{
if(!reseted)
{
start = 0;
reseted = 1;
result = 0;
timer = 0;
relay_off();
relay = 0;
#ifdef CNTR_01
relay_repeat = 0;
#else
relay_repeat = 1;
#endif
buzer_on(); // пищит пищалка
null_cntr();
wait_pcint0(); // ожидание прерывания со входа 0
}
}
}
}
}
void inc_tmr(void)
{
if(++millisecond[4] > 9)
{
millisecond[4] = 0;
if(++millisecond[3] > 9)
{
millisecond[3] = 0;
if(++millisecond[2] > 9)
{
millisecond[2] = 0;
if(++millisecond[1] > 9)
{
millisecond[1] = 0;
if(++millisecond[0] > 9)
millisecond[0] = 0;
}
}
}
}
}
void inc_period(void)
{
if(++period[1] > 9)
{
period[1] = 0;
if(++period[0] > 9)
period[0] = 0;
}
}
void wait_pcint0(void)
{
PCMSK = (1 << PCINT0); // ожидание прерывания со входа 0
EIFR = (1 << PCIF); // сбросить прерывание от фотодатчика
}
void wait_pcint1(void)
{
PCMSK = (1 << PCINT1); // ожидание прерывания со входа 2
EIFR = (1 << PCIF); // сбросить прерывание от фотодатчика
}
void null_cntr(void)
{
period[0] = 0;
period[1] = 0;
millisecond[0] = 0;
millisecond[1] = 0;
millisecond[2] = 0;
millisecond[3] = 0;
millisecond[4] = 0;
}
void relay_off(void) // программа для выключения реле (магнита)
{
REL1 = 0; // выключить реле 1 (магнита)
REL2 = 0; // выключить реле 2 (магнита)
relay_tmr = 0; // обнуление соответствующего таймера
}
void relay_on(void) // программа для включения реле (магнита)
{
REL1 = 1; // включить реле 1
#ifdef CNTR_02 // если счетчик СЭ-02
REL2 = 1; // включить реле 2
#endif
}
void buzer_on(void) // программа для включения пищалки
{
BUZER = 1;
buzer_tmr = Buzer_Time; // включит бузер
}
void write_register(signed int data) // программа для вывода информации на индикаторы
{
unsigned char bit;
for(bit = 0; bit < 16; bit++)
{
SCK = 0;
if(BIT(data, 15))
DOUT = 1;
else
DOUT = 0;
data = data << 1;
SCK = 1;
}
SCK = 0;
DOUT = 0;
STR = 1;
__delay_cycles(4);
STR = 0; // стробирование регистра
OE = 1; // разрешить регистр
}
**
** Последнее изменение: 12.02.2010
** Микроконтроллер: ATtiny2313
** Частота: Кварц внешний, 4.0 МГц
**
*******************************************************/
#include "common.h" ;присоединение файла common.h
#include "cntr.h" ;присоединение файла cntr.h
#include "iotiny2313.h" ;присоединение файла iotiny2313.h файл описания для микроконтроллера
#define DOUT PORTB_Bit6 // определение переменных PB6 (PORT - сконфигурировать порт на вывод)
#define SCK PORTB_Bit5 // для портов PB5 вывод
#define STR PORTB_Bit7 // вывода информации PB7 вывод
#define OE PORTB_Bit4 // на индикаторы PB4 вывод
#define REL1 PORTB_Bit2 // опредление переменных для магнита №1 PB2 вывод
#define REL2 PORTB_Bit3 // -||- PB3 вывод
#define IN1 PINB_Bit0 // опредление переменной для запуска счетчика PB0 (PIN-сконфигурировать порт на ввод)
#define IN2 PINB_Bit1 // опредление переменной для стопа счетчика PB1 ввод
#define BUZER PORTD_Bit1 // опредление переменной для пищалки PD1 вывод
#define RELAY PIND_Bit2 // опредление переменной для кнопки ЭМ PD2 ввод
#define START PIND_Bit3 // опредление переменной для кнопки пуск PD3 ввод
#define STOP PIND_Bit4 // опредление переменной для кнопки стоп PD4 ввод
#define RESET PIND_Bit5 // опредление переменной для кнопки сброс PD5 ввод
#define Relay_Start_Time 6000 // 60 сек (6000 * 10 мс)
#define Relay_Pause_Time 20 // 0.2 сек (20 * 0.01 с)
#define Relay_Stop_Time 200 // 2 сек (200 * 0.01 с)
#define Buzer_Time 60 // 60 мс (60 * 1 мс)
#define Relay_Poll_Time 200 // 2 сек (300 * 0.01 с)
__no_init __regvar struct // объявление бит
{
unsigned char dynamic : 1; // флаг динамической индикации
unsigned char timer : 1; // unsigned char 0...255 (только полож. числа)
unsigned char start : 1; //
unsigned char parity : 1;
unsigned char reseted : 1;
unsigned char relay : 1;
unsigned char result : 1;
}@15;
__no_init __regvar struct // объявление бит
{
unsigned char relay_keep : 1;
unsigned char relay_repeat : 1;
}@14;
union
{
struct
{
unsigned char millisecond[5];
unsigned char period[2];
};
unsigned char digit[7];
};
__no_init __regvar unsigned char dynamic_cntr@13;
__no_init __regvar unsigned char relay_pause_tmr@12;
__no_init __regvar unsigned char timer_cntr@11;
__no_init __regvar unsigned char buzer_tmr@10;
unsigned char segment;
unsigned char segment_register;
unsigned char anode_register;
unsigned int relay_tmr;
unsigned int relay_poll_cntr;
__flash unsigned char anode_code[] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF};
__flash unsigned char segment_code[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
void main(void) // основная программа (главная функция)
{
_WDR();
WDTCR = (1 << WDCE) | (1 << WDE); // начать изменения WDT
WDTCR = (1 << WDE); // программирование WDT на 16ms
DDRD = 0x02;
PORTD = 0xFD;
DDRB = 0xFC;
PORTB = 0x03;
dynamic_cntr = 0;
relay_pause_tmr = 0;
timer_cntr = 0;
buzer_tmr = 0;
dynamic = timer = start = parity = reseted = result = relay = 0;
#ifdef CNTR_01 // если счетчик СЭ-01
relay_repeat = 0;
#else
relay_repeat = 1;
#endif
relay_keep = 0;
OCR1A = 499; // период таймера 1 мс
TCCR1A = 0x00;
TCCR1B = (1 << WGM12) | (1 << CS11); // очищать таймер 1 по переполнению, делитель на 8
TIMSK = (1 << OCIE1A); // разрешить прерывание по сравнению таймера 1
wait_pcint0();
GIMSK = (1 << PCIE);
buzer_on();
_SEI();
while(1)
{
if(dynamic)
{
dynamic = 0;
if(segment == 0)
{
#ifdef CNTR_02 // если счетчик СЭ-02
segment = 5;
#else
segment = 7;
#endif
}
segment--;
segment_register = segment_code[digit[segment]];
#ifdef CNTR_02 // если счетчик СЭ-02
if(segment == 1)
segment_register &= 0x7F;
#else
if(segment == 2)
segment_register &= 0x7F;
#endif
anode_register = anode_code[segment];
write_register(((signed int)anode_register << 8) | segment_register);
}
}
}
#pragma vector=PCIN1_vect
__interrupt void PCIN1_interrupt(void)
{
#ifdef CNTR_02
if(start) // если запущен счетчик
{
if(!timer)
{
timer = 1;
buzer_on(); // пищит пищалка
wait_pcint1();
}
else
{
timer = 0; // остановить миллисекундомер
start = 0;
buzer_on(); // пищит пищалка
wait_pcint0();
if(relay_repeat)
relay_pause_tmr = 20; // запустить паузу на 200 ms и повторное включение реле
relay_repeat = 1;
}
}
#else // иначе счетчик СЭ-01
if(IN1) // если положительный фронт
{
parity = ~parity;
if(timer)
{
if(!parity)
{
inc_period();
buzer_on(); // пищит пищалка
}
}
if(start)
{
if(!timer)
{
parity = 0;
timer = 1;
buzer_on(); // пищит пищалка
}
}
else
{
if(timer)
{
if(!parity)
{
timer = 0;
result = 1;
buzer_on(); // пищит пищалка
if(relay_repeat)
{
relay_pause_tmr = Relay_Pause_Time; // запустить паузу и потом включить реле
//relay_repeat = 0;
}
}
}
}
}
#endif
}
#pragma vector=TIMER1_COMPA_vect
__interrupt void TIMER1_COMPA_interrupt(void)
{
if(++dynamic_cntr > 2)
{
dynamic_cntr = 0;
dynamic = 1;
}
if(buzer_tmr > 0)
if(!--buzer_tmr)
BUZER = 0;
#ifdef CNTR_02
if(timer) // если запущен таймер
inc_tmr();
#endif
if(++timer_cntr > 9) // период 10 мс
{
timer_cntr = 0;
_WDR();
#ifdef CNTR_01 // если счетчик СЭ-01
if(timer) // если запущен таймер
inc_tmr();
#endif
if(relay_tmr > 0)
{
if(!--relay_tmr)
{
relay = 0;
REL1 = 0;
REL2 = 0; // выключить реле 1 и 2
}
}
if(relay_pause_tmr > 0)
{
if(!--relay_pause_tmr)
{
relay_on(); // включить реле для торможения
relay_tmr = Relay_Stop_Time;
}
}
if(!RELAY) // нажата кнопка магнит
{
if(++relay_poll_cntr > Relay_Poll_Time)
{
if(!relay_keep)
{
relay_keep = 1;
#ifdef CNTR_01
relay_repeat = 1;
#else
relay_repeat = 0;
#endif
buzer_on(); // пищит пищалка
}
}
if(!result)
{
if(!relay)
{
if(!start)
{
buzer_on(); // пищит пищалка
relay_on();
relay_tmr = Relay_Start_Time; // запустить таймер
relay = 1;
reseted = 0;
}
}
}
}
else
{
relay_poll_cntr = 0;
relay_keep = 0;
if(!START) // нажата кнопка старт
{
if(!result)
{
if(!start)
{
start = 1;
reseted = 0;
#ifdef CNTR_01
timer = 0;
null_cntr();
#endif
buzer_on(); // пищит пищалка
relay_off();
relay = 0;
wait_pcint0(); // ожидание прерывания со входа 0
}
}
}
else if(!STOP) // нажата кнопка стоп
{
if(start)
{
start = 0;
buzer_on(); // пищит пищалка
}
}
else if(!RESET) // нажата кнопка сброс
{
if(!reseted)
{
start = 0;
reseted = 1;
result = 0;
timer = 0;
relay_off();
relay = 0;
#ifdef CNTR_01
relay_repeat = 0;
#else
relay_repeat = 1;
#endif
buzer_on(); // пищит пищалка
null_cntr();
wait_pcint0(); // ожидание прерывания со входа 0
}
}
}
}
}
void inc_tmr(void)
{
if(++millisecond[4] > 9)
{
millisecond[4] = 0;
if(++millisecond[3] > 9)
{
millisecond[3] = 0;
if(++millisecond[2] > 9)
{
millisecond[2] = 0;
if(++millisecond[1] > 9)
{
millisecond[1] = 0;
if(++millisecond[0] > 9)
millisecond[0] = 0;
}
}
}
}
}
void inc_period(void)
{
if(++period[1] > 9)
{
period[1] = 0;
if(++period[0] > 9)
period[0] = 0;
}
}
void wait_pcint0(void)
{
PCMSK = (1 << PCINT0); // ожидание прерывания со входа 0
EIFR = (1 << PCIF); // сбросить прерывание от фотодатчика
}
void wait_pcint1(void)
{
PCMSK = (1 << PCINT1); // ожидание прерывания со входа 2
EIFR = (1 << PCIF); // сбросить прерывание от фотодатчика
}
void null_cntr(void)
{
period[0] = 0;
period[1] = 0;
millisecond[0] = 0;
millisecond[1] = 0;
millisecond[2] = 0;
millisecond[3] = 0;
millisecond[4] = 0;
}
void relay_off(void) // программа для выключения реле (магнита)
{
REL1 = 0; // выключить реле 1 (магнита)
REL2 = 0; // выключить реле 2 (магнита)
relay_tmr = 0; // обнуление соответствующего таймера
}
void relay_on(void) // программа для включения реле (магнита)
{
REL1 = 1; // включить реле 1
#ifdef CNTR_02 // если счетчик СЭ-02
REL2 = 1; // включить реле 2
#endif
}
void buzer_on(void) // программа для включения пищалки
{
BUZER = 1;
buzer_tmr = Buzer_Time; // включит бузер
}
void write_register(signed int data) // программа для вывода информации на индикаторы
{
unsigned char bit;
for(bit = 0; bit < 16; bit++)
{
SCK = 0;
if(BIT(data, 15))
DOUT = 1;
else
DOUT = 0;
data = data << 1;
SCK = 1;
}
SCK = 0;
DOUT = 0;
STR = 1;
__delay_cycles(4);
STR = 0; // стробирование регистра
OE = 1; // разрешить регистр
}