Skocz do zawartości

[STM32] STM32 - NUCLEO F103RB, CubeMX - problem z uruchomieniem CAN


juras

Pomocna odpowiedź

Witam.

Próbowałem uruchomić interfejs CAN, ale jednego problemu nie mogę obejść. Na początku chciałem tylko aby pomiędzy dwoma jednakowymi płytkami Nucleo przesyłać dane. Kod konfiguracyjny wygenerowałem w środowisku Cube. Kod z pliku main.c:

#include "main.h"
#include "stm32f1xx_hal.h"

/* USER CODE BEGIN Includes */
#include "stm32f1xx_it.h"
/* USER CODE END Includes */

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

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
uint8_t x=0;
CAN_FilterConfTypeDef sFilterConfig;
CanTxMsgTypeDef TxMsg;
CanRxMsgTypeDef RxMsg;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

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_CAN_Init();

 /* USER CODE BEGIN 2 */
 hcan.pTxMsg = &TxMsg;
 hcan.pRxMsg = &RxMsg;
 //Tx config
 hcan.pTxMsg->StdId = 0x244;
 hcan.pTxMsg->IDE = CAN_ID_STD;
 hcan.pTxMsg->RTR = CAN_RTR_DATA;
 hcan.pTxMsg->DLC = 1;

 //filter configs
 sFilterConfig.FilterNumber = 0;
 sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
 sFilterConfig.FilterIdHigh =0;
 sFilterConfig.FilterIdLow = 0;
 sFilterConfig.FilterMaskIdHigh = 0;
 sFilterConfig.FilterMaskIdLow = 0;
 sFilterConfig.FilterFIFOAssignment = 0;
 sFilterConfig.FilterActivation = ENABLE;
 HAL_CAN_ConfigFilter(&hcan,&sFilterConfig);
 HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);

 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */

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

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

 RCC_OscInitTypeDef RCC_OscInitStruct;
 RCC_ClkInitTypeDef RCC_ClkInitStruct;

   /**Initializes the CPU, AHB and APB busses clocks 
   */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSICalibrationValue = 16;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
 RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
   Error_Handler();
 }

   /**Initializes the CPU, AHB and APB busses 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_0) != HAL_OK)
 {
   Error_Handler();
 }

   /**Configure the Systick interrupt time 
   */
 HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

   /**Configure the Systick 
   */
 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

 /* SysTick_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* CAN init function */
static void MX_CAN_Init(void)
{

 hcan.Instance = CAN1;
 hcan.Init.Prescaler = 16;
 hcan.Init.Mode = CAN_MODE_NORMAL;
 hcan.Init.SJW = CAN_SJW_1TQ;
 hcan.Init.BS1 = CAN_BS1_3TQ;
 hcan.Init.BS2 = CAN_BS2_5TQ;
 hcan.Init.TTCM = DISABLE;
 hcan.Init.ABOM = DISABLE;
 hcan.Init.AWUM = DISABLE;
 hcan.Init.NART = DISABLE;
 hcan.Init.RFLM = DISABLE;
 hcan.Init.TXFP = DISABLE;
 HAL_NVIC_SetPriority(CAN1_RX1_IRQn,0,0);
 HAL_NVIC_GetActive(CAN1_RX1_IRQn);
 if (HAL_CAN_Init(&hcan) != HAL_OK)
 {
   Error_Handler();
 }

}

/** Configure pins as 
       * Analog 
       * Input 
       * Output
       * EVENT_OUT
       * EXTI
*/
static void MX_GPIO_Init(void)
{

 GPIO_InitTypeDef GPIO_InitStruct;

 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();

 /*Configure GPIO pin : PC13 */
 GPIO_InitStruct.Pin = GPIO_PIN_13;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

 /*Configure GPIO pin : LED_G_Pin */
 GPIO_InitStruct.Pin = LED_G_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(LED_G_GPIO_Port, &GPIO_InitStruct);

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);

 /* EXTI interrupt init*/
 HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0);
 HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

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

Tutaj jeszcze kod z pliku "stm32f1xx_it.c":

#include "stm32f1xx_hal.h"
#include "stm32f1xx.h"
#include "stm32f1xx_it.h"

/* USER CODE BEGIN 0 */
extern uint8_t x;
/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern CAN_HandleTypeDef hcan;

/******************************************************************************/
/*            Cortex-M3 Processor Interruption and Exception Handlers         */ 
/******************************************************************************/

/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
 /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

 /* USER CODE END NonMaskableInt_IRQn 0 */
 /* USER CODE BEGIN NonMaskableInt_IRQn 1 */

 /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
 /* USER CODE BEGIN HardFault_IRQn 0 */

 /* USER CODE END HardFault_IRQn 0 */
 while (1)
 {
 }
 /* USER CODE BEGIN HardFault_IRQn 1 */

 /* USER CODE END HardFault_IRQn 1 */
}

/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
 /* USER CODE BEGIN MemoryManagement_IRQn 0 */

 /* USER CODE END MemoryManagement_IRQn 0 */
 while (1)
 {
 }
 /* USER CODE BEGIN MemoryManagement_IRQn 1 */

 /* USER CODE END MemoryManagement_IRQn 1 */
}

/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
 /* USER CODE BEGIN BusFault_IRQn 0 */

 /* USER CODE END BusFault_IRQn 0 */
 while (1)
 {
 }
 /* USER CODE BEGIN BusFault_IRQn 1 */

 /* USER CODE END BusFault_IRQn 1 */
}

