Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CAN на AT90CAN128
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Д_М
Приветствую!
Устройство на базе AT90CAN128 новое и нет 100% уверенности, что в нём отсутствуют аппаратные ошибки. При тщательном изучении аппаратных ошибок не выявлено.
Имеется заведомо работающий датчик с CAN, который постоянно сыпет в линию CAN своё значение. Имеется конвертер, который получает то, что кидает датчик и тупо передаёт по RS232.
Цифры осмысленные, расшифровке поддаются. Коечная цель сделать так, чтобы устройство на базе AT90CAN128 воспринимало то, что кидает в линию датчик.
На текущий момент получается так, что устройство на базе AT90CAN128 "подвешивает" датчик после инициализации CAN контроллера в устройстве на базе AT90CAN128. Да так подвешивает, что датчик возобновляет нормальную работу только после передёргивания питания. Специально сделал задержку инициализации CAN на 10 секунд. Когда на линии CAN сидят три устройства - датчик, конвертер, контроллер вижу, как сыпятся посылки от датчика. Прошло 10 секунд, произошла инициализация датчика, посылки прекратились. Методом исключения было установлено, что контроллер вешает датчик, когда в инициализации делается только сброс контроллера, задание скорости, включение CAN контроллера. Если в процедуре инициализации убрать задание скорости, но оставить включение 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;
*/

CANBT1 = 0x0E;
CANBT2 = 0x04;
CANBT3 = 0x13;

CANGCON |= 0x02;             //Разрешить контроллер CAN
}

Значение CANBT взяты из мануала AT90CAN128. Пробовал оба значения для данного кварца. Результат один. Конечно можно предположить, что датчик неправильный. Но ведь другое CAN устройство с этим датчиком подружилось.
Пробовал делать передачу на моём контроллере, используя вот этот пример http://forum.cxem.net/index.php?app=core&a...ttach_id=137917 Смущает, что светодиод, подключенный на линию CAN горит ровным свечением, без мерцания. Когда я цеплял тот же светодиод на линию CAN, когда был подключен датчик и конвертер, наблюдалось характерное мерцание светодиода.
Заранее благодарен за советы!
KRS
Цитата(Д_М @ Jun 29 2016, 10:41) *
Если в процедуре инициализации убрать задание скорости, но оставить включение CAN контроллера, то датчик не подвешивается.

Так вы либо скорость неправильно задаете, в итоге CAN128 может портить посылки кода выдает на линию например ошибки...
либо проблемы со схемой (с драйвtром CAN)
может быть и с шиной проблемы - шина не должна быть звездой и с короткими стабами и терминаторами 120 ом по краям...
Да и еще проверить не перевернута ли шина...

Можно попробовать в listen only режиме пакеты принимать...
Д_М
Цитата(KRS @ Jun 29 2016, 11:27) *
Так вы либо скорость неправильно задаете, в итоге CAN128 может портить посылки кода выдает на линию например ошибки...
либо проблемы со схемой (с драйвtром CAN)
может быть и с шиной проблемы - шина не должна быть звездой и с короткими стабами и терминаторами 120 ом по краям...
Да и еще проверить не перевернута ли шина...

Можно попробовать в listen only режиме пакеты принимать...


Суммарная длина линии CAN не более метра. На такой длине звезда не может быть источником проблем. Установлен один терминатор 120 Ом. Без него не работало бы. Интереса ради пробовал менять полярность на контроллере. Если неправильно, то он не мешает жить другим. Если я правильно понял, то сама по себе инициализация CAN контроллера не должна вызывать влияния на линию? Однако на практике не совсем так. Попробовал включить Чтение. В этом режиме контроллер не завешивает датчик. Даже срабатывает обработчик прерывания. Чувствует наличие / отсутствие CAN. Пробовал менять полярность. При иной полярности нет прерывания CAN. Пробовал оба значения CANBT, предлагаемые мануалом, для данного кварца. В обоих случаях значение регистра прерывания CAN CANGIT одно и тоже 0xB8. Bit 3 – SERG: Stuff Error General 1 - stuff error interrupt: detection of more than 5 consecutive bits with the same polarity. То есть временные параметры заданы неверно. А это самая нудная часть CAN. Есть ли какие стандартные значения?
pavel-pervomaysk
Была задача сделать мост UART 500k <-> CAN 125 kBps.
Долго извращался я с такой-же проблемой, но нужно внимательно "курнуть" даташит на английском.
Русская версия мне была понятной но сути в ней не описано.

