Skocz do zawartości
Dziobak94

[STM32F3] Magistrala CAN i biblioteki HAL

Pomocna odpowiedź

Cześć,
Od dwóch dni staram się uporać z komunikacją dwóch mikro-kontrolerów ze sobą przez magistralę CAN.

Wykorzystuję do tego płytki Nucleo F303RE, na razie bez transcrivera, jednak połączone są ze sobą RX->TX i TX->RX (tylko 2 płytki więc nie powinno być problemu).

Tu poniżej kod dla 1 i 2 płytki (różnią się tylko wnętrzem pętli While, raz za komentowana jedna część raz druga)

Jeśli można prosić o jakąś wskazówkę co robię nie tak.

Kod jak widać tworzony przez CubeMX

/**
 ******************************************************************************
 * File Name          : main.c
 * Description        : Main program body
 ******************************************************************************
 *
 * COPYRIGHT(c) 2016 STMicroelectronics
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of STMicroelectronics nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */
/* Includes ------------------------------------------------------------------*/
#include "stm32f3xx_hal.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

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

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
CanRxMsgTypeDef Rxcan;
CanTxMsgTypeDef Txcan;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
static void dane0(void);
static void dane1(void);
static void odbior(void);

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

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
int abc;
/* 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 */
 __CAN_CLK_ENABLE ();
 __GPIOD_CLK_ENABLE ();

 /* USER CODE END 2 */

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

 /* USER CODE BEGIN 3 */

  odbior();
  abc=CAN_RDL0R_DATA0;
  if(abc==0b11011111)
  {
	  HAL_GPIO_TogglePin(ULN25_GPIO_Port,ULN25_Pin);
  }

/*
  dane0();
  HAL_GPIO_TogglePin(ULN25_GPIO_Port,ULN25_Pin);
  HAL_Delay(200);
  dane1();
  HAL_GPIO_TogglePin(ULN25_GPIO_Port,ULN25_Pin);
  HAL_Delay(500);
*/
 }
 /* USER CODE END 3 */

}

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

 RCC_OscInitTypeDef RCC_OscInitStruct;
 RCC_ClkInitTypeDef RCC_ClkInitStruct;

 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSICalibrationValue = 16;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 HAL_RCC_OscConfig(&RCC_OscInitStruct);

 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                             |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);

 HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

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

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

 hcan.Instance = CAN;
 hcan.Init.Prescaler = 16;
 hcan.Init.Mode = CAN_MODE_NORMAL;
 hcan.Init.SJW = CAN_SJW_1TQ;
 hcan.Init.BS1 = CAN_BS1_1TQ;
 hcan.Init.BS2 = CAN_BS2_1TQ;
 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_CAN_Init(&hcan);

}

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

 GPIO_InitTypeDef GPIO_InitStruct;

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

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(GPIOA, S_STOP_Pin|ULN25_Pin|ULN24_Pin|ULN23_Pin 
                         |ULN17_Pin|ULN18_Pin|S_POZ_Pin, GPIO_PIN_RESET);

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(GPIOB, ULN16_Pin|S_ML_Pin|ULN15_Pin|S_MP_Pin 
                         |ULN22_Pin|ULN27_Pin|ULN26_Pin, GPIO_PIN_RESET);

 /*Configure GPIO pin Output Level */
 HAL_GPIO_WritePin(GPIOC, ULN21_Pin|ULN28_Pin|P_SYR_Pin|P_KOG_Pin, GPIO_PIN_RESET);

 /*Configure GPIO pins : S_STOP_Pin ULN25_Pin ULN24_Pin ULN23_Pin 
                          ULN17_Pin ULN18_Pin S_POZ_Pin */
 GPIO_InitStruct.Pin = S_STOP_Pin|ULN25_Pin|ULN24_Pin|ULN23_Pin 
                         |ULN17_Pin|ULN18_Pin|S_POZ_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 /*Configure GPIO pins : ULN16_Pin S_ML_Pin ULN15_Pin S_MP_Pin 
                          ULN22_Pin ULN27_Pin ULN26_Pin */
 GPIO_InitStruct.Pin = ULN16_Pin|S_ML_Pin|ULN15_Pin|S_MP_Pin 
                         |ULN22_Pin|ULN27_Pin|ULN26_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 /*Configure GPIO pins : ULN21_Pin ULN28_Pin P_SYR_Pin P_KOG_Pin */
 GPIO_InitStruct.Pin = ULN21_Pin|ULN28_Pin|P_SYR_Pin|P_KOG_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */
void odbior(void)
{
Rxcan.IDE = CAN_ID_STD;
Rxcan.StdId = 100;
Rxcan.RTR = CAN_RTR_DATA;
Rxcan.DLC = 8;
Rxcan.FIFONumber = CAN_FIFO0;
hcan.pRxMsg = &Rxcan;
HAL_CAN_Receive(&hcan,0,1000);
}

