|
|
  |
Проблема с прерыванием CAN Rx |
|
|
|
Feb 2 2009, 10:32
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 29-01-09
Из: Moscow
Пользователь №: 44 153

|
Ребята, бъюсь с этим уже неделю, просто достало. Установил прерывание на входящие пакеты по CAN. ------------------------------- CODE // CAN interrupt service routine interrupt [CAN_IT] void can_isr(void) { // Place your code here
CANGIE = 0;
if((CANSIT2 & 1)!=0) // MOB0 сработал? { // for(i=0;i<8;i++) data[i]=CANMSG; // Прочитать сообщение целиком
can_in=1; } toggleLED1_on(); delay_ms(50); toggleLED1_off(); // Визуальный тест } ----------------------------------------- В теле основной программы в while вставил CODE /****************************************************************/ /* CAN initialization */ /****************************************************************/
void can_init (unsigned char BT_1,unsigned char BT_2,unsigned char BT_3) { unsigned char i=0; unsigned char j=0; //reset CAN interface CANGCON |= (1<<SWRES); //reset all MObs for (i=0; i<15; i++) { CANPAGE = (i<<4); //select MOb CANCDMOB = 0; //disable MOb CANSTMOB = 0; //clear status CANIDT1 = 0; //clear ID CANIDT2 = 0; CANIDT3 = 0; CANIDT4 = 0; CANIDM1 = 0; //clear mask CANIDM2 = 0; CANIDM3 = 0; CANIDM4 = 0; for (j=0; j<8; j++) CANMSG = 0; //clear data }
// set CAN -> baudrate // bit timing -> datasheet 264 (check table) // 250Kbps 8MHz cpu-clk CANBT1 = BT_1; // 0x00; CANBT2 = BT_2; // 0x0C; CANBT3 = BT_3; // 0x60; //start CAN interface //CANGCON = (1<<ENASTB); // clear CAN interrupt registers CANGIE = 0xA0; // none interrupts CANIE1 = 0; // none interrupts on MObs CANIE2 = 0x03; CANEN2 = 0x03; // 0x03 = 2 mail // 0x01 = 1 mail CANSIT1 = 0; CANSIT2 = 0; //start CAN interface CANGCON = (1<<ENASTB);
//wait until module ready while (!(CANGSTA & (1<<ENFG))); }
-------------------------------------------- CODE void my_can_rx_unlim_time_11 (unsigned long my_id, unsigned char MyIDfiltr_4, unsigned char MyIDfiltr_3, unsigned char MyIDfiltr_2, unsigned char MyIDfiltr_1){
unsigned char i; CANHPMOB=0; //select MOb0 CANPAGE = 0x00; //select MOb0
//clear MOb flags //CANSTMOB = 0;
my_id *= 2; // умножение на 2 CANIDT1 = (unsigned char) (my_id>>4); CANIDT2 = (unsigned char) (my_id<<4); // set mask in order to receive only the message with the ID CANIDM4 = MyIDfiltr_4; // CANIDM3 = MyIDfiltr_3; // CANIDM2 = MyIDfiltr_2; // CANIDM1 = MyIDfiltr_1; // // enable extended ID //CANIDM4 |= (1<<IDEMSK); // enable reception and CANCDMOB=(1<<CONMOB1) | (0<<IDE); // wait until reception is complete // while(!(CANSTMOB&(1<<RXOK))); // reset flag // CANSTMOB &= ~(1<<RXOK); va=CANIDT1; vb=CANIDT2;
return; }
// Поехали..
main{
while(1){
// № 1 ################################################################################ ####################### // Здесь принимаем только один единственный ID 0x321. my_can_rx_unlim_time_11(0x321,248,255,255,255); // Если сработало прерывание CAN Rx if((CANSTMOB&(1<<RXOK))){ // wait until reception is complete //while(!(CANSTMOB&(1<<RXOK))); // reset flag CANSTMOB &= ~(1<<RXOK); } can_in=0; // Снимаем флаг прерывания. CANGIE = 0xA0; // Разрешаем прерывание CAN Rx. } //################################################################################ #########################
}
}
------------------------------------------------------- Вот это все работает, но если я функции while последовательно вставлю еще одну проверку на другой пакет: CODE // № 2 ################################################################################ ####################### // Здесь принимаем только один единственный ID 0x325. my_can_rx_unlim_time_11(0x325,248,255,255,255); // Если сработало прерывание CAN Rx if((CANSTMOB&(1<<RXOK))){ // wait until reception is complete //while(!(CANSTMOB&(1<<RXOK))); // reset flag CANSTMOB &= ~(1<<RXOK); } can_in=0; // Снимаем флаг прерывания. CANGIE = 0xA0; // Разрешаем прерывание CAN Rx. } //################################################################################ ######################### То прерывание срабатывает только на этот последний ID Под номером 2, а код под номером 1 не срабатывает на прерывание. Я уже запарился, не могу проверить (выловить) разный ID.
Причина редактирования: Исходники нужно заключать в соответствующие тэги code или codebox
|
|
|
|
|
Feb 2 2009, 14:30
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 29-01-09
Из: Moscow
Пользователь №: 44 153

|
Вторую тему создал по CAN. Неужели никто не работает с этой шиной?? Ни одного ответа. Или нормальные герои не ходят в раздел для начинающих, хотя я бы не назвал себя начинающим, но структура форума такова, что в другом разделе не дает создать тему новенькому на форуме.
Сообщение отредактировал Simok - Feb 2 2009, 14:31
|
|
|
|
|
Feb 2 2009, 18:30
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Simok @ Feb 2 2009, 17:30)  Вторую тему создал по CAN. Неужели никто не работает с этой шиной?? Работают, работают! Только ведь Вы же не про "шину" спрашиваете а про то, что у Вас какой-то код не работает. Причем для неназванного чипа, но похоже, что CAN-AVR которую по нынешним временам использовать нет никакого смысла ввиду убогого функционала и неадекватной стоимости оставшейся с прошлого века. Потерпите, кто-нибудь возможно и потянется.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 3 2009, 10:54
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 29-01-09
Из: Moscow
Пользователь №: 44 153