В итоге сделал так:
Настраиваем фильтр на каждый приемный MAILBOX, выбираем RX/TX Mailboxes, полная инициализация CAN модуля.
Прием только по прерыванию, приняли CAN сообщение, обработали и в UART его.
Аналогичто все обратно.

Инициализация модуля. Это пример для M16M1, отличие только в количестве Mailbox 0...5, у CAN32/64/128 их 15 штук.

CODE
;----------------------;
can_init: ; Initialization CAN module
;---- CANGCON ---------;
; ABRQ OVRQ TTC SYNTTC LISTEN TEST ENA/STB SWRES
ldi tmp,0b00000010 ; 02 - enabled!
sts CANGCON,tmp ; Can General Control Register
;---- CANGIT-----------;
; CANIT BOFFIT OVRTIM BXOK SERG CERG FERG AERG
ldi tmp,0b00000000 ;
andi tmp,0x7F ; 7-th bit read only!
sts CANGIT,tmp ; Can General Interrupt Register
;---- CANGIE ----------;
; ENIT ENBOFF ENRX ENTX ENERR ENBX ENERG ENOVRT
ldi tmp,0b10100000 ; TX & RX interrupt! было 1011 0000
sts CANGIE,tmp ; Can General Interrupt Enable Register
;-------------------------------------------------------------------------------
; Interrupt Enable & Disable for Mob 5...0

;Mob 5,4,3,2,1,0 ; IEMOB5 IEMOB4 IEMOB3 IEMOB2 IEMOB1 IEMOB0
ldi tmp,0b100000 ; Mob5,0 in interrupt mode!
andi tmp,0x3F ;
sts CANIE2,tmp ; Can Enable Interrupt MOb Register
sts CANIE1,zero ; Can Enable Interrupt MOb Register

;--------------------------------------------------------------------------------
; Read only!
; - OVRG - TXBSY RXBSY ENFG BOFF ERRP
;ldi tmp,0b00000000 ;
;andi tmp,0x5F ; bits 7,5 not used!
;sts CANGSTA,tmp ; Can General Status Register

; Enable or Disable Mob 5...0 ;
; Read only! 0 - Disabled; 1 - Enabled;
; bit provides the availability of the MOb.
;Mob 5,4,3,2,1,0 ; ENMOB5 ENMOB4 ENMOB3 ENMOB2 ENMOB1 ENMOB0; CANEN2
;lds tmp,CANEN2 ; Can Enable MOb Register


; CAN Status Interrupt MOb Registers
; read only!
; - - SIT5 SIT4 SIT3 SIT2 SIT1 SIT0
;lds tmp,CANSIT2 ;



rcall baud_500k ; CAN speed baudrate 500k!


;----------------------;
; CAN Timer Clock Period: 0,500 us
; TPRSC7 TPRSC6 TPRSC5 TPRSC4 TPRSC3 TPRSC2 TRPSC1 TPRSC0
; 16 mhz timer timer ovf interrypt!
; (255 = (255*32.7ms)) = 8338ms
ldi tmp,30 ; 30 make ~ 1s timer interrupt
sts CANTCON,tmp ; Can Timer Control Register
;----------------------;
; CANTIM7 CANTIM6 CANTIM5 CANTIM4 CANTIM3 CANTIM2 CANTIM1 CANTIM0
ldi tmp,0b00000000 ;
sts CANTIML,tmp ; Can Bit Timer RegisterL
; CANTIM15 CANTIM14 CANTIM13 CANTIM12 CANTIM11 CANTIM10 CANTIM9 CANTIM8
ldi tmp,0b00000000 ;
sts CANTIMH,tmp ; Can Bit Timer RegisterH
;----------------------;
; TIMTTC7 TIMTTC6 TIMTTC5 TIMTTC4 TIMTTC3 TIMTTC2 TIMTTC1 TIMTTC0
ldi tmp,0b00000000 ;
sts CANTTCL,tmp ; Can TCC Timer RegisterL
; TIMTTC15 TIMTTC14 TIMTTC13 TIMTTC12 TIMTTC11 TIMTTC10 TIMTTC9 TIMTTC8
ldi tmp,0b00000000 ;
sts CANTTCH,tmp ; Can TCC Timer RegisterH

