Jump to content

    

stm32f103c8t6 + CAN + Hard Fault

Всем привет

Использую stm32f103c8t6 в связке с MCP2551, с другой стороны к нему подключен CAN Shield для Arduino, чтобы ловить пакеты.

При включении со стороны STM32 приходят 2 пустых пакета с заголовком (насколько я понимаю)

После этого STM32 уходит в Hard Fault, тактирование я вроде бы настроил правильно, кванты времени выставил для скорости 500 кбит

Код генерировал в STM32CubeMX, а отладку провожу в Keil uVision5

 

Честно говоря это мои первые попытки работы с CAN протоколом, да и до этого я с STM32 не работал, но похоже я что-то делаю не так

#include "main.h"

CAN_HandleTypeDef hcan;

void SystemClock_Config(void);
static void CAN_Data_Send(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);

void CAN_Data_Send(void){
	
	CAN_TxHeaderTypeDef Tx_Header;
	
	Tx_Header.StdId = 0x201;
	Tx_Header.IDE = CAN_ID_STD;
	Tx_Header.RTR = CAN_RTR_DATA;
	Tx_Header.DLC = 0x08;

	uint8_t Tx_Data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
	
	HAL_CAN_AddTxMessage(&hcan, &Tx_Header, Tx_Data, (uint32_t *)CAN_TX_MAILBOX0);
}	

int main(void){
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_CAN_Init();

  while (1){
		HAL_Delay(500);
		CAN_Data_Send();
		HAL_GPIO_TogglePin(GPIOC, CAN_Error_LED_Pin);
	}
}

void SystemClock_Config(void){
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
	
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){
    Error_Handler();
  }

  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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

static void MX_CAN_Init(void){
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 9;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_4TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_3TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = ENABLE;
  hcan.Init.AutoRetransmission = ENABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan) != HAL_OK){
    Error_Handler();
  }
}

static void MX_GPIO_Init(void){
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  HAL_GPIO_WritePin(CAN_Error_LED_GPIO_Port, CAN_Error_LED_Pin, GPIO_PIN_RESET);

  HAL_GPIO_WritePin(LED_Output_GPIO_Port, LED_Output_Pin, GPIO_PIN_RESET);

  GPIO_InitStruct.Pin = CAN_Error_LED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(CAN_Error_LED_GPIO_Port, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = Button_1_Pin|Button_2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LED_Output_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LED_Output_GPIO_Port, &GPIO_InitStruct);

}

void Error_Handler(void){
}

{2E0E8566-15F8-4E7A-92C9-FA01EC04A7DB}.png.jpg

{4FFD33FB-9ED1-4218-A241-1E70AEDD28A7}.png.jpg

{F453FD4A-166D-4EA9-BC06-B5C993958982}.png.jpg

Edited by Koteyk0o

Share this post


Link to post
Share on other sites
29 minutes ago, Koteyk0o said:

После этого STM32 уходит в Hard Fault

Расшифруйте причину hardfault. В книге Дж. Ю прекрасно написано как это сделать для cortex-m0/m3/m4(f). Ибо причины могут быть совершенно разные. А некоторые даже вполне "безобидные" (например, невыровненный доступ, включается принудительно).

Хотя, скорее всего, какая-нибудь ошибка доступа к памяти (выход за границы массива, неаккуратная работа с указателями).

Share this post


Link to post
Share on other sites

Верно-верно. Что-то не вижу буфер для CanTxMsgTypeDef *pTxMsg в CAN_HandleTypeDef hcan.

Share this post


Link to post
Share on other sites

Да, похоже была ошибка с почтовым ящиком в функции HAL_CAN_AddTxMessage

