Перейти к содержанию
    

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

Есть контроллер 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);

}

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если есть устройста, работающие на другой скорости, ставится шлюз 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);

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

CAN->MCR &= ~CAN_MCR_INRQ; // в нормальный модус

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

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

книжку надо читать как в стм это делается.

 

но в любом случае можно и вочь дог дернуть)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...