;----------------------;
; TEC7 TEC6 TEC5 TEC4 TEC3 TEC2 TEC1 TEC0
ldi tmp,0b00000000 ;
sts CANTEC,tmp ; Can Transmit Error Counter Register
; REC7 REC6 REC5 REC4 REC3 REC2 REC1 REC0
ldi tmp,0b00000000 ;
sts CANREC,tmp ; Can Receive Error Counter Register

;----------------------;
; HPMOB3 HPMOB2 HPMOB1 HPMOB0 CGP3 CGP2 CGP1 CGP0
ldi tmp,0b01010000 ; MOB5 - RX
sts CANHPMOB,tmp ; Can Highest Priority MOb Register
;----------------------;
; статус временной ометки CAN 0 ... 65535
; TIMSTM7 TIMSTM6 TIMSTM5 TIMSTM4 TIMSTM3 TIMSTM2 TIMSTM1 TIMSTM0
ldi tmp,0x00 ;
sts CANSTML,tmp ; Can Time Stamp RegisterL
; TIMSTM15 TIMSTM14 TIMSTM13 TIMSTM12 TIMSTM11 TIMSTM10 TIMSTM9 TIMSTM8
ldi tmp,0x00 ;
sts CANSTMH,tmp ; Can Time Stamp RegisterH

;----------------------;
rcall clear_all_mobs ; Clear all mobs buffer!
clr flags ;
ret ;


Настройка скоростей, я использую 16МГц кварц.

CODE
;----------------------;
; CAN Bit Timing Registers 1,2,3
; CAN 8 bit 50.000 Kbps 16 MHz
; Sample Point at 75%
baud_50k:
ldi tmp,0x26 ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret
;----------------------;
; CAN 8 bit 75.000 Kbps 16 MHz
; Sample Point at 75%
baud_75k:
ldi tmp,0x1C ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret
;----------------------;
; CAN 8 bit 83.333 Kbps 16 MHz ( 16 0C 37 old )
; Sample Point at xx.x%
baud_83k:
ldi tmp,0x16 ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret
;----------------------;
; CAN 8 bit 100 Kbps 16 MHz
; Sample Point at 75%
baud_100k: ;
ldi tmp,0x12 ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret
;----------------------;
; CAN 8 bit 125 Kbps 16 MHz
; Sample Point at 75%
baud_125k: ;
ldi tmp,0x0E ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret ;
;----------------------;
; CAN 8 bit 200 Kbps 16 MHz
; Sample Point at 75%
baud_200k: ;
ldi tmp,0x08 ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret ;
;----------------------;
; CAN 8 bit 250 Kbps 16 MHz
; Sample Point at 75%
baud_250k: ;
ldi tmp,0x0E ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x04 ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x13 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret ;
;----------------------;
; CAN 8 bit 500 Kbps 16 MHz
; Sample Point at 75%
baud_500k: ;
ldi tmp,0x02 ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x0C ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x37 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret ;
;----------------------;
; CAN 8 bit 1000 Kbps 16 MHz
; Sample Point at 75%
baud_1m: ;
ldi tmp,0x02 ;
sts CANBT1,tmp ; Can Bit Timming Register
ldi tmp,0x04 ;
sts CANBT2,tmp ; Can Bit Timming Register
ldi tmp,0x13 ;
sts CANBT3,tmp ; Can Bit Timming Register
ret ;
;----------------------;
KRS
Цитата(Д_М @ Jun 29 2016, 14:26) *
Если я правильно понял, то сама по себе инициализация CAN контроллера не должна вызывать влияния на линию?