void dane1(void)
{
Txcan.IDE = CAN_ID_STD;
Txcan.StdId = 100;
Txcan.RTR = CAN_RTR_DATA;
Txcan.DLC = 8;
Txcan.Data [0] = 0b11011111;
hcan.pTxMsg = &Txcan;
HAL_CAN_Transmit(&hcan,100);
}
void dane0(void)
{
Txcan.IDE = CAN_ID_STD;
Txcan.StdId = 100;
Txcan.RTR = CAN_RTR_DATA;
Txcan.DLC = 8;
Txcan.Data [0] = 0b00000000;
hcan.pTxMsg = &Txcan;
HAL_CAN_Transmit(&hcan,100);
}
/* USER CODE END 4 */

#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,
   ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */

}

#endif

/**
 * @}
 */ 

/**
 * @}
*/ 

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

Z góry dzięki za każdą pomoc,
Pozdrawiam,
Tomasz

Udostępnij ten post


Link to post
Share on other sites

CAN znam tylko z teorii (a i z STM32 nie mam wielkiego doświadczenia), ale dwa pytania jakie przychodzą mi do głowy:

1. Skąd przekonanie że komunikacja będzie działała bez odpowiedniej warstwy fizycznej?

2. Czy podłączałeś oscyloskop do wyjścia układu wysyłającego dane?

Udostępnij ten post


Link to post
Share on other sites

AD1 : Transceiver CAN służy do tego jak mówiłeś zmiany sygnału, do odpowiedniej warstwy fizycznej. Jednak oba uC komunikują się po tej samej warstwie, fakt jest taki że bez nich nie da się podłączyć większej ilości urządzeń. ale Transceiver zmienia warstwę A na B, z drugiej strony dzieje się na odwrót z B na A.

AD2 : Niestety nie mam nigdzie na stanie Oscyloskopu, ale będę musiał gdzieś się przejść żeby dostać dostęp 🙂

Ma ktoś jakieś inny pomysł ?

Udostępnij ten post


Link to post
Share on other sites

A w jaki sposób stworzyłeś kod który napisałeś? Wzorowałeś się na jakimś przykładzie, czy raczej wykorzystałeś dokumentację uc i dokumentację biblioteki?

Jeżeli to drugie to może spróbuj wersji z uruchomieniem podstawowego przykładu i potem wprowadzania modyfikacji do działającego rozwiązania?

Udostępnij ten post


Link to post
Share on other sites

Dzięki za rady,

Ogólnie to korzystałem i z jednego i z drugiego. Wygląda jednak na to że kontroler nasłuchuje sieć tak że potrzebny jest Transcriver.

Po inicjalizacji wysyłane jest kilka bitów (tak jakby sprawdzanie sieci, albo odpytywanie Transcrivera) po czym wyskakuje błąd kontrolera (Stan najpierw TIMEOUT potem ERROR).

Jakieś rady ?

W poniedziałek skoczę po Transcrivery na THT albo cały moduł.

Udostępnij ten post


Link to post
Share on other sites

Zobacz ten dokument: http://www.keil.com/appnotes/files/apnt_236.pdf

Strona 4 (dół)

Sometimes you have a CAN equipped processor on a low cost board but it has no CAN transceiver chips. Here is a method

that can be used to create a small experimental network with such a board. There will be no noise immunity and you might

have to lower the speed….but many experimenters have made this work satisfactorily. Use a signal diode similar to 1N914

or 1N4148. Power supply diodes usually do not have a fast enough recovery time for CAN to function.

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

Dzięki wielkie ! Problemy zaczynają się klarować.

Mam tylko jedno pytanie, czy ktoś próbował wykorzystać funkcję HAL_CAN_Tranmit_IT i HAL_CAN_Receive_IT ? Mi udaje się tylko przy Transmit_IT i zwykłym Receive. Do tego nie potrafię odpalić ponownie transmisji. Dane wysyłają się tylko raz. (Oczywiście udanie raz, jak nie dostaną odpowiedzi że zostały wysłuchane wiadomość się zapętla aż ktoś potwierdzi otrzymanie komunikatu).

EDIT 2:11 :

Dodam jeszcze że za pomocą tzw Pollingu wszystko gładko poszło 😉 wygląda na to że nie potrafię porządnie obsłużyć przerwań. za pomocą CallBack'ów. 😳

[ Dodano: 10-05-2016, 00:09 ]

Dziękuję wszystkim pięknie za pomoc ! Udało mi się odpalić Całość za pomocą przerwań 🙂

Temat do zamknięcia.

Udostępnij ten post


Link to post
Share on other sites

Cześć,
Od jakiegoś czasu walczę z uruchomieniem magistrali CAN na STM32. Jest to fragment większego projektu, który zakłada:

