2017-03-05 4 views
0

Ich benutze ein STM32F469 Discovery Board und versuche die CAN-Funktionen zu nutzen.STM32F4 - Can TX ist immer erfolgreich, aber CAN RX ist nur beim ersten Aufruf erfolgreich

Ich verstehe, dass auf dieser Platine CAN1 nicht gleichzeitig mit dem Touchscreen verwendet werden kann. Daher muss ich CAN2 verwenden, aber um CAN2 zu aktivieren, muss CAN1 aktiviert sein.

Mein Code für die Konfiguration/Callback ist wie folgt:

/* CAN1 Values */ 
#define CAN1_CLK_ENABLE()    __HAL_RCC_CAN1_CLK_ENABLE() 
#define CAN1_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE() 
#define CAN1_FORCE_RESET()    __HAL_RCC_CAN1_FORCE_RESET() 
#define CAN1_RELEASE_RESET()   __HAL_RCC_CAN1_RELEASE_RESET() 
#define CAN1_TX_PIN     GPIO_PIN_9 
#define CAN1_TX_GPIO_PORT    GPIOB 
#define CAN1_TX_AF      GPIO_AF9_CAN1 
#define CAN1_RX_PIN     GPIO_PIN_8 
#define CAN1_RX_GPIO_PORT    GPIOB 
#define CAN1_RX_AF      GPIO_AF9_CAN1 
#define CAN1_RX_IRQn     CAN1_RX0_IRQn 
#define CAN1_RX_IRQHandler    CAN1_RX0_IRQHandler 

/* CAN2 Values */ 
#define CAN2_CLK_ENABLE()    __HAL_RCC_CAN2_CLK_ENABLE() 
#define CAN2_GPIO_CLK_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE() 
#define CAN2_FORCE_RESET()    __HAL_RCC_CAN2_FORCE_RESET() 
#define CAN2_RELEASE_RESET()   __HAL_RCC_CAN2_RELEASE_RESET() 
#define CAN2_TX_PIN     GPIO_PIN_13 
#define CAN2_TX_GPIO_PORT    GPIOB 
#define CAN2_TX_AF      GPIO_AF9_CAN2 
#define CAN2_RX_PIN     GPIO_PIN_5 
#define CAN2_RX_GPIO_PORT    GPIOB 
#define CAN2_RX_AF      GPIO_AF9_CAN2 
#define CAN2_RX_IRQn     CAN2_RX0_IRQn 
#define CAN2_RX_IRQHandler    CAN2_RX0_IRQHandler 

CAN_HandleTypeDef CanHandle1; 
CAN_HandleTypeDef CanHandle2; 

static uint8_t Message_Data[8]; 

static void CAN1_Config(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStruct; 
    CAN_FilterConfTypeDef CAN_FilterInitStructure; 

    static CanTxMsgTypeDef  TxMessage; 
    static CanRxMsgTypeDef  RxMessage; 

    /* CAN1 Periph clock enable */ 
    CAN1_CLK_ENABLE(); 
    CAN1_GPIO_CLK_ENABLE(); 

    /* CAN1 TX GPIO pin configuration */ 
    GPIO_InitStruct.Pin = CAN1_TX_PIN; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    GPIO_InitStruct.Alternate = CAN1_TX_AF; 

    HAL_GPIO_Init(CAN1_TX_GPIO_PORT, &GPIO_InitStruct); 

    /* CAN1 RX GPIO pin configuration */ 
    GPIO_InitStruct.Pin = CAN1_RX_PIN; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    GPIO_InitStruct.Alternate = CAN1_RX_AF; 

    HAL_GPIO_Init(CAN1_RX_GPIO_PORT, &GPIO_InitStruct); 

    /* NVIC configuration for CAN1 Reception complete interrupt */ 
    HAL_NVIC_SetPriority(CAN1_RX_IRQn, 1, 0); 
    HAL_NVIC_EnableIRQ(CAN1_RX_IRQn); 

    CanHandle1.Instance = CAN1; 
    CanHandle1.pTxMsg = &TxMessage; 
    CanHandle1.pRxMsg = &RxMessage; 

    /* CAN peripheral init */ 
    CanHandle1.Init.TTCM = DISABLE; 
    CanHandle1.Init.ABOM = DISABLE; 
    CanHandle1.Init.AWUM = DISABLE; 
    CanHandle1.Init.NART = DISABLE; 
    CanHandle1.Init.RFLM = DISABLE; 
    CanHandle1.Init.TXFP = DISABLE; 
    CanHandle1.Init.Mode = CAN_MODE_LOOPBACK; 
    CanHandle1.Init.SJW = CAN_SJW_1TQ; 
    CanHandle1.Init.BS1 = CAN_BS1_6TQ; 
    CanHandle1.Init.BS2 = CAN_BS2_8TQ; 
    CanHandle1.Init.Prescaler = 2; 

    HAL_CAN_Init(&CanHandle1); 

    /* CAN filter init */ 
    CAN_FilterInitStructure.FilterNumber = 0; 
    CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK; 
    CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT; 
    CAN_FilterInitStructure.FilterIdHigh = 0x0000; 
    CAN_FilterInitStructure.FilterIdLow = 0x0000; 
    CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000; 
    CAN_FilterInitStructure.FilterMaskIdLow = 0x0000; 
    CAN_FilterInitStructure.FilterFIFOAssignment = 0; 
    CAN_FilterInitStructure.FilterActivation = ENABLE; 
    CAN_FilterInitStructure.BankNumber = 0; 

    HAL_CAN_ConfigFilter(&CanHandle1, &CAN_FilterInitStructure); 

    /* Configure transmission */ 
    CanHandle1.pTxMsg->StdId = 0x7DF; 
    CanHandle1.pTxMsg->ExtId = 0x7DF; 
    CanHandle1.pTxMsg->RTR = CAN_RTR_DATA; 
    CanHandle1.pTxMsg->IDE = CAN_ID_STD; 
    CanHandle1.pTxMsg->DLC = 8; 
}  