Как это не должна?
если CAN проиничен не в listen only mode, скорость задана - CAN обязан выдавать на линию сигналы АСК в случае приема корректного фрейма или ошибки... (настройки фильтров и мейлбокосов на это не влияют!)


Цитата(Д_М @ Jun 29 2016, 14:26) *
А это самая нудная часть CAN. Есть ли какие стандартные значения?

Там - все просто, надо только внимательно прочитать как формируются биты!
И учесть что в регистрах хранится значение на 1 меньше...

Например здесь все хорошо расписано
http://www.nxp.com/files/microcontrollers/...note/AN1798.pdf

Д_М
Приветствую!
Получилось добиться работы с одним прибором в режиме listening. Прибор постоянно сыпет в линию данные. Принятые данные ожидаемые и корректные. Проблема в том, что не получается работать не в listening. Вытекающая проблема – не получается идентифицировать устройства, если их более одного. В регистрах CANIDT1 и CANIDT2 одно и тоже значение, не зависящее от сетевого адреса. В регистрах CANIDT3 и CANIDT4 бессистемный мусор. Приятно, что прерывание происходит именно от Mob0. Если не разрешать это прерывание, то ничего не работает. Прошу разъяснить определения. Чем отличается reception от frame buffer reception. Банальная эрудиция подсказывает, что в моём случае надо выбрать второй вариант. Но если разрешить прерывание Frame Buffer, зависает весь контроллер.

CODE
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); //Разрешить прерывание по приему
}

Во вложении полный файл.

Заранее благодарен!
pavel-pervomaysk
CAN контроллер у AT90CAN очень таки неплох, если с ним разобраться...
15 маилбоксов.

Внимательно почитать надо про CANPAGE.
Рулится все через него.
Очень хотелось бы чтобы было как в нормальных процессорах типа NEC, своя отдельная область с произвольным доступом, но нет тут такого.

Я настравиваю 1 на передачу
Следующими настраиваю фильтр для каждого принимающего маилбокса!
Прием работает по прерыванию.

Сработало прерывание, проверил забрал данные с маилбокса.
CODE
;----------------------;
can_handler: ; CAN Transfer Complete or Error
push tmp ;
in tmp,SREG ;
push tmp ;
out TCNT0,zero ; Clean TCNT0
lds temp,CANPAGE ; Store CANPAGE
;----------------------;
lds tmp,CANSIT2 ; MOB1 RX interrupt!
sbrc tmp,SIT5 ; skip if SIT5 =0
rcall _crxi ; SIT5?1{MOB5_interrupt}
;----------------------;
sts CANPAGE,temp ; Restore CANPAGE
pop tmp ;
out SREG,tmp ;
pop tmp ;
reti ; return from interrupt


;----------------------;
_crxi: ; CAN RX MOB in interrupt mode!
inc mode ;
sbi canlp,crxl ; Can RX Led ON;
ldi tmp,mob5 ; Select MOB5
sts _rmob,tmp ;
sts CANPAGE,tmp ; SET MOB5
sts CANSTMOB,zero ; clear status register
rcall read_mobx ; READ MOB5, save in RAM!
lds tmp,CANCDMOB ; Load register
ori tmp,RXmes ; SET RX flag!
sts CANCDMOB,tmp ; save register
;cbi canlp,crxl ; Can RX Led OFF;
ret ; return
;----------------------;

;--- Read MOB 8 bytes ;
; save in RAM (_CRXA) ;
read_mobx: ; read data from MOB area and save in RAM
push tmp ; Save tmp in STACK
push loop2 ; Save Loop2 in STACK
push yl ; Save YL in STACK
push yh ; Save YH in STACK
;----------------------;
clr loop2 ;
ldi yl,low (_CRXA) ; Load address
ldi yh,high(_CRXA) ; can_rx Array space in RAM
ldi loop,8 ; data bytes length
;----------------------;
rmc: ; Read_mob_cycle <----|
lds tmp,_rmob ; |
or loop2,tmp ; Mob number (0...5) |
sts CANPAGE,loop2 ; 0...7 |
lds tmp,CANMSG ; tmp=CANMSG with pointer loop2 |
st y+,tmp ; save in SDRAM with pointer Y tmp |
inc loop2 ; loop2 = +1 |
dec loop ; loop=-1 |
brne rmc ; -----------------------------------|
;----------------------;
pop yh ;
pop yl ;
pop loop2 ;
pop tmp ;
ret ; return
;----------------------;

