[an error occurred while processing this directive]
T89C51CC01: "медленный" CAN?
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено asd 22 сентября 2005 г. 11:56

Я начал программировать CAN на T89C51CC01 недавно, может быть я чего-то не так делаю, но почему-то CAN у меня медленно отправляет сообщения. То есть, приходится ждать чуть ли не полсекунды пока выставится бит TXOK в регистре CANCONCH после отправки очередного сообщения. Ниже привожу функции инициализации CAN и отправки сообщения. Не могли бы уважаемые гуру сказать мне чего-нибудь по этому поводу?

//...
CKCON = 0x01;
//...
// ===== CAN Baudrate Calculation ======================
// Tscl = (1+BRP)/(XTAL) // for X2 Mode = ON
// Tscl = 2*(1+BRP)/(XTAL) // for X2 Mode = OFF
// Tbit = (1 + (PRS+1) + (PHS1+1) + (PHS2+1)) * Tscl

// Examples:
// 500KHz CAN Baudrate, X2 Mode = OFF, XTAL=12MHz
// BRP = 0, PRS = 2, PHS1 = 3, PHS2 = 3
// Tscl = 2/12.0MHz = 0.167 чSec
// Tbit = (1 + (2+1)+(3+1)+(3+1)) * Tscl = 12 * 0.167uSec = 2 чSec -> 500KHz Baudrate

// Examples:
// 1MHz CAN Baudrate, X2 Mode = ON, XTAL=20MHz
// BRP = 1, PRS = 1, PHS1 = 3, PHS2 = 2
// Tscl = 2/20.0MHz = 0.100 чSec
// Tbit = (1 + (1+1)+(3+1)+(2+1)) * Tscl = 10 * 0.100uSec = 1 чSec -> 1MHz Baudrate

#define BRP 25
#define SJW 2
#define PRS 1
#define PHS1 6
#define PHS2 6

#define SMP 1

BYTE CAN_init(void *init_params){
//Инициализация CAN
BYTE XDATA i;

//dummy assignment to avoid warning
//'unreferenced local variable'
init_params = init_params;

EA = 0;
CANGCON |= CanGRES; // Reset CAN controller
ECAN = 0; // disable CAN interupt
ETIM = 0; // disable CAN timer overrun interrupt

//сбрасываем входную очередь
rx_head = rx_count = 0;
queue_overflow = 0;

//message object 0 is used for transmission
CANPAGE = CanChannel(0);
CANCONCH = 0;

for (i = 1; i < MAX_CANOBJ; i++){
CANPAGE = CanChannel (i);
CANCONCH = 0;
//11-bit identifiers
CANSTCH = 0;
CANIDM1 = CANIDM2 = CANIDM3 = CANIDM4 = 0;
CANCONCH = CanRX;
}

// Set CAN Baudrate
CANBT1 = ((BRP)<<1); // set CANBT1 register (BRP timing)
CANBT2 = ((PRS)<<1) | ((SJW)<<5); // set CANBT2 register (PRS & SJW timing)
CANBT3 = ((PHS1)<<1)| ((PHS2)<<4) | SMP; // set CANBT3 register (PHS1 & PHS1 timing)

CANGCON |= CanENA; // enable CAN controller

ECAN = 1; // enable general CAN interupt
CANGIE |= CanENRX /* | CanENERCH | CanENBUF | CanENERG*/;
CANIE2 |= 0xFE;
CANIE1 |= 0x7F;
EA = 1; // enable All interrupts
return 1;
}

//-------------------------------------------------------------------------

//!!!!!!!!!! эта функция очень часто возвращает 0 !!!!!!!!!!!!!!

BYTE CAN_transmit(CAN_msg_t *msg){
//Передача сообщения из буфера CAN_msg
BYTE i, save_canpage = CANPAGE;

// select CAN message object
CANPAGE = CanChannel(0);

// CAN channel used before?
if ((CANCONCH & CanCONCH)){
int n = 0x7FFF;
while (!(CANSTCH & CanTXOK))
if (!--n){
CANPAGE = save_canpage;
// previous message not yet send!
return 0;
}
}
// reset previous status
CANCONCH &= ~CanCONCH;
CANSTCH &= ~CanTXOK;

CANIDT1 = msg->id >> 3;
CANIDT2 = msg->id << 5;
CANIDT3 = 0;
if (msg->rtr)
CANIDT4 = CanRTRMSK;
else
CANIDT4 = 0;

// copy information to message buffer
for (i = 0; i < msg->len; i++)
CANMSG = msg->dat[i];

// send information
CANCONCH = CanTX | (msg->len & 0xF);
CANPAGE = save_canpage;
return 1;
}

Составить ответ  |||  Конференция  |||  Архив

Ответы


Отправка ответа

Имя (обязательно): 
Пароль: 
E-mail: 
NoIX ключ Запомнить

Тема (обязательно):
Сообщение:

Ссылка на URL: 
Название ссылки: 

URL изображения: 


Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru