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

STM32F3xx Обмен по CAN

В продолжение темы по CAN на stm32f3xx.

Не получив успеха в запуске CAN внутри своего проекта, решил откатиться назад и создать новый проект, на котором нужно отладить код с работай CAN.

Итак. 
Имею два абсолютно одинаковых устройства.
- на плате есть трансивер, подключённый к МК.
- на выходе трансивера имеется резистор на 120.
- МК тактируется от внешнего кварца.
- цепи проверены, обрывов нет.

Решил набросать пример на HAL образу из данного видео (уверен, что видео известное): 

 и часть 2:



Первым делом, если вспомнить о режимах CAN внутри stm32, где выход можно замкнуть на вход, то можно произвести первичную отладку в рамках одного камня. 
Задача:
- настроить МК в режим где выход замкнут на вход, пусть будет CAN_MODE_LOOPBACK.
- в цикле МК пусть оправляет что-нибудь по кругу
- а в прерывании приёма пусть переключает состояние светодиода.

- кванты времени взяты с ресурса http://www.bittiming.can-wiki.info/ :
-- частота тактирования шины 32MHz
-- выбранная частота самая низкая - 10kbit-s

Вот что у меня вышло:
 

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
	CAN_FilterTypeDef  sFilterConfig;
    CAN_TxHeaderTypeDef TxHeader;
    CAN_RxHeaderTypeDef RxHeader;
    uint8_t Can_Data_Tx[8];
    uint8_t Can_Data_Rx[8];
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

// Прерывание приёма. Если будет что-то получено, то переключить состояние светодиода.
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RxHeader, Can_Data_Rx) == HAL_OK)
	{
		GPIOB -> ODR ^= GPIO_ODR_6;
	}
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */

  //светодиод "ERROR" (pcb)
  	//PA3(18)
  	RCC -> AHBENR |= RCC_AHBENR_GPIOAEN; //		тактирование порта A
  	GPIOA -> MODER |= GPIO_MODER_MODER3_0; // 	01: General purpose output mode

//светодиод "TR" (панель пульта)
	//PB6(58)
	RCC -> AHBENR |= RCC_AHBENR_GPIOBEN; 		// Тактирование порта B
	GPIOB -> MODER |= GPIO_MODER_MODER6_0; 		// 01: General purpose output mode
	GPIOB -> ODR |= GPIO_ODR_6; 				// выключение светодиода "TR"
//	Init_TIM4();

	//светодиод "EL" (панель пульта)
	//PB7(59)
	RCC -> AHBENR |= RCC_AHBENR_GPIOBEN; 		// Тактирование порта B
	GPIOB -> MODER |= GPIO_MODER_MODER7_0; 		// 01: General purpose output mode
	GPIOB -> ODR |= GPIO_ODR_7; 				// выключение светодиода "EL"
//	Init_TIM4();

	//светодиод "ERR" (панель пульта)
	//PB5(57)
	RCC -> AHBENR |= RCC_AHBENR_GPIOBEN; 		// Тактирование порта B
	GPIOB -> MODER |= GPIO_MODER_MODER5_0;		// 01: General purpose output mode
	GPIOB -> ODR |= GPIO_ODR_5; 				// выключение светодиода "ERR"
//	Init_TIM3();

  MX_GPIO_Init();
  MX_CAN_Init();
  /* USER CODE BEGIN 2 */
  Can_Data_Tx[0] = 1;

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  Can_Data_Tx[0] = 1;
	  Can_Data_Tx[1] = 0xf0;
	  HAL_CAN_AddTxMessage(&hcan, &TxHeader, Can_Data_Tx, &sFilterConfig);
	  GPIOA -> ODR ^= GPIO_ODR_3;
	  HAL_Delay(200);

	  Can_Data_Tx[0] = 2;
	  Can_Data_Tx[1] = 0xf0;
	  HAL_CAN_AddTxMessage(&hcan, &TxHeader, Can_Data_Tx, &sFilterConfig);
	  GPIOA -> ODR ^= GPIO_ODR_3;
	  HAL_Delay(200);

	  Can_Data_Tx[0] = 3;
	  Can_Data_Tx[1] = 0xf0;
	  HAL_CAN_AddTxMessage(&hcan, &TxHeader, Can_Data_Tx, &sFilterConfig);
	  GPIOA -> ODR ^= GPIO_ODR_3;
	  HAL_Delay(200);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief CAN Initialization Function
  * @param None
  * @retval None
  */
static void MX_CAN_Init(void)
{

  /* USER CODE BEGIN CAN_Init 0 */
  /* USER CODE END CAN_Init 0 */

  /* USER CODE BEGIN CAN_Init 1 */

  /* USER CODE END CAN_Init 1 */
  hcan.Instance = CAN;
  hcan.Init.Prescaler = 200;
  hcan.Init.Mode = CAN_MODE_LOOPBACK;
  hcan.Init.SyncJumpWidth = CAN_SJW_2TQ;
  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;
  if (HAL_CAN_Init(&hcan) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN_Init 2 */
  	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;
    sFilterConfig.SlaveStartFilterBank = 14;

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

    HAL_CAN_Start(&hcan);

    HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
    HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO1_MSG_PENDING);
    HAL_CAN_ActivateNotification(&hcan, CAN_IT_ERROR);

    TxHeader.StdId = 0x122;
    TxHeader.ExtId = 0xff;
    TxHeader.IDE = CAN_ID_EXT;
    TxHeader.DLC = 8;
    TxHeader.TransmitGlobalTime = DISABLE;
    TxHeader.RTR = CAN_RTR_DATA;

  /* USER CODE END CAN_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/



К сожалению, данный пример не работает.
- судя по светодиоду отправки и по осциллограмме между CAN_H и CAN_L, шина работает.
- но вот приёмник не работает. 
Прошу помощи форумчан.

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


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

Зачем создавать две темы с одинаковой сутью?

А по делу - даже видео называется "...странности HAL", так может просто написать свое по мануалу на МК?

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


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

16 минут назад, Arlleex сказал:

Зачем создавать две темы с одинаковой сутью?

А по делу - даже видео называется "...странности HAL", так может просто написать свое по мануалу на МК?

А может лучше не выпендриваться, а помочь)?

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


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

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

В рамках одного устройства данные отправляются и принимаются.

Теперь буду пробовать объединить два устройства.
- Одно устройство будет находиться в режиме CAN_MODE_LOOPBACK. Получается, что оно будет отправлять кадры на второе устрой и принимать кадры от самого себя же.
- А второе устройство будет в CAN_MODE_NORMAL. И будет закомментирован цикл отправки. Получается, что второе устройство будет постоянно находится в ожидании сообщения. И если сообщение придёт, то оно в такт с первым будет моргать светодиодом.

Ну вот прикол и случился.
- Устройство передающее отправляет сообщения на второе и слышит само себя,
- но вот второе устройство молчит.

Такая же ситуация, если оба устройства перевести в CAN_MODE_NORMAL.

Прошу помощи. Что сейчас может быть не так???

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


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

Если второе устройство только слушает, его стоило в режим Silent выставить, а не normal.

Посмотрите шину осциллографом: идут ли в ней данные. Если идут, проверьте, не перепутали ли CANL/CANH. Если не перепутали, то проверяйте, что там у вас с настройками принимающей стороны.

Лучше всего было бы, как уже неоднократно советовали, настроить по даташиту (взяв за образец сниппет), тогда хотя бы можно будет сюда выложить код настройки, чтобы люди посмотрели и посоветовали. В дебрях хала никто ковыряться не будет, потому что никто его не использует!

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


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

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

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

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

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

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

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

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

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

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