;----------------------;




Что можно сделать на этом проце не напрягаясь:
Принимаит 14 различных "отфильтрованных" ID в прерывании, обрабатывать их, отвечать на них.
Больше 16 ID стречается только в приборных панелях автомобилей 32-64.
Д_М
Спасибо, что ответили!
Для начала мне хотелось бы разобраться с технологией CAN. В моём случае имеющиеся у меня устройства постоянно сыпят посылки в линию. Независимо от того, надо оно кому-то, или нет. В этом и заключается главное отличие CAN от других интерфейсов, где всё строится по принципу запрос-ответ. Из этого вытекает вопрос - какой надо выбрать режим при инициализации MailBox?

– 00 - disable.
– 01 - enable transmission.
– 10 - enable reception.
– 11 - enable frame buffer reception

И далее инициализация CAN. Какие разрешить прерывания?
pavel-pervomaysk
Настроили CAN модуль.

19.11.2 CAN MOb Control and DLC Register - CANCDMOB
CONMOB1 CONMOB0 RPLV IDE DLC3 DLC2 DLC1 DLC0


Bits 7;6;

00 - disable;

01 - enable transmission.

Отправляем подготовленный маилбокс

;ID11
ldi tmp,0x48 ; High nibble (4-11bit);(5-29bit); low nibble&7(DLC)
;ID29
ldi tmp,0x58 ; High nibble (4-11bit);(5-29bit); low nibble&7(DLC)
и ждем пока установится TXOK в регистре CANSTMOB


10 - перезапись при приеме сообщений маилбокса
11 - приняли сообщение, и пока его не обработаем, оно там будет сидеть.

Посоветую еще купить CAN анализатор, очень пригодится, если планируешь работать с шиной.
Ато читаю что сообщения друг другу посылаются хаотично - уши заворачиваются.... biggrin.gif
Д_М
Пересмотрел все примеры программ, которые мне удалось найти. Кое-что "надёргал" и повставлял в мою программу. А результат прежний - работает только в listening. Ниже инициализация и обработчик прерывания.

CODE
void CAN_Init(unsigned char set_brp, unsigned char set_prs, unsigned char set_phs1, unsigned char set_phs2)
{
unsigned char num_channel, num_data;

TxCAN_DDR = 0;
RxCAN_DDR = 0;
TxCAN = 1;
CANGCON |= MSK_CANGCON_GRES; // reset CAN
CANGIT = CANGIT; // reset all flags

// reset all mailboxes
for(num_channel = 0; num_channel < 15; num_channel++)
{
CANPAGE = num_channel << 4;
CANCDMOB = CH_DISABLE;
CANSTMOB = 0;
CANIDT1 = 0;
CANIDT2 = 0;
CANIDT3 = 0;
CANIDT4 = 0;
CANIDM1 = 0;
CANIDM2 = 0;
CANIDM3 = 0;
CANIDM4 = 0;
for(num_data = 0; num_data < 8; num_data++) CANMSG = 0;
}

// setup bit timing at 250k with 16 MHz crystal
CANBT1 = 0x06;
CANBT2 = 0x0C;
CANBT3 = 0x37;
//CANGCON |= MSK_CANGCON_ENA; // Разрешить контроллер CAN
CANGCON |= 0x0A; // Разрешить контроллер CAN + Listening Mode

// Channel 0 init
CANPAGE = (0 << 4); // CHNB=0x00; select channel 0
CANSTMOB = 0x00; // reset channel status
CANCDMOB = CH_DISABLE; // reset control and dlc register

CANIDT4 = 0x00;
CANIDT3 = 0x00;
CANIDT2 = 0x00;
CANIDT1 = 0x00;

CANIDM4 = 0x00; // Принудительный положительный результат сравнени
CANIDM3 = 0x00; // Принудительный положительный результат сравнени
CANIDM2 = 0x00; // Принудительный положительный результат сравнени
CANIDM1 = 0x00; // Принудительный положительный результат сравнени

// Channel 0 configuration
CANIDT4 &=~0x04; // clear bit rtr in CANIDT4.
CANCDMOB |= DLC_MAX; // Reception 8 bytes.*/
CANCDMOB |= CH_RxENA; // Reception enabled without buffer.
CANCDMOB |= CH_ID29BIT; // CAN standard rev 2.0 B (identifiers length = 29 bits).

CANEN2 |= (1 << 0); // channel 0 enable
CANIE2 = 1; // channel 0 interrupt enable
CANGIE = ((1<<ENRX)|(1<<ENIT)); // Can_Rx & IT enable
//CANGIE = 0x84;// CAN General Interrupt Enable Register Bit 2 – ENBX: Enable Frame Buffer Interrupt
}

