Jump to content

    

CAN_stm32

Привет всем, новичок в этом деле. Пытаюсь настроить CAN в режиме "слушать себя". Использую CubeMX HAL, ну и ручками немного понацарапалось. Кто может мне, тугодуму, подсказать,

почему в прерывание по приему и передаче входит только раз? Может, я какие-то флаги не сбрасываю? или фильтр не правильно настроен.

Куда копать хоть...

 

настройка CAN

static void MX_CAN1_Init(void)
{

  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 16;
  hcan1.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
  hcan1.Init.SJW = CAN_SJW_1TQ;
  hcan1.Init.BS1 = CAN_BS1_3TQ;
  hcan1.Init.BS2 = CAN_BS2_3TQ;
  hcan1.Init.TTCM = DISABLE;
  hcan1.Init.ABOM = ENABLE;
  hcan1.Init.AWUM = DISABLE;
  hcan1.Init.NART = DISABLE;
  hcan1.Init.RFLM = ENABLE;
  hcan1.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

}

 

функция отправки

void CAN_Transmit(void)
{
    hcan1.pTxMsg->StdId = 0x002;
    hcan1.pTxMsg->DLC = 3;
    hcan1.pTxMsg->Data[0] = tx++;
    hcan1.pTxMsg->Data[1] = 2;
    hcan1.pTxMsg->Data[2] = 3;
    HAL_CAN_Transmit(&hcan1, 10);

 

прерывания

void CAN1_TX_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_TX_IRQn 0 */

  /* USER CODE END CAN1_TX_IRQn 0 */
  HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE BEGIN CAN1_TX_IRQn 1 */
    //HAL_CAN_Transmit_IT(&hcan1);
  /* USER CODE END CAN1_TX_IRQn 1 */
}

/**
* @brief This function handles CAN1 RX0 interrupt.
*/
void CAN1_RX0_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
    HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE END CAN1_RX0_IRQn 0 */
  HAL_CAN_Receive(&hcan1,CAN_FIFO0,10);
    hcan1.pRxMsg->DLC = 0x00;
  hcan1.pRxMsg->StdId =0x00;
  hcan1.pRxMsg->Data [0] = 0x00;
  hcan1.pRxMsg->Data [1] = 0x00;
  hcan1.pRxMsg->Data [2] = 0x00;
  hcan1.pRxMsg->Data [3] = 0x00;
  hcan1.pRxMsg->Data [4] = 0x00;
  hcan1.pRxMsg->Data [5] = 0x00;
  hcan1.pRxMsg->Data [6] = 0x00;
  hcan1.pRxMsg->Data [7] = 0x00;
  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
  /* USER CODE END CAN1_RX0_IRQn 1 */
}

 

МЭЙН

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN1_Init();

  /* USER CODE BEGIN 2 */
    hcan1.pTxMsg = &canTxMessage;
    hcan1.pRxMsg = &canRxMessage;
    
    //фильтры CAN
    // настраиваем фильтр — приём всех посылок
    CAN_FilterConfTypeDef canFilterConfig;
    canFilterConfig.FilterNumber = 0;
    canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    canFilterConfig.FilterIdHigh = 0x0000;
    canFilterConfig.FilterIdLow = 0x0000;
    canFilterConfig.FilterMaskIdHigh = 0x0000 << 5;
    canFilterConfig.FilterMaskIdLow = 0x0000;
    canFilterConfig.FilterFIFOAssignment = 0;
    canFilterConfig.FilterActivation = ENABLE;
    canFilterConfig.BankNumber = 1;
    
    HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig);
    HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0); //разрешаем приём посылок
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        CAN_Transmit();
        HAL_Delay(10);
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

 

 

Что не так???? stm32105R8Tx

Edited by Ekka

Share this post


Link to post
Share on other sites
Что не так???? stm32105R8Tx

похоже через хал мало кто работает с каном.

