Vovan » 11 окт 2005, 20:29
Благодаря 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