Jump to content

    
Sign in to follow this  
LEXIS

Правильная инициализация CAN в STM32F103

Recommended Posts

Есть контроллер STM32F103C6, инициализирую CAN модуль на скорость 500 кб/с. На этой скорости работает. Потом по CAN шине приходит команда на смену скорости - меняю, например, на 600 кб/с. - не работает, хотя если принудительно задать эту скорость изначально - то работает. Как правильно надо менять скорость во время работы.

Функция настройки скорости ниже (опущена инициализация портов, фильтров и прерываний):

void CAN_Config(unsigned int bitrate)//Kbit/sec
{
 char BitTimeCAN=0;

 CAN_DeInit(CANx);
 CAN_StructInit(&CAN_InitStructure);

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

 /* CAN cell init */
 CAN_InitStructure.CAN_TTCM = DISABLE;
 CAN_InitStructure.CAN_ABOM = DISABLE;
 CAN_InitStructure.CAN_AWUM = DISABLE;
 CAN_InitStructure.CAN_NART = DISABLE;
 CAN_InitStructure.CAN_RFLM = DISABLE;
 CAN_InitStructure.CAN_TXFP = DISABLE;
 CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

 /* CAN Baudrate */
// SetSpeed (bitrate/1000);
switch (bitrate)
{
 case 1000: BitTimeCAN = 0;break;
 case 950: BitTimeCAN = 1;break;
 case 900: BitTimeCAN = 2;break;
 case 850: BitTimeCAN = 3;break;
 case 800: BitTimeCAN = 4;break;
 case 750: BitTimeCAN = 5;break;
 case 700: BitTimeCAN = 6;break;
 case 650: BitTimeCAN = 7;break;
 case 600: BitTimeCAN = 8;break;
 case 550: BitTimeCAN = 9;break;
 case 500: BitTimeCAN = 10;break;
 case 450: BitTimeCAN = 11;break;
 case 400: BitTimeCAN = 12;break;
 case 350: BitTimeCAN = 13;break;
 case 300: BitTimeCAN = 14;break;
 case 250: BitTimeCAN = 15;break;
 case 200: BitTimeCAN = 16;break;
 case 150: BitTimeCAN = 17;break;
 case 125: BitTimeCAN = 18;break;
 case 100: BitTimeCAN = 19;break;
 case 50: BitTimeCAN = 20;break;
 case 10: BitTimeCAN = 21;break;
}

 CAN_InitStructure.CAN_SJW = CAN_BTR[bitTimeCAN][0];
 CAN_InitStructure.CAN_BS1 = CAN_BTR[bitTimeCAN][1];
 CAN_InitStructure.CAN_BS2 = CAN_BTR[bitTimeCAN][2];
 CAN_InitStructure.CAN_Prescaler = CAN_BTR[bitTimeCAN][3];
 CAN_Init(CANx, &CAN_InitStructure);

}

Именно эта функция вызывает смену скорости.

Share this post


Link to post
Share on other sites

Изначально шина задумана так, что скорость в ней одинакова для всех устройств.

Когда ID-шников не хватает, используют 29 bit.

 

Если есть устройста, работающие на другой скорости, ставится шлюз gateway.

 

Так для примера: есть N устройств, работающих по UART, там кто меняет скорость во время обмена?

Share this post


Link to post
Share on other sites

Работающий CAN нужно перевести в режим инициализации, поменять настройки и снова включить в Normal mode.

пункт "24.4.1 Initialization mode" в реф. мануале.

Share this post


Link to post
Share on other sites
Если есть устройста, работающие на другой скорости, ставится шлюз gateway.

Смысл изменения скорости не в том, чтобы соединить разноскоростные устройства, а для тонкой настройки по месту, например, при шумном канале уменьшать скорость. При этом изменение скорости будет происходить для всех устройств одновременно. Либо настраивать запрограммированное устройство на другую скорость.

 

"24.4.1 Initialization mode"

В моем мануале это 23.4.1. или у Вас какой-то другой?

 

Добавил как написано в мануале

  CAN_DeInit(CANx);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
  CAN1->MCR |= CAN_MCR_INRQ;    // wait while CAN entered to initialization mode    
  while (!(CAN1->MSR & CAN_MSR_INAK));    // CAN to initialization mode
  CAN_StructInit(&CAN_InitStructure);

 

Как обычно инициализируется, но скорость не переключает.

 

Share this post


Link to post
Share on other sites

а если сохранить желаемую скорость во флешке и перегрузиться?

я так понимаю смена скорости процесс не постоянный, случаи с настройкой прибора метод с перезагрузкой устраивает полностью. А в боевом режиме, скорее тоже подойдет...

 

зато безопасно и работоспособно 100%

Share this post


Link to post
Share on other sites
CAN->MCR &= ~CAN_MCR_INRQ; // в нормальный модус

Это делается в CAN_Init(CANx, &CAN_InitStructure);

 

а если сохранить желаемую скорость во флешке и перегрузиться?

вапиант хороший, а как програмно сделать рестарт?

Share this post


Link to post
Share on other sites

Устроить ресет процессору можно функцией NVIC_SystemReset() из core_cm3.h

или напрямую записью в регистр SCB->AIRCR.

 

Но можно сделать ресет и персонально для CAN через регистр RCC->_APB1RSTR.

Share this post


Link to post
Share on other sites
а если сохранить желаемую скорость во флешке и перегрузиться?

С ума посходили.

Оно и так нормально работает: initialization mode, настройка регистров, normal mode.

 

У нас STM32F4xx, но не думаю, что там какие-то отличия...

Share this post


Link to post
Share on other sites

Спасибо запомощь, проблему решил следующим образом: Остановил прерывания, изменил скорость, разрешил заново прерывания. Может из-за этого не работало, но теперь скорость можно менять налету.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this