void CAN_Data_Send(void){
	
	CAN_TxHeaderTypeDef Tx_Header;
	
	Tx_Header.StdId = 0x321;
	Tx_Header.ExtId = 0x01;
	Tx_Header.RTR = CAN_RTR_DATA;
	Tx_Header.IDE = CAN_ID_STD;
	Tx_Header.DLC = 2;
	
	uint32_t mail_Box;

	uint8_t Tx_Data[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
	
	HAL_CAN_AddTxMessage(&hcan, &Tx_Header, Tx_Data, &mail_Box);
}

 

С таким кодом контроллер работает, мигает встроенным светодиодом, функция отправки работает, отправка возвращает HAL_OK. Но.

После отправки ОДНОГО сообщения шина сходит с ума, и ардуина с CAN Shield принимает кучу одинаковых пустых сообщений в огромнейшем колличестве до перезагрузки stm32

Я так понимаю это уже какая-то аппаратная проблема? Потому что по дебагу вроде бы все отлично, отправляется сообщение, дальше дергается нога GPIO, задержка, и так по кругу, все как и должно быть.

{E42A5F4E-CCB6-4575-B6AD-36F59C97899F}.png.jpg

Edited by Koteyk0o

Share this post


Link to post
Share on other sites

CAN контроллер на STM не видит доставки сообщения.

1. Ошибка в физике CAN.

2. Никто не отвечает Acknowledgement.

И еще, почему в программе ID = 0x321, а на приеме 0x448? Передается не то или не оттуда?

А после 

HAL_CAN_AddTxMessage(&hcan, &Tx_Header, Tx_Data, &mail_Box);

не нужно дождаться окончания передачи сбросить мэйлбокс? ( В версии HAL, что я использую, такой функции нет, поэтом не знаю чем она завершается)

Edited by Andrew_Q

Share this post


Link to post
Share on other sites
12 минут назад, Andrew_Q сказал:

CAN контроллер на STM не видит доставки сообщения.

1. Ошибка в физике CAN.

2. Никто не отвечает Acknowledgement.

И еще, почему в программе ID = 0x321, а на приеме 0x448? Передается не то или не оттуда?

А после 


HAL_CAN_AddTxMessage(&hcan, &Tx_Header, Tx_Data, &mail_Box);

не нужно дождаться окончания передачи сбросить мэйлбокс? ( В версии HAL, что я использую, такой функции нет, поэтом не знаю чем она завершается)

 

Спасибо большое, отключил AutoRetransmission и все ок, данные передаются в нужном промежутке времени

Цитата

И еще, почему в программе ID = 0x321, а на приеме 0x448? Передается не то или не оттуда?

Передается не то, ID указан один, приходит вообще другое

 

{7780D1A6-DA45-4186-9640-0795F14BCBE5}.png.jpg

Share this post


Link to post
Share on other sites

Смотрите что конкретно делает HAL_CAN_AddTxMessage(). Что берет? Куда кладет? Как выбирает мэйлбокс? Как его освобождает?

Share this post


Link to post
Share on other sites

У меня подозрение, что мы наблюдаем проблемы а) с битовой скоростью и б) с тем, что ардуина принимает всё подряд и не говорит, что принято с ошибкой.

Осцилл у Вас есть? А ещё лучше - логический анализатор (подключать между контроллером и PHY'ем CAN'а).

 

Советики:

- объявите в настройках проекта дефайн USE_FULL_ASSERT. Очень помогает в отладке этого чёртова хала - иначе при ошибках вызова он "ест" любые комбинации параметров и падает в совершенно неожиданных местах.

- как что-то заработает, верните назад авторетрансмит. Это полезная фича CAN'а. Иначе на более-менее загруженных шинах сообщения будут теряться (ну или придётся руками этот ретрансмит делать).

Share this post


Link to post
Share on other sites

Все заработало, извиняюсь, мой косяк

Если у кого-то принимаются неверные данные с помощью MCP2515 CAN модуля для ардуино, то проверьте какой у вас там установлен кварц. Обычно там стоит кварц на 16 МГц, но у меня почему-то стоял кварц на 8 МГц, из-за этого модуль работал неправильно. Его можно или перепаять, или поменять значения квантов времени в библиотеке

1 час назад, esaulenka сказал:

У меня подозрение, что мы наблюдаем проблемы а) с битовой скоростью и б) с тем, что ардуина принимает всё подряд и не говорит, что принято с ошибкой.

Осцилл у Вас есть? А ещё лучше - логический анализатор (подключать между контроллером и PHY'ем CAN'а).

 

Советики:

- объявите в настройках проекта дефайн USE_FULL_ASSERT. Очень помогает в отладке этого чёртова хала - иначе при ошибках вызова он "ест" любые комбинации параметров и падает в совершенно неожиданных местах.

- как что-то заработает, верните назад авторетрансмит. Это полезная фича CAN'а. Иначе на более-менее загруженных шинах сообщения будут теряться (ну или придётся руками этот ретрансмит делать).

Спасибо за советы, ретрансмит включу обратно

{E8AEF4E6-FDC2-412A-BAB4-6D6DA4CE9869}.png.jpg

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