Я хз, что там скрыто в вызовах, но не вижу разрешения прерываний от кана, типа

CAN->IER = CAN_IER_ERRIE | CAN_IER_BOFIE | CAN_IER_LECIE | CAN_IER_FMPIE0 | CAN_IER_TMEIE;

 

Ну и имхо стоит без loopback сниффером глянуть, что происходит на шине.

Share this post


Link to post
Share on other sites

Подозреваю, что вообще никто не связывается с HAL в чем-то хоть немного сложней "помигать светодиодиком".

ТСу либо надо ковыряться в исходниках используемых библиотек, либо написать нормально — по даташиту.

Share this post


Link to post
Share on other sites

Осмелюсь предположить, что нет сброса битов прерывания.

void CAN1_TX_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_TX_IRQn 0 */
    HAL_NVIC_ClearPendingIRQ(CAN1_TX_IRQn);
  /* USER CODE END CAN1_TX_IRQn 0 */
  HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE BEGIN CAN1_TX_IRQn 1 */

  /* USER CODE END CAN1_TX_IRQn 1 */
}

/**
* @brief This function handles CAN1 RX0 interrupts.
*/
void CAN1_RX0_IRQHandler(void)
{
  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */
    HAL_NVIC_ClearPendingIRQ(CAN1_RX0_IRQn);
  /* USER CODE END CAN1_RX0_IRQn 0 */
  HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */

  /* USER CODE END CAN1_RX0_IRQn 1 */
}

Share this post


Link to post
Share on other sites
Осмелюсь предположить, что нет сброса битов прерывания.

    HAL_NVIC_ClearPendingIRQ(CAN1_TX_IRQn);
    HAL_NVIC_ClearPendingIRQ(CAN1_RX0_IRQn);
}

Это лишнее для Cortex, т.к. это делает ядро при входе в обработчик.

Share this post


Link to post
Share on other sites

ткните носом, пожалуйста, где в datasheet про КАН написано, какой документ?

Share this post


Link to post
Share on other sites

Это вам не в даташит, а в RM на линейку используемых МК.

Edited by Эдди

Share this post


Link to post
Share on other sites

на всякий случай:

сталкивались с глюками "HAL CAN драйвера"

то есть там есть путь, в котором его состояние не убирается в IDLE и соответственно софт подвисает

ну и при интенсивной работе на прием-передачу иногда сбрасывает биты маскирования CAN RX1|2 - может проблемы с реентерабельностью или интерференция какая-то с FreeRTOS задачами - на запись работает одна задача, на чтение другая

вобщем сделал некий внешний контроль битов по таймеру и если биты сброшены, то поднимать...

 

то есть - лучше разберитесь с железом, чем использовать CAN HAL

 

Share this post


Link to post
Share on other sites

разобрались потихоньку, не знаю, правильно ли, но теперь КАН в режиме loopback работает. Кому надо, может, говорите, кину.

 

Share this post


Link to post
Share on other sites

вопрос другой возник...пытаюсь связать две stm32f105r8t6 через CAN, но после отправки всегда появляется 131 ошибка (ErrorCode=131)...потом все виснет, отчего так может быть?

 

настройка первой stm

static void MX_CAN1_Init(void)
{

  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 4;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SJW = CAN_SJW_1TQ;
  hcan1.Init.BS1 = CAN_BS1_4TQ;
  hcan1.Init.BS2 = CAN_BS2_4TQ;
  hcan1.Init.TTCM = DISABLE;
  hcan1.Init.ABOM = DISABLE;
  hcan1.Init.AWUM = DISABLE;
  hcan1.Init.NART = ENABLE;
  hcan1.Init.RFLM = DISABLE;
  hcan1.Init.TXFP = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }

}

 

ее фильтры