static void CAN2_Config(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStruct; 
    CAN_FilterConfTypeDef CAN_FilterInitStructure; 

    static CanTxMsgTypeDef  TxMessage; 
    static CanRxMsgTypeDef  RxMessage; 

    /* CAN2 Periph clock enable */ 
    CAN2_CLK_ENABLE(); 
    CAN2_GPIO_CLK_ENABLE(); 

    /* CAN2 TX GPIO pin configuration */ 
    GPIO_InitStruct.Pin = CAN2_TX_PIN; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    GPIO_InitStruct.Alternate = CAN2_TX_AF; 

    HAL_GPIO_Init(CAN2_TX_GPIO_PORT, &GPIO_InitStruct); 

    /* CAN2 RX GPIO pin configuration */ 
    GPIO_InitStruct.Pin = CAN2_RX_PIN; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    GPIO_InitStruct.Alternate = CAN2_RX_AF; 

    HAL_GPIO_Init(CAN2_RX_GPIO_PORT, &GPIO_InitStruct); 

    /* NVIC configuration for CAN2 Reception complete interrupt */ 
    HAL_NVIC_SetPriority(CAN2_RX_IRQn, 1, 0); 
    HAL_NVIC_EnableIRQ(CAN2_RX_IRQn); 

    CanHandle2.Instance = CAN2; 
    CanHandle2.pTxMsg = &TxMessage; 
    CanHandle2.pRxMsg = &RxMessage; 

    /* CAN peripheral init */ 
    CanHandle2.Init.TTCM = DISABLE; 
    CanHandle2.Init.ABOM = DISABLE; 
    CanHandle2.Init.AWUM = DISABLE; 
    CanHandle2.Init.NART = DISABLE; 
    CanHandle2.Init.RFLM = DISABLE; 
    CanHandle2.Init.TXFP = DISABLE; 
    CanHandle2.Init.Mode = CAN_MODE_LOOPBACK; 
    CanHandle2.Init.SJW = CAN_SJW_1TQ; 
    CanHandle2.Init.BS1 = CAN_BS1_6TQ; 
    CanHandle2.Init.BS2 = CAN_BS2_8TQ; 
    CanHandle2.Init.Prescaler = 2; 

    HAL_CAN_Init(&CanHandle2); 

    /* CAN filter init */ 
    CAN_FilterInitStructure.FilterNumber = 0; //14 enables CAN1; 
    CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK; 
    CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT; 
    CAN_FilterInitStructure.FilterIdHigh = 0x0000; 
    CAN_FilterInitStructure.FilterIdLow = 0x0000; 
    CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000; 
    CAN_FilterInitStructure.FilterMaskIdLow = 0x0000; 
    CAN_FilterInitStructure.FilterFIFOAssignment = 0; 
    CAN_FilterInitStructure.FilterActivation = ENABLE; 
    CAN_FilterInitStructure.BankNumber = 0; //14 enables CAN1 

    HAL_CAN_ConfigFilter(&CanHandle2, &CAN_FilterInitStructure); 

    /* Configure transmission */ 
    CanHandle2.pTxMsg->StdId = 0x7DF; 
    CanHandle2.pTxMsg->ExtId = 0x7DF; 
    CanHandle2.pTxMsg->RTR = CAN_RTR_DATA; 
    CanHandle2.pTxMsg->IDE = CAN_ID_STD; 
    CanHandle2.pTxMsg->DLC = 8; 
} 

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle) 
{ 
    EwBspYellowLedOn(); 

    Message_Data[0] = CanHandle->pRxMsg->Data[0]; 
    Message_Data[1] = CanHandle->pRxMsg->Data[1]; 
    Message_Data[2] = CanHandle->pRxMsg->Data[2]; 
    Message_Data[3] = CanHandle->pRxMsg->Data[3]; 
    Message_Data[4] = CanHandle->pRxMsg->Data[4]; 
    Message_Data[5] = CanHandle->pRxMsg->Data[5]; 
    Message_Data[6] = CanHandle->pRxMsg->Data[6]; 
    Message_Data[7] = CanHandle->pRxMsg->Data[7]; 

    if (HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK) 
    { 
    EwBspRedLedOn(); 
    } 
} 

