Благодаря ASin-у, (спасибо ему большое!) программы теперь нормально компилируются и, как сообщает Studio, без единой ошибки! Докопаться нЕ к чему. Однако, hex-файл получается отличным от исходника (????)... ну и это, казалось бы ерунда (мало ли какие-то там цифирки поменялись), но после того как я ентот самый hex заливаю в контроллер - часть программы не работает (а именно от: SIGNAL(SIG_INT0... до: this_move=F;} в приведённой ниже программе), т.е. не работают "бампера". Всё остальное - как часы! . Контроллер ATTINY2313-20PI. Вот ента программа: #include <inttypes.h> #include <avr/io.h> #include <avr/signal.h> #include <avr/interrupt.h> #include <stdlib.h>
// назначение определений для танкового привода #define OUT PORTB #define MOTOR_FR PB7 // вперед-вправо #define MOTOR_BR PB6 // назад-вправо #define MOTOR_BL PB5 // назад-влево #define MOTOR_FL PB4 // вперед-влево
#define IN PIND #define LIGHT_R PD0 #define LIGHT_L PD1 #define BUMPER_F PD2 #define BUMPER_B PD3 #define LED PD6
#define sbi(port,bit) port |= (1<<(bit)) #define cbi(port,bit) port &= ~(1<<(bit)) #define outb(port,bit)
// Возможные режимы движения для танкового привода // R, L - вращение на месте соответственно вправо, влево
enum {STOP, F, FR, FL, B, BR, BL, R, L};
//------------------------------------------------------------------------------ // Задержка t х 10ms //------------------------------------------------------------------------------ #define F_CPU 4000000 #define K_DELAY_10ms F_CPU/6000 void Delay_10ms(unsigned char t) { if (t==0) return; unsigned int i; while (t--) for(i=0;i<K_DELAY_10ms; i++); }
// таблица вероятностей для выбора направления движения, исходя // из текущего направления движения. Добавлены развороты на месте // STOP, F, FR, FL, B, BR, BL, R, L - порядок команд в цепи Маркова unsigned char p[9][9] = { {21,52,52,52,52,52,52,76,100}, {7,43,71,100,100,100,100,100,100}, {7,50,93,100,100,100,100,100,100}, {7,50,57,100,100,100,100,100,100}, {29,29,29,29,56,78,100,100,100}, {36,36,36,36,71,93,100,100,100}, {36,36,36,36,71,78,100,100,100}, {15,40,50,55,55,55,55,85,100}, {15,40,45,55,55,55,55,70,100}, }; // текущее направление движения unsigned char this_move;
//------------------------------------------------------------------------------ // Включение комбинации моторов для движения в заданном направлении // Переделано для таокового привода, добавлены развороты на месте! //------------------------------------------------------------------------------ void go(unsigned char direction){
switch (direction) { case STOP: cbi(OUT, MOTOR_FR); cbi(OUT, MOTOR_BR); cbi(OUT, MOTOR_BL); cbi(OUT, MOTOR_FL); break;
case F: sbi(OUT, MOTOR_FR); cbi(OUT, MOTOR_BR); cbi(OUT, MOTOR_BL); sbi(OUT, MOTOR_FL); break;
case FR: cbi(OUT, MOTOR_FR); cbi(OUT, MOTOR_BR); cbi(OUT, MOTOR_BL); sbi(OUT, MOTOR_FL); break;
case FL: sbi(OUT, MOTOR_FR); cbi(OUT, MOTOR_BR); cbi(OUT, MOTOR_BL); cbi(OUT, MOTOR_FL); break;
case B: cbi(OUT, MOTOR_FR); sbi(OUT, MOTOR_BR); sbi(OUT, MOTOR_BL); cbi(OUT, MOTOR_FL); break;
case BR: cbi(OUT, MOTOR_FR); cbi(OUT, MOTOR_BR); sbi(OUT, MOTOR_BL); cbi(OUT, MOTOR_FL); break;
case BL: cbi(OUT, MOTOR_FR); sbi(OUT, MOTOR_BR); cbi(OUT, MOTOR_BL); cbi(OUT, MOTOR_FL); break;
case R: cbi(OUT, MOTOR_FR); sbi(OUT, MOTOR_BR); cbi(OUT, MOTOR_BL); sbi(OUT, MOTOR_FL); break;
case L: sbi(OUT, MOTOR_FR); cbi(OUT, MOTOR_BR); sbi(OUT, MOTOR_BL); cbi(OUT, MOTOR_FL); break; } }
//------------------------------------------------------------------------------ // Выбор направления движения в следующем шаге по таблице вероятностей //------------------------------------------------------------------------------ unsigned char next_move(void){ unsigned char pp, i;
pp = rand()/327; // получаем случайное число 0..99 for (i=0;i<9;i++){ // ищем соответствие в таблице вероятностей if (p[this_move][i] > pp) break; } this_move = i; // записываем новое полученное направление как текущее return(i); }
//------------------------------------------------------------------------------ // Обработка прерывания от переднего бампера (INT0 = PD2) //------------------------------------------------------------------------------ SIGNAL(SIG_INT0) { if(this_move==FR) go(BL); if(this_move==FL) go(BR); else go(B);
// горим при обработке прерывания от бампера
cbi(PORTD, LED); // зажигаем Delay_10ms(60); // отъезд в течение 2.5 х 2 сек Delay_10ms(60); sbi(PORTD, LED); // гасим
// не горим
this_move=B; }
//------------------------------------------------------------------------------ // Обработка прерывания от заднего бампера (INT1 = PD3) //------------------------------------------------------------------------------ SIGNAL(SIG_INT1) { if(this_move==BR) go(FL); if(this_move==BL) go(FR); else go(F);
// горим при отработке прерываний от бамперов
cbi(PORTD, LED); // зажигаем Delay_10ms(60); // отъезд в течение 2.5 х 2 сек Delay_10ms(60); sbi(PORTD, LED); // гасим
// не горим
this_move=F; }
//------------------------------------------------------------------------------ // "Случайное блуждание" //------------------------------------------------------------------------------ unsigned char walk(void){ // этот цикл организует "свободное блуждание" пока // нет сигнала ни от одного из датчиков освещенности while((bit_is_set(IN, LIGHT_R)) && (bit_is_set(IN, LIGHT_L))){ go(next_move()); // получаем следующее направление движения и
// подмигиваем при каждом цикле работы основного цикла программы
cbi(PORTD, LED); // зажигаем светодиод на PD4 Delay_10ms(45); // движемся в этом направлении 2.5 сек sbi(PORTD, LED); // гасим светодиод на PD4 Delay_10ms(45); // движемся в этом направлении 2.5 сек } // этот цикл организует движение на свет, пока // есть сигнал хотя бы от одного из датчиков освещенности while((bit_is_clear(IN, LIGHT_R)) || (bit_is_clear(IN, LIGHT_L))){ if((bit_is_clear(IN, LIGHT_R)) && (bit_is_clear(IN, LIGHT_L))) go(F); else if(bit_is_clear(IN, LIGHT_R)) go(FR); else if(bit_is_clear(IN, LIGHT_L)) go(FL); }
return(0); }
//------------------------------------------------------------------------------ // Главная программа //------------------------------------------------------------------------------ int main(void) { DDRB = 0xff; // назначаем все линии порта B на выход PORTB = 0x00; // и устанавливаем на них низкий уровень
DDRD = 0x40; // назначаем все линии порта D на вход, кроме PD6 PORTD = 0xbf; // подключаем внутренние нагрузочные резисторы, кроме PD6
// разрешаем прерывания int0 и int1 outb(GIMSK, (1<<INT0)|(1<<INT1));
// запрос на прерывание - по спадающим фронтам на int0 и int1 outb(MCUCR, (1<<ISC01)|(1<<ISC11));
// разрешаем прерывания sei();
// Задержка на старте 5 сек // чтобы успеть отбежать в сторону
// для подсчета числа миганий в цикле unsigned char i;
for (i=0;i<5;i++){ // Подмигиваем пять раз cbi(PORTD, LED); // Зажигаем LED Delay_10ms(25); // пауза sbi(PORTD, LED); // гасим LED Delay_10ms(25); // пауза }
// запускаем главный цикл while(1) walk();
} ___________ С уважением Vovan
|