#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;

//CANGIE &= (~(1<<ENRX)); // Запретить прерывание по приему

Buttons.Left.reg = CANGSTA;
Buttons.Right.reg = CANGIT;

flag = CANSIT2; // чтение регистра состояния прерываний(того где Mob0 и Mob1)
if(flag & (1<<0)) //Если прерывание по Mob0
{
CANPAGE = 0<<4; //Выбор Mob0
for(i = 0; i < 8; i++)
{
*ptr++ = CANMSG; //Считать регистр данных сообщения 8 раз
}
CANSTMOB &= ~(1<<RXOK); //сбросить влаг удачного завершения приема
}

ptr = &Buttons.Right.reg + 2;
tmp.lo = CANIDT1;
tmp.hi = CANIDT2;

if(tmp.si == 18466)
{
Joystik_X = (signed char)(~*ptr++);
Joystik_Y = (signed char)(~*ptr++);
}

if(tmp.si == 18467)
{
Src_NWA_r = (signed char)(~*ptr++);
Trg_NWA_r = (signed char)(~*ptr++);
}

CANPAGE = (0 << 4);
CANSTMOB=0x00; // reset channel 0 status
CANEN2 |= (1 << 0); // channel 0 enable
CANCDMOB = DLC_MAX; // receive 8 bytes
CANCDMOB |= CH_RxENA; // Reception enabled without buffer.
CANCDMOB |= CH_ID29BIT; // CAN standard rev 2.0 B (identifiers length = 29 bits).
CANGIT = CANGIT; // reset all flags

//CANGIE |= (1<<ENRX); //Разрешить прерывание по приему
}

Непонятно, почему программа одинаково работает как в 11 бит, так и в 29 бит. Как мне представляется, то если этот параметр задан некорректно, то работать не должно. У меня задача с тремя неизвестными. Сомнительных код, сомнительных контроллер, сомнительный датчик. Может быть посоветуете какой-то копеечный датчик, например автомобильный, который можно использовать, как тестовый. Если есть заведомо проверенный софт, под какой-то конкретный датчик, не откажите в любезности. Если у Вас есть контроллер и датчик, которые стыковались друг с другом, я у Вас их приобрёл бы.
pavel-pervomaysk
Приниматься будут все сообщения 11 и 29 бит.
Мы можем их фильтровать только. Флаг IDE проверили, далее решили как считать MID.
Для начала начинать надо передавать сообщения корректно.
Ловить вторым устройством.
Может банально неправильно Baud настроен, я с 250к не работал, такое только в BMW и газелях встречается.



Д_М
Здравствуйте!
Спасибо за ответ! Не понял на счет MID - что это за флаг, или регистр? В документации не нашёл.
Интереса ради пробовал менять Baud rate на 200. Не работает даже в Listening. Попробовал сделать на 250, с другими битовыми параметрами, согласно документации. Работает, но тоже только в Listening. Протестировал CAN драйвер, реализовав программно импульсы на выходе TxCAN. Установлен терминатор 100 Ом, другой нагрузки нет. Там, где два графика, измерения относительно Gnd, соответственно H и L. Там, где один график, между H и L. Везде 1 Вольт на клетку. Вот и получается, что амплитуда каждого канала 1 вольт. Дифференциальная амплитуда 2 вольта. Это нормально? На мой взгляд маловато. Из графика следует, что дифференциальное напряжение (между H и L) в рецессивном состоянии должно быть меньше 0,5 вольта. А на графике видно, что оно явно больше 0,5 Вольта.

