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

STM32F3xx Обмен по CAN

Доброго времени!
Появилась необходимость в умении работать с CAN шиной.

Собрал проект на по примеру, https://istarik.ru/blog/stm32/159.html , вдруг кто-то знаком с данной статьёй.
В примере автор запускает CAN сначала внутри самой себя используя режим Loopback.
А после берёт вторую плату Bluepill и переведя проект в Normal перекидывается сообщениями между платами.

А что у меня.
Я взял две платы с CAN-трансиверами.
Сначала одну плату настроил на Loopback…
в результате чего, при помощи осциллографа я убедился, что сигнал выходит из первой платы.

Начал работу со второй.
Настроил ее на такой же проект, но оказалось, что в Normal режиме, вторая плата не принимает сообщения от первой.
А принимает только в Silent режиме.

Соответственно, если вернуться к первой плате и перевести ее в режим NORMAL, то она начинает зависать, так как ждёт когда придёт подтверждение от второй платы о принятии кадра. (ждёт выставления ACK)



Получается, что на данный момент я могу передавать сообщения только в одну сторону, от устройства 1 к устройству 2. А хотелось бы освоить и общение в обе стороны.

Вот что я сейчас имею.
Вот это первое устройство (на данный момент передатчик). Суть: фифо настроен на приём всего подряд. А в цикле просто шлёт сообщение "HI!\r\n"
 

int main(void) {
        Init_CAN();
        while (1) {
           sprintf(buff, "HI!\r\n");
           CAN_Transmit_data(0x01, buff);
                HAL_Delay(500);
        }
}

void Init_CAN (void){

   /*
    * Шина настроена на 500kbit/s
    * Semple point = 87.5%
    */

   HAL_Init();
    MX_GPIO_Init();
    MX_CAN_Init();

    HAL_CAN_Start(&hcan);
    HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE);
}

void CAN_Transmit_data (uint32_t id_message, uint8_t Data[]){

    TxHeader.StdId = 0x0;             // ID_EXT
    TxHeader.ExtId = id_message;       // от 0х00 до 1FFFFFFF (0 — 536870911) сам идентификатор
    TxHeader.RTR = CAN_RTR_DATA;       // Указывает что будет оправляться данные или команда
    TxHeader.IDE = CAN_ID_EXT;          // расширенный идентификатор
    TxHeader.DLC = 8;                // количество полезных байт данных в одном сообщении
    TxHeader.TransmitGlobalTime = 0;    // отправка счётчика времени

   while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0);
   HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data, &TxMailbox);
}

static void MX_CAN_Init(void)
{

   CAN_FilterTypeDef  sFilterConfig;

// Работает, но только в loopback режиме
//  hcan.Instance = CAN;
//  hcan.Init.Prescaler = 4;
//  hcan.Init.Mode = CAN_MODE_LOOPBACK;
//  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
//  hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
//  hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
//  hcan.Init.TimeTriggeredMode = DISABLE;
//  hcan.Init.AutoBusOff = ENABLE;
//  hcan.Init.AutoWakeUp = DISABLE;
//  hcan.Init.AutoRetransmission = ENABLE;
//  hcan.Init.ReceiveFifoLocked = DISABLE;
//  hcan.Init.TransmitFifoPriority = ENABLE;


// копия для ээээкперимета
  hcan.Instance = CAN;
  hcan.Init.Prescaler = 4;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE; // работает при DISABLE и ENABLE
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = DISABLE; // повторное отправление, если не выставился ACK-бит.  работает при DISABLE и ENABLE   !!!Если включить режим CAN_MODE_NORMAL и ОТКЛЮЧИТЬ AutoRetransmission, то шина работает. Если включить AutoRetransmission, то шина зависает. Получается, что подтверждения от получателя!
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = ENABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    //Error_Handler();
  }

  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;


  if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  {
     //Error_Handler();
  }


}

А вот второе устройство (приёмник). Суть: настроен так же как и передатчик но в цикл пуст, а имеет настроенное прерывание HAL_CAN_RxFifo0MsgPendingCallback, в котором при получении кадра переключает светодиод. Работает, но только в режиме CAN_MODE_SILENT.
 



void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK)
    {
       Led_Green(2);

        sprintf(buff,"%c%c%c%c%c%c%c%c", RxData[0],RxData[1],RxData[2],RxData[3],RxData[4],RxData[5],RxData[6],RxData[7]);

        for(int counter=0; counter < sizeof(buff); counter++){
           USART1->DR = buff[counter];
           while (!(USART1->SR & USART_SR_TC)); // ожидание завершения передачи
        }

    }
}

void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
}


void CAN_Transmit_data (uint32_t id_message, uint8_t Data[]){

   TxHeader.StdId = 0x1; // ID_EXT
    TxHeader.ExtId = id_message; // от 0х00 до 1FFFFFFF (0 — 536870911)
    TxHeader.RTR = CAN_RTR_DATA;
    TxHeader.IDE = CAN_ID_EXT;
    TxHeader.DLC = 8;
     TxHeader.TransmitGlobalTime = 0;

   while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0);
   HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data, &TxMailbox);
}



int main(void)
{
         MX_CAN_Init();
         TxHeader.StdId = 1;

         TxHeader.RTR = CAN_RTR_DATA; //CAN_RTR_REMOTE
         TxHeader.IDE = CAN_ID_EXT;   // CAN_ID_EXT CAN_ID_STD
         TxHeader.DLC = 8;
         TxHeader.TransmitGlobalTime = 0;

         HAL_CAN_Start(&hcan);
         HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE);


         while (1)
         {
                 
         }

Прошу помощи в настройке CAN на работу в NORMAL mode и отправкой сообщений в обе стороны.

 

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


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

10 часов назад, rkit сказал:

В проводке всё в порядке? Особенно tx-пин на второй плате?

да, всё в порядке, так как можно первое устройство настроить как второе, а второе как первое и всё работает по той же схеме

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


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

1.Тактирование МК должно быть от внешних стабильных источников (кварцевых резонаторов). У внутренних генераторов может быть раброс, из-за чего не совпадают скорости.

2. Обязательные резисторы 120 Ом (хотя бы 1 на короткой линии до 1 метра).

3.На передающем МК посмотреть, какая ошибка возникает в контроллере CAN.

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


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

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

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

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

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

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

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

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

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

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