|
|
  |
Помогите с кодом новичку, пожалуйста |
|
|
|
Dec 13 2012, 19:40
|
Группа: Новичок
Сообщений: 4
Регистрация: 13-12-12
Пользователь №: 74 841

|
Я студент 5-го курса. Надо было бы начать заниматся подобным раньше. Сейчас уже время поджимает и препод тоже. Нужно разобрать код, который я практически не понимаю. Там есть некие обьяснения предыдущего автора, но их маловато. А препод в программировании не шарит. В общем код написан для секундомера для лабораторной установки в универе. Заранее извиняюсь, что такой большой код кинул на страницу, но файл не загрузило 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; // разрешить регистр }
|
|
|
|
|
Dec 14 2012, 02:28
|
Группа: Новичок
Сообщений: 4
Регистрация: 13-12-12
Пользователь №: 74 841

|
Цитата(=AK= @ Dec 14 2012, 02:36)  Установите себе редактор Дракон и рисуйте блок-диаграммы для всех функций, начиная с main() . Когда все нарисуете, тогда и "разберете", то есть, поймете как работает. Прикольненько...  Огромное спасибо от нуба. Если есть ещё какие советы очень прошу
|
|
|
|
|
Dec 14 2012, 13:35
|
Группа: Новичок
Сообщений: 4
Регистрация: 13-12-12
Пользователь №: 74 841

|
А в драконе можно просто вкинуть код, чтоб он схему составил?
|
|
|
|
|
Dec 17 2012, 08:55
|
Группа: Новичок
Сообщений: 4
Регистрация: 13-12-12
Пользователь №: 74 841

|
Цитата(kovigor @ Dec 14 2012, 18:22)  Да хоть в драконе, хоть где угодно, выкидывание вам ничего не даст. В этой программе задействованы аппаратные ресурсы МК, так что ни один дракон не растолкует вам, как их использовать и программировать. Начать надо с чтения даташита на МК, а не с неизвестно каких программ ... Я начал учить по книге Белова "Создаем устройства на микроконтролерах", но такое впечатление, что код отличается от того, что написано в книге. З.Ы. И ещё, я конечно понимаю, что вопрос глупый, но что такое "даташит"
Сообщение отредактировал Alex Nebrituy - Dec 17 2012, 08:58
|
|
|
|
|
Dec 17 2012, 15:51
|
Участник
  
Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695

|
Желательно всегда скачивать Datasheet только с сайта производителя, во избежание. В данном случае, с сайта Atmel - ATtiny2313По ссылке MaxiMuz - datasheet не полный (Summary за 2006 г.)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|