Про датчик BMW даже и не спрашиваю. Наверняка он стоит баснословных денег. А датчик на Газель, определённо доступен по цене. Можете сказать, что это за датчик? Либо посоветовать какой-то другой недорогой датчик, с которым Вы имели дело. Если Вы ещё этот датчик подключали к AT90CAN128 и всё подружилось, то буду премного благодарен за код.
pavel-pervomaysk
Датчиков с CAN я не встречал.
Датчики обрабатывает зачастую МК.

Для HIGH SPEED CAN напряжение между CANH CANL 2-2.5V это нормально.
Настраиваем прием Mailbox 14 для сообщений с адресом 777H
CODE
CANGCON=2 ;
CANGSTA=0 ;
CANGIT=0 ;
CANGIE=0b00000000 ;

;-------------------------------------------------------------------------------
; Interrupt Enable & Disable for Mob 14...0
;Mob 14,13,12,11,10,9,8; - IEMOB14 IEMOB13 IEMOB12 IEMOB11 IEMOB10 IEMOB9 IEMOB8
ldi tmp,0b01000000 ; Mailbox 14 - interrupt mode!
sts CANIE1,tmp ; Can Enable Interrupt MOb Register


BAUD 250 000
; CAN 8 bit 250 Kbps 16 MHz
; Sample Point at 75%
CANBT1=0x0E
CANBT2=4
CANBT3=13H
;-------------------------


CANTCON=0
CANTIML=0
CANTIMH=0
CANTTCL=0
CANTTCH=0

CANTEC=0
CANREC=0
CANHPMOB=0
CANSTMOB=0

CANSTML=0
CANSTMH=0


Инициализируем:

CANPAGE=E0H; MailBox 14;

CANMESSAGE 0-7;
E0 - High nibble Mailbox index;
E0-CANMSG[0];
E1-CANMSG[1];
E2-CANMSG[2];
E3-CANMSG[3];
E4-CANMSG[4];
E5-CANMSG[5];
E6-CANMSG[6];
E7-CANMSG[7];

Устанавливаем MID: Message ID. Читаем даташит.
CANIDT4 CANIDT3 CANIDT2 CANIDT1 = (777H << 21);

Устанавливаем маску (фильтр диапазона принимаемых сообщений): Опять читаем даташит.
CANIDM4 CANIDM3 CANIDM2 CANIDM1 = (7FFH << 21);

Фильтр указанного ID
Full filtering: to accept only ID = 0x317 in part A.
- ID MSK = 111 1111 1111 b
- ID TAG = 011 0001 0111 b

Диапазон работы фильтра
Partiel filtering: to accept ID from 0x310 up to 0x317 in part A.
- ID MSK = 111 1111 1000 b
- ID TAG = 011 0001 0xxx b

Без фильтра
No filtering: to accept all ID’s from 0x000 up to 0x7FF in part A.
- ID MSK = 000 0000 0000 b
- ID TAG = xxx xxxx xxxx b


Затем обрабатываем прерывание
Смотрим
lds tmp,CANSIT1
проверяем бит 6, если он, достаем сообщение, обрабатываем, отвечаем.

Все.

Получаем сообщение

CANPAGE=E0H; MailBox 14;
CAN0=CANMSG[0];

CANPAGE=E1H; MailBox 14;
CAN1=CANMSG[1];

и так до 8го байта.
Д_М
Спасибо, попробовал!
Результат прежний - работает только в Listening.
Есть подозрение, что у меня какая-то аппаратная проблема. Вы использовали какое-то серийное устройство на базе AT90CAN128? Это устройство можно приобрести?

Сделал вот так:
CODE
#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;

