Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CAN_stm32
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Ekka
Привет всем, новичок в этом деле. Пытаюсь настроить 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
Эдди
Жутко нечитаемый код.
Andreas1
Цитата(Ekka @ Nov 7 2017, 17:22) *
Что не так???? stm32105R8Tx

похоже через хал мало кто работает с каном.
Я хз, что там скрыто в вызовах, но не вижу разрешения прерываний от кана, типа
CAN->IER = CAN_IER_ERRIE | CAN_IER_BOFIE | CAN_IER_LECIE | CAN_IER_FMPIE0 | CAN_IER_TMEIE;

Ну и имхо стоит без loopback сниффером глянуть, что происходит на шине.
Эдди
Подозреваю, что вообще никто не связывается с HAL в чем-то хоть немного сложней "помигать светодиодиком".
ТСу либо надо ковыряться в исходниках используемых библиотек, либо написать нормально — по даташиту.
Andrew_Q
Осмелюсь предположить, что нет сброса битов прерывания.
Код
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 */
}
adnega
Цитата(Andrew_Q @ Nov 8 2017, 07:57) *
Осмелюсь предположить, что нет сброса битов прерывания.
Код
    HAL_NVIC_ClearPendingIRQ(CAN1_TX_IRQn);
    HAL_NVIC_ClearPendingIRQ(CAN1_RX0_IRQn);
}

Это лишнее для Cortex, т.к. это делает ядро при входе в обработчик.
Ekka
ткните носом, пожалуйста, где в datasheet про КАН написано, какой документ?
Эдди
Это вам не в даташит, а в RM на линейку используемых МК.
Ekka
Все, вопрос снят
yes
на всякий случай:
сталкивались с глюками "HAL CAN драйвера"
то есть там есть путь, в котором его состояние не убирается в IDLE и соответственно софт подвисает
ну и при интенсивной работе на прием-передачу иногда сбрасывает биты маскирования CAN RX1|2 - может проблемы с реентерабельностью или интерференция какая-то с FreeRTOS задачами - на запись работает одна задача, на чтение другая
вобщем сделал некий внешний контроль битов по таймеру и если биты сброшены, то поднимать...

то есть - лучше разберитесь с железом, чем использовать CAN HAL
Ekka
разобрались потихоньку, не знаю, правильно ли, но теперь КАН в режиме loopback работает. Кому надо, может, говорите, кину.
Ekka
вопрос другой возник...пытаюсь связать две 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
Ekka
Ребят, неужели такой ошибки не у кого не было? Понимаю,вопросы не из умных... Но надо же с чего-то начинать? Может,кто подскажет,куда копать хоть( хелп
esaulenka
Копать:
1) в сторону рассмотрения шины осциллографом и заведомо работоспособным CAN-адаптером
2) в сторону понимания, что и как устроено в этом чудо HAL'е. К сожалению, качество его такое, что любой шаг в сторону от придуманного его авторами алгоритма - и ничего не работает.

Не уверен, что тут есть люди, которые наизусть помнят, что такое "ошибка 131". При этом многие (и я в т.ч.) имеют представление и о CAN-периферии стм-ки, и о спецификации дядьки Боша на саму шину.
Andreas1
Цитата(Ekka @ Nov 14 2017, 10:52) *
Ребят, неужели такой ошибки не у кого не было? Понимаю,вопросы не из умных... Но надо же с чего-то начинать? Может,кто подскажет,куда копать хоть( хелп

У вас странный подход к кану.
- проверять надо не другим стм, а сниффером. На али они стоят от 1000р, потерянное время намного дороже.
- большинство работают без хала и что такое ошибка 131 - хз. Можно было бы хоть описание ее дать.
- выше уже сказали простейший вариант - дать передачу и смотреть скопом или лог. анализатором с того-же али за 600р( saleae logic). Он еще и декодировать кан умеет, и крестиком вышивать, всегда пригодится.

Ну и вообще, передача по кану без хала, только работой регистрами проста и дубова. Я ее за пару часов просмотра даташита и инета написал и она сразу заработала. Но за месяц до этого заказал синффер с али.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.