CAN_Transmit_Message(void) 
{ 
    CanHandle2.pTxMsg->StdId = 0x7DF; 
    CanHandle2.pTxMsg->ExtId = 0x7DF; 
    CanHandle2.pTxMsg->Data[0] = 0x02; 
    CanHandle2.pTxMsg->Data[1] = 0x01; 
    CanHandle2.pTxMsg->Data[2] = 0x0D; 
    CanHandle2.pTxMsg->Data[3] = 0x55; 
    CanHandle2.pTxMsg->Data[4] = 0x55; 
    CanHandle2.pTxMsg->Data[5] = 0x55; 
    CanHandle2.pTxMsg->Data[6] = 0x55; 
    CanHandle2.pTxMsg->Data[7] = 0x55; 

    if (HAL_CAN_Transmit(&CanHandle, 10) != HAL_OK) 
    { 
    EwBspOrangeLedOn(); 
    } 

    HAL_Delay(10); 
} 

ich dann folgend in meiner Hauptfunktion ausführen, um die CAN1, CAN2 und die Unterbrechung zu konfigurieren:

/* Configure interrupt for CAN transmission */ 
CAN1_Config(); 
CAN2_Config(); 
HAL_CAN_Receive_IT(&CanHandle2, CAN_FIFO0); 

Und ich dann Führen Sie die CAN_Transmit_Message().

Dabei habe ich verifiziert, dass die Nachricht erfolgreich übertragen wurde (die orange LED leuchtet NICHT), der Empfangs-Interrupt-Handler wird ausgeführt (gelbe LED leuchtet) und die Nachricht wurde erfolgreich empfangen (rote LED leuchtet nicht)).

Bei der zweiten Übertragung einer Nachricht (ein anderer Aufruf an CAN_Transmit_Message()) ist die Übertragung jedoch erneut erfolgreich, aber der Empfang schlägt fehl (rote LED leuchtet).

Ich habe diesen Code erstellt, indem ich der Struktur im CAN_Networking-Beispielcode gefolgt bin, aber ich kann nicht herausfinden, warum es bei der HAL_CAN_Receive_IT-Funktion auf der zweiten Nachricht fehlschlägt (nachdem die erste Nachricht erfolgreich empfangen wurde).

HINWEIS: Nach der stm32f4xx_HAL_CAN Bibliotheksdatei zu lesen, bemerkte ich, gibt es zwei Arten von Empfangs-/Sende:

  1. HAL_CAN_Transmit_IT/HAL_CAN_Receive_IT
  2. HAL_CAN_Transmit/HAL_CAN_Receive

Er sagt, dass 1. ist nicht blockierend - ich nehme an, dass ein anderer Interrupt ausgelöst werden kann, während dieser Sende-/Empfangsvorgang noch läuft?

In meinem Fall möchte ich sicherstellen, dass ich die Antwortdaten nach dem Senden der Übertragung erhalten, um es anzufordern, also sollte ich Funktion 2 verwenden? I.e. Ich würde HAL_CAN_Transmit mit einem geeigneten Timeout aufrufen und dann, nachdem der Aufruf HAL_CAN_Receive beendet ist, erneut mit einem geeigneten Timeout.

Antwort

0

Rufen Sie HAL_CAN_Receive_IT jedes Mal auf, wenn Sie eine Antwort erhalten?

Es ist ein Schuss. Um weiter zu empfangen, rufen Sie es erneut in Ihrem Interrupt-Handler auf.

Verwandte Themen