/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
 /* USER CODE BEGIN UsageFault_IRQn 0 */

 /* USER CODE END UsageFault_IRQn 0 */
 while (1)
 {
 }
 /* USER CODE BEGIN UsageFault_IRQn 1 */

 /* USER CODE END UsageFault_IRQn 1 */
}

/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
 /* USER CODE BEGIN SVCall_IRQn 0 */

 /* USER CODE END SVCall_IRQn 0 */
 /* USER CODE BEGIN SVCall_IRQn 1 */

 /* USER CODE END SVCall_IRQn 1 */
}

/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
 /* USER CODE BEGIN DebugMonitor_IRQn 0 */

 /* USER CODE END DebugMonitor_IRQn 0 */
 /* USER CODE BEGIN DebugMonitor_IRQn 1 */

 /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
 /* USER CODE BEGIN PendSV_IRQn 0 */

 /* USER CODE END PendSV_IRQn 0 */
 /* USER CODE BEGIN PendSV_IRQn 1 */

 /* USER CODE END PendSV_IRQn 1 */
}

/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
 /* USER CODE BEGIN SysTick_IRQn 0 */

 /* USER CODE END SysTick_IRQn 0 */
 HAL_IncTick();
 HAL_SYSTICK_IRQHandler();
 /* USER CODE BEGIN SysTick_IRQn 1 */

 /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
* @brief This function handles CAN RX1 interrupt.
*/
void CAN1_RX1_IRQHandler(void)
{
 /* USER CODE BEGIN CAN1_RX1_IRQn 0 */

 /* USER CODE END CAN1_RX1_IRQn 0 */
 HAL_CAN_IRQHandler(&hcan);
 /* USER CODE BEGIN CAN1_RX1_IRQn 1 */
 HAL_CAN_Receive_IT(&hcan,CAN_FIFO0);
 GPIOA->ODR = hcan.pRxMsg->Data[0]<<5;
 /* USER CODE END CAN1_RX1_IRQn 1 */
}

/**
* @brief This function handles EXTI line[15:10] interrupts.
*/
void EXTI15_10_IRQHandler(void)
{
 /* USER CODE BEGIN EXTI15_10_IRQn 0 */
HAL_Delay(50);
	if (HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)==GPIO_PIN_SET)
	{
		x++;
		hcan.pTxMsg->Data[0]=x;
		HAL_CAN_Transmit(&hcan,1);
	}
 /* USER CODE END EXTI15_10_IRQn 0 */
 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
 /* USER CODE BEGIN EXTI15_10_IRQn 1 */

 /* USER CODE END EXTI15_10_IRQn 1 */
}

Podczas debugowania przy przyciśnięciu przycisku (PC13) zmienna x inkrementuje się, jednak na drugiej płytce stan diody się nie zmienia. Przy wgrywaniu programu dla drugiego procka, oczywiście zmieniłem jego adres (StdId) na inny. Czy ktoś jest w stanie znaleźć źródło problemu?

Z góry dziękuję za wszelką pomoc i pozdrawiam.

@edit: dodam jeszcze, że wyjścia Tx połączyłem odpowiednio za pomocą diod 1N4148 do wejść Rx drugiego procka.

Link do komentarza
Share on other sites

Kolejno LED_G_Pin i LED_G_GPIO_Port są to GPIO_PIN_5 i GPIOA. Są to dodane etykiety z poziomu Cube'a do wyprowadzenia zielonej diody LED na płytce Nucleo.

Schemat połączeń:

CAN_SCH.png

__________

Komentarz dodany przez: Sabre

Link do komentarza
Share on other sites

Jestem na 75% pewny że to problemy z ustawieniem filtru pakietów. Jesteś pewien co do poprawności jego ustawień?

Drugie pytanie to czy masz może oscyloskop lub analizator logiczny żeby sprawdzić przebiegi na wyjściu mikrokontrolera nadającego? Bardziej chodzi o samo sprawdzenie czy mikrokontroler nadaje (ew. na analizatorze możesz zweryfikować poprawność ustawień modułu CAN).

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Co do poprawności ustawień filtrów nie miałem pewności i szukając odpowiedzi w internecie doszedłem do wniosku, że powinienem wykorzystać do filtrowania tryb maskowania i użyłem CAN_FILTERMODE_IDMASK zamiast CAN_FILTERMODE_IDLIST, niestety nic to nie dało.

Niestety nie mam teraz dostępu do żadnego oscyloskopu ani analizatora stanów logicznych.

Link do komentarza
Share on other sites

Ogólnie to pamiętam, że jak próbowałem kiedyś konfigurować moduł CAN to właśnie pojawiły się u mnie problemy z poprawnym filtrowaniem. Niestety w tej chwili nie jestem w stanie znaleźć konkretnego kodu (ani przypomnieć sobie co było dokładnie nie tak)...

Link do komentarza
Share on other sites

Czy jest możliwe w ogóle wyłączenie filtrowania, aby sprawdzić czy cokolwiek jest wysyłane? Zmieniłem wartość parametru FilterActivation na DISABLE, jednak to nie podziałało. Czy jest inna metoda?

Link do komentarza
Share on other sites

Znalazłem rozwiązanie problemu, może się komuś przyda.

Należało samemu dodać do kodu linijkę aktywującą przerwanie przy odbiorze ramki, w tym celu dopisałem w funkcji main kod:

HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);

i podziałało.

Zauważyłem tu, że Cube przy generowaniu kodu może nie aktywować wszystkich przerwań, mimo że były wybierane przeze mnie z poziomu Cube. Nie wiem czy jest to mankament programu, czy po prostu tak powinno być. W każdym razie, temat do zamknięcia.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.