flag = CANSIT1; // чтение регистра состояния прерываний(того где Mob0 и Mob1)
if(flag & (1<< 6)) //Если прерывание по Mob14
{
CANPAGE = 0xE0; //Выбор Mob14
for(i = 0; i < 8; i++)
*ptr++ = CANMSG; //Считать регистр данных сообщения 8 раз
// CANSTMOB &= ~(1<<RXOK); //сбросить влаг удачного завершения приема
}

ptr = &Buttons.Right.reg + 2;
tmp.lo = CANIDT1;
tmp.hi = CANIDT2;
Trg_NWA_r = tmp.si;

Joystik_X = (signed char)(~*ptr++);
Joystik_Y = (signed char)(~*ptr++);

CANPAGE = 0xE0;
CANSTMOB=0x00; // reset channel 14 status
CANEN1 = 0x40; // channel 14 enable
CANCDMOB = 0x88; // receive 8 bytes
CANGIT = CANGIT; // reset all flags
}

void CAN_Init(unsigned char set_brp, unsigned char set_prs, unsigned char set_phs1, unsigned char set_phs2)
{
CANGCON = 0x0A; // Разрешить контроллер CAN
CANGSTA = 0;
CANGIT = 0;
CANGIE = 0;
CANIE1 = 0x40;
CANEN1 = 0x40;

CANBT1 = 0x06;
CANBT2 = 0x0C;
CANBT3 = 0x37;

CANTCON = 0;
CANTIML = 0;
CANTIMH = 0;
CANTTCL = 0;
CANTTCH = 0;

CANTEC = 0;
CANREC = 0;
CANHPMOB = 0;
CANSTMOB = 0;

CANSTML = 0;
CANSTMH = 0;

CANPAGE = 0xE0; // MailBox 14

// setup bit timing at 250k with 16 MHz crystal
CANBT1 = 0x06;
CANBT2 = 0x0C;
CANBT3 = 0x37;

CANPAGE = 0xE0; // MailBox 14

CANSTMOB = 0; // reset channel status
CANCDMOB = 0; // reset control and dlc register

CANIDT4 = 0x00;
CANIDT3 = 0x00;
CANIDT2 = 0x00;
CANIDT1 = 0x00;

CANIDM4 = 0x00; // Принудительный положительный результат сравнени
CANIDM3 = 0x00; // Принудительный положительный результат сравнени
CANIDM2 = 0x00; // Принудительный положительный результат сравнени
CANIDM1 = 0x00; // Принудительный положительный результат сравнени

// Channel 14 configuration
CANCDMOB = 0x88; // Reception 8 bytes.*/
CANGIE = ((1<<ENRX)|(1<<ENIT)); // Can_Rx & IT enable
}
pavel-pervomaysk
Прочитайте даташит ВНИМАТЕЛЬНО, и желательно начиная с 19. Controller Area Network - CAN
Я дал пример инициализации для работы в нормальном режиме.
Нет же, надо принудительно включить LISTEN и все...
Д_М
Здравствуйте!
Изначально я попробовал в нормально режиме. Но не заработало. Уж потом попробовал в listenig. Есть у меня подозрение, что проблема в драйвере или, его обвязке. Устройство новой разработки, CAN ранее не тестировался. Потому я и спросил Вас с каким устройством на базе AT90CAN128 Вы работали. Хотел бы я приобрести заведомо рабочее, проверенное устройство на базе AT90CAN128.
pavel-pervomaysk
Что значит не заработало?
Если сообщение принято, контроллер отправит АСК.
Д_М
В нормальном режиме не происходит прерывание от CAN. То есть ничего не принимается. В Listening работает.
Д_М
Разобрались!
Проблема, как и думалось, была аппаратная. Софт рабочий. Проверен на отладочной плате от Olimex. С реальным датчиком работает.
Д_М
Всем большое спасибо за помощь!
Контроллер довели. CAN работает на 250 kBit/sec. Полноценная, трёхходовая гальваническая изоляция CAN и остальных интерфейсов. Если вдруг, кому-то потребуется завершённый контроллер в промышленном исполнении, на базе AVR, обращайтесь.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.