|
Цитата(zltigo @ Feb 2 2009, 21:30)  Работают, работают! Только ведь Вы же не про "шину" спрашиваете а про то, что у Вас какой-то код не работает. Причем для неназванного чипа, но похоже, что CAN-AVR которую по нынешним временам использовать нет никакого смысла ввиду убогого функционала и неадекватной стоимости оставшейся с прошлого века.
Потерпите, кто-нибудь возможно и потянется. Понял, спасибо. Да, действительно, чип не указал. Камень у меня AT90CAN128. По поводу проблемы немного поясню короче и потолковее исходя из последних опытов. Проблема в прерывании CAN на входящие пакеты. Если в цикл while я вставляю функцию на получение только определенного ID, то все прекрасно работает, правда приходится прерывание останавливать при его возникновении и снова запускать, иначе всегда висит в прерывании, если оно сработало. Но если я вставлю подряд две функции и каждой назначен маской уникальный ID, то срабатывает прерывание исключительно на последнюю функцию. Результат, не могу использовать прерывание для нескольких разных ID (их нельзя указать одной маской). Потом непонятно, почему прерывание не срабатывает само по себе, не вставляя функцию Rx в цикл. Хотя например прерывание от ноги (кнопки) срабатывает как и положено, само по внешнему сигналу, и для него нет необходимости вставлять код функции в тело Main, хватает кода и в самом прерывании. Почему не так в CAN прерывании, мне не понятно. По логике, оно должно было срабатывать при поступлении нужного сообщения само, а нет, надо делать запрос на получение в теле программы. Еще загвоздка в том, что если в само прерывание вставить функцию отправки или получения сообщения, то оно зависает через несколько пакетов, что тоже обламывает. Правда есть еще таймер от CAN, может оно решает подобные проблемы??
Сообщение отредактировал Simok - Feb 3 2009, 10:56
|
|
|
|
|
Feb 4 2009, 14:11
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 29-01-09
Из: Moscow
Пользователь №: 44 153