hcan1.pTxMsg = &canTxMessage;
    hcan1.pRxMsg = &canRxMessage;
    CAN_FilterConfTypeDef canFilterConfig;
    canFilterConfig.FilterNumber = 0;
    canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    canFilterConfig.FilterIdHigh = 0;
    canFilterConfig.FilterIdLow = 0;
    canFilterConfig.FilterMaskIdHigh = 0;
    canFilterConfig.FilterMaskIdLow = 0;
    canFilterConfig.FilterFIFOAssignment = 0;
    canFilterConfig.FilterActivation = ENABLE;
    canFilterConfig.BankNumber = 1;
    HAL_CAN_ConfigFilter(&hcan1, &canFilterConfig);

    canRxMessage.StdId = 0x801;
    canRxMessage.RTR = CAN_RTR_DATA;
    canRxMessage.IDE = CAN_ID_STD;
    canRxMessage.DLC = 2;
    HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0);
    HAL_NVIC_SetPriority(CAN1_RX0_IRQn,2,0);
    HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);

 

настройки одинаковые у обоих плат.

 

разница только в том, что первая плата отправляется команду, а вторая принимает.

 

у первой платы:

 

void CAN_Transmit()
{
    canTxMessage.StdId=0x802;
    canTxMessage.DLC=2;  
    canTxMessage.Data[0] = 0x00;
    canTxMessage.Data[1] = 0x01;
    HAL_CAN_Transmit(&hcan1,10);
}

 

в цикле ее же:

while (1)
  {
  /* USER CODE END WHILE */
        CAN_Transmit();
        HAL_Delay(2000);
  /* USER CODE BEGIN 3 */

  }

 

вторая должна принимать

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
    CAN_ID = CanHandle->pRxMsg->StdId;
    CAN_DLC = CanHandle->pRxMsg->DLC;
    __HAL_UNLOCK (CanHandle);
    r=HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0);
    DATA[0]=CanHandle->pRxMsg->Data[0];
    DATA[1]=CanHandle->pRxMsg->Data[1];
}

 

но первая плата после отправки уходит в ошибку 131, потом через некоторое время виснет (число ошибок зашкаливает,наверное)... что может быть не так???

 

если быть точнее, но в функции отправки уходит в таймаут и сидит там, пока статус кана не перейдет в HAL_STATE_ERROR

 

Edited by Ekka

Share this post


Link to post
Share on other sites

Ребят, неужели такой ошибки не у кого не было? Понимаю,вопросы не из умных... Но надо же с чего-то начинать? Может,кто подскажет,куда копать хоть( хелп

Share this post


Link to post
Share on other sites

Копать:

1) в сторону рассмотрения шины осциллографом и заведомо работоспособным CAN-адаптером

2) в сторону понимания, что и как устроено в этом чудо HAL'е. К сожалению, качество его такое, что любой шаг в сторону от придуманного его авторами алгоритма - и ничего не работает.

 

Не уверен, что тут есть люди, которые наизусть помнят, что такое "ошибка 131". При этом многие (и я в т.ч.) имеют представление и о CAN-периферии стм-ки, и о спецификации дядьки Боша на саму шину.

Share this post


Link to post
Share on other sites
Ребят, неужели такой ошибки не у кого не было? Понимаю,вопросы не из умных... Но надо же с чего-то начинать? Может,кто подскажет,куда копать хоть( хелп

У вас странный подход к кану.

- проверять надо не другим стм, а сниффером. На али они стоят от 1000р, потерянное время намного дороже.

- большинство работают без хала и что такое ошибка 131 - хз. Можно было бы хоть описание ее дать.

- выше уже сказали простейший вариант - дать передачу и смотреть скопом или лог. анализатором с того-же али за 600р( saleae logic). Он еще и декодировать кан умеет, и крестиком вышивать, всегда пригодится.

 

Ну и вообще, передача по кану без хала, только работой регистрами проста и дубова. Я ее за пару часов просмотра даташита и инета написал и она сразу заработала. Но за месяц до этого заказал синффер с али.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this