- customową płytkę z STM32F303

- FreeRTOS

W przypadku wystąpienia przerwania przychodzącej wiadomości CAN funkcja obsługująca przerwanie ma ustawić odpowiednią flagę - reakcja na flagę będzie w odpowiednim wątku RTOSa.

Mam problem z kilkoma rzeczmi:

- fizyczną inicjalizacją odpowiednich GPIO do komunikacji z CAN (złącze wlutowane na pinach PB8, PB9)

- obsługą samego przerwania (jakaś funkcja biblioteki HAL?)

- funkcjami wysyłania i odbierania wiadomości CAN

Ktoś wie co i jak?

Do tej pory programowałem CAN na Raspberry i było troszkę łatwiej 😋

Edit. Wszystkie inicjalizacje przechodzą ok. Natomiast

status = HAL_CAN_Transmit(&sysH->hCAN, 100);

zwraca HAL_TIMEOUT

Ktoś jest w stanie podpowiedzieć dlaczego tak? Na magistrali CAN mam podpięty Raspberry z PiCAN który "zbiera" wszystko, niestety nic na magistrali się nie pojawia.

Kod:

void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{

GPIO_InitTypeDef GPIO_InitStruct;
if (hcan->Instance == CAN)
{
/* USER CODE BEGIN CAN_MspInit 0 */

  /* USER CODE END CAN_MspInit 0 */
    /* Peripheral clock enable */
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_CAN1_CLK_ENABLE();


    /**CAN GPIO Configuration    
    PB8     ------> CAN_RX
    PB9     ------> CAN_TX 
    */
	GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF9_CAN;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

	    /* CAN interrupt Init */
	HAL_NVIC_SetPriority(USB_HP_CAN_TX_IRQn, 8, 0);
	HAL_NVIC_EnableIRQ(USB_HP_CAN_TX_IRQn);
	HAL_NVIC_SetPriority(USB_LP_CAN_RX0_IRQn, 8, 0);
	HAL_NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn);
	HAL_NVIC_SetPriority(CAN_RX1_IRQn, 8, 0);
	HAL_NVIC_EnableIRQ(CAN_RX1_IRQn);
	HAL_NVIC_SetPriority(CAN_SCE_IRQn, 8, 0);
	HAL_NVIC_EnableIRQ(CAN_SCE_IRQn);
  /* USER CODE BEGIN CAN_MspInit 1 */



    /* USER CODE END CAN_MspInit 1 */
}

}

int CCANControler::init(TSystemHandlers* sysH)
{
CModule::init(sysH);
sysH->hCAN.Instance = CAN;
sysH->hCAN.Init.Prescaler = 16;
sysH->hCAN.Init.Mode = CAN_MODE_NORMAL;
sysH->hCAN.Init.SJW = CAN_SJW_1TQ;
sysH->hCAN.Init.BS1 = CAN_BS1_1TQ;
sysH->hCAN.Init.BS2 = CAN_BS2_1TQ;
sysH->hCAN.Init.TTCM = DISABLE;
sysH->hCAN.Init.ABOM = DISABLE;
sysH->hCAN.Init.AWUM = DISABLE;
sysH->hCAN.Init.NART = DISABLE;
sysH->hCAN.Init.RFLM = DISABLE;
sysH->hCAN.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&sysH->hCAN) != HAL_OK)
{
//	Error_Handler();
}
 /* CAN filter init */




}


int CCANControler::handle()
{
static CanTxMsgTypeDef        TxMsg;
static CanRxMsgTypeDef        RxMsg;

sysH->hCAN.pTxMsg = &TxMsg;
sysH->hCAN.pRxMsg = &RxMsg;

while (1)
{

	HAL_CAN_Receive_IT(&sysH->hCAN, 0);

//sprawdzic semafor, czy dostałeś dane, wykonać odczyt
	if (xSemaphoreTake(sysH->sh_CANRead_bin, 1))
	{



	}
	//wysyłanie ramek

	TxMsg.StdId = 0x100;
	TxMsg.RTR = CAN_RTR_DATA;
	TxMsg.IDE = CAN_ID_STD;
	TxMsg.DLC = 2;
	TxMsg.Data[0] = 0x01;
	TxMsg.Data[1] = 0x02;

	if (HAL_CAN_Init(&sysH->hCAN) == HAL_OK)

	{

	    //Everythying OK, so send the message
		//HAL_CAN_Transmit_IT(&sysH->hCAN);
		HAL_StatusTypeDef status;
		status = HAL_CAN_Transmit(&sysH->hCAN, 100);
	}
	vTaskDelayUntil(&lastWakeTime, 10);
}
}

Udostępnij ten post


Link to post
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!

Gość
Napisz odpowiedź...

×   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...