|
Камень AT90CAN128
Получаю по CAN сообщения с одним ID, остальные по маске не проходят. А мне нужно параллельно знать, поступают ли другие сообщения в сети в принципе. Как в таком случае узнать, что на линии еще есть другие сообщения?
Сообщение отредактировал Simok - Feb 4 2009, 14:12
|
|
|
|
|
Mar 1 2009, 12:14
|
Группа: Новичок
Сообщений: 1
Регистрация: 16-12-08
Пользователь №: 42 532

|
Вы используете только MOB0, а их 15 штук, и для каждого полный набор регистров. Где выбор MOB? перед чтением д.б. CANPAGE=new_MOb; Обязательно в прерывании: BYTE oldMob=CANPAGE; //запомнить ... CANPAGE=oldMob; //востановить После срабатывания прерывания нужно снова настраивать MOb на прием и уберите delay_ms(50) - в прерывании это ПРОТИВОЗАКОННО! .
|
|
|
|
|
Mar 8 2009, 20:15
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 29-01-09
Из: Moscow
Пользователь №: 44 153

|
Цитата(andreyasm @ Mar 1 2009, 15:14)  Вы используете только MOB0, а их 15 штук, и для каждого полный набор регистров. Где выбор MOB? перед чтением д.б. CANPAGE=new_MOb; Обязательно в прерывании: BYTE oldMob=CANPAGE; //запомнить ... CANPAGE=oldMob; //востановить После срабатывания прерывания нужно снова настраивать MOb на прием и уберите delay_ms(50) - в прерывании это ПРОТИВОЗАКОННО! .  Прерывание настроено на два ящика, но я не пойму, как выловить это прерывание... Я пробовал и MOB0 и MOB1.. Я просто не въеду в эти ящики и прерывания. Если прерывание например на ногу порта, то оно и срабатывает независимо от хода программы, когда на ноге есть уровень. А здесь никаких действий. Вот что меня волнует. Прерывание срабатывает конечно, но только если его подтолкнуть, т.е. в коде программы надо вставлять функцию чтения ящиков, а это напрягает, если программа например находится в ожидании действий пользователя, то приходиться туда же повторно вставлять функцию чтения ящиков в While и break по условию. Если прерывание идет по MOB0, то прерывание должно срабатывать, т.е. должен исполняться код внутри прерывания, а этого не происходит. Непривычно как то, другие прерывания срабатывают, как положено, а это что за прерывание, если так и так нужно его "подталкивать", и это не зависимо от выбора ящика, а если еще и проводить проверку на получение, то пока не придет хотя бы один пакет, программа дальше работать не будет. Пришлось все пока реализовать засчет собственных конструкции, но хотелось бы компактнее и без лишних переменных. Читаешь описание протокола CAN, все настолько просто и ясно, начинаешь реализовывать и получашь не то, что думаешь. Все это касабельно прерывания, без него все просто и ясно.
|
|
|
|
|
Mar 10 2009, 20:57
|
Группа: Новичок
Сообщений: 2
Регистрация: 24-10-05
Пользователь №: 10 057

|
Я работаю с CAN очень плотно, но использую связку SJA1000 + m8515. И к тому-же пишу только на ассемблере. Если тебе поможет, то могу сбросить исходник ( на asm-e ) , как у меня организована фильтрация по ID
|
|
|
|
|
Mar 17 2009, 21:20
|
Участник

Группа: Новичок
Сообщений: 16
Регистрация: 29-01-09
Из: Moscow
Пользователь №: 44 153

|
Цитата(Strateg @ Mar 10 2009, 23:57)  Если тебе поможет, то могу сбросить исходник ( на asm-e ) , как у меня организована фильтрация по ID Был бы признателен, может этот пинок направит меня в нужное русло.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|