Jump to content
    

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 и отправкой сообщений в обе стороны.

 

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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.

×
×
  • Create New...