2017-03-05 3 views
0

J'utilise une carte Discovery STM32F469 et j'essaie d'utiliser les fonctions CAN.STM32F4 - Can TX réussit à chaque fois, mais CAN RX ne réussit qu'au premier appel

Je comprends que sur cette carte CAN1 ne peut pas être utilisé en même temps que l'écran tactile. Par conséquent, j'ai besoin d'utiliser CAN2, mais pour activer CAN2, CAN1 doit être activé.

Mon code pour la configuration/callback est la suivante:

/* 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); 
} 

Je lance alors ce qui suit dans ma fonction principale pour configurer le CAN1, CAN2 et l'interruption:

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

Et puis je exécutez le CAN_Transmit_Message(). Pour ce faire, j'ai vérifié que le message réussit à émettre (la LED orange ne s'allume pas), le gestionnaire d'interruption de réception est alors exécuté (la LED jaune s'allume) et le message est reçu avec succès (la LED rouge ne s'allume pas).

Cependant, lors de la deuxième transmission d'un message (un autre appel à CAN_Transmit_Message()), la transmission réussit à nouveau mais la réception échoue (la DEL rouge s'allume).

J'ai créé ce code en suivant la structure dans le code exemple CAN_Networking, mais je ne peux pas comprendre pourquoi il échoue à la fonction HAL_CAN_Receive_IT sur le deuxième message (après la réception du premier message).

REMARQUE: Après avoir lu le fichier de bibliothèque stm32f4xx_HAL_CAN, j'ai remarqué il y a deux types de réception/transmission:

  1. HAL_CAN_Transmit_IT/HAL_CAN_Receive_IT
  2. HAL_CAN_Transmit/HAL_CAN_Receive

Il dit que 1. est non bloquant - je suppose que cela signifie qu'une autre interruption peut être déclenchée alors que cette transmission/réception est toujours en cours?

Dans mon cas, je veux m'assurer que je reçois les données de réponse après avoir envoyé la transmission pour le demander, alors devrais-je utiliser la fonction 2.? C'est à dire. J'appellerais HAL_CAN_Transmit avec un délai d'expiration approprié, puis après avoir terminé l'appel HAL_CAN_Receive, à nouveau avec un délai d'attente approprié.

Répondre

0

Appellez-vous HAL_CAN_Receive_IT chaque fois que vous recevez une réponse?

C'est un coup de feu. Pour continuer à recevoir, appelez-le à nouveau dans votre gestionnaire d'interruption.