CAN на AT90CAN128 Получилось добиться работы с одним прибором в режиме listening. Прибор постоянно сыпет в линию данные. Принятые данные ожидаемые и корректные. Проблема в том, что не получается работать не в listening. Вытекающая проблема – не получается идентифицировать устройства, если их более одного. В регистрах CANIDT1 и CANIDT2 одно и тоже значение, не зависящее от сетевого адреса. В регистрах CANIDT3 и CANIDT4 бессистемный мусор. Приятно, что прерывание происходит именно от Mob0. Если не разрешать это прерывание, то ничего не работает. Прошу разъяснить определения. Чем отличается reception от frame buffer reception. Банальная эрудиция подсказывает, что в моём случае надо выбрать второй вариант. Но если разрешить прерывание Frame Buffer, зависает весь контроллер, вероятно по причине того, что контроллер постоянно входит в прерывание CAN.
void CAN_Init(unsigned char set_brp, unsigned char set_prs, unsigned char set_phs1, unsigned char set_phs2)
{
CAN_CONTROLLER_RESET; //сброс общего регистра управления CAN
CANBT1 = 0x06;
CANBT2 = 0x0C;
CANBT3 = 0x37;
ResetAllMailbox(); //сброс регистров
//Настройка MOB0=RX на прием
CANPAGE = 0x00; //Выбор номера Mob - в данном случае Mob0
CANSTMOB = 0x00; //Очистка регистра состояния Mob
CANCDMOB = 0xD8;
CANIDT4 = 0x00;
CANIDT3 = 0x00;
CANIDT2 = 0x00;
CANIDT1 = 0x00;
CANIDM4 = 0x00; //Принудительный положительный результат сравнени
CANIDM3 = 0x00; //Принудительный положительный результат сравнени
CANIDM2 = 0x00; //Принудительный положительный результат сравнени
CANIDM1 = 0x00; //Принудительный положительный результат сравнени
CANGIE=0xB0; //Разрешение прерываний по приему, по передаче, по общим ошибкам, по ошибкам Mob
CANEN2=0xff; //Разрешить все Mob
CANEN1=0xff;
CANIE2=0x01; //Разрешить прерывания только по Mob0
CANIE1=0x00;
CANHPMOB=0x00; //Установка высшего приоритета для MOb0
CANGCON |= 0x0A; //Разрешить контроллер CAN + Listening Mode
}
#pragma vector=CANIT_vect
__interrupt void can_isr(void)
{
unsigned char *ptr = &Buttons.Right.reg + 2;
union
{
signed int si;
struct
{
unsigned char
lo,
hi;
};
}tmp;
/
// Place your code here
//unsigned char i, flag;
LED1R_On
CANGIE &= (~(1<<ENRX)); // Запретить прерывание по приему
flag = CANSIT2; // чтение регистра состояния прерываний(того где Mob0 и Mob1)
//-----------------------------------------------------
if(flag & (1<<0)) //Если прерывание по Mob0
{
CANPAGE = 0<<4; //Выбор Mob0
for(i = 0; i < 8; i++)
{
*ptr++ = CANMSG; //Считать регистр данных сообщения 8 раз
}
CANPAGE = 0<<4; //Выбор Mob0
CANSTMOB &= ~(1<<RXOK); //сбросить влаг удачного завершения приема
CANCDMOB = 0x80; //Разрешить прием
}
ptr = &Buttons.Right.reg + 2;
tmp.lo = CANIDT1;
tmp.hi = CANIDT2;
if(tmp.si == 18467)
{
Src_NWA_r = tmp.si;
Joystik_X = (signed char)(~*ptr++);
Joystik_Y = (signed char)(~*ptr++);
tmp.lo = CANIDT3;
tmp.hi = CANIDT4;
Trg_NWA_r = tmp.si;
}
if(flag & (1<<1)) //Если прерывание по Mob1
{
CANPAGE = 1<<4; //Выбор Mob1
CANSTMOB &= (~(1<<TXOK)); //Сбросить бит удачного завершения передачи
}
//------------------------------------------------------
CANGIE |= (1<<ENRX); //Разрешить прерывание по приему
}