STM32 FDCAN 通信:如何在 STM32U5 上使用低级编程设置 FDCAN? [已解决]

问题描述 投票:0回答:2

我目前正在尝试在 STM32U575 微控制器上初始化和配置 FDCAN,以与 microchip CAN 总线分析仪进行通信。所有编码都是使用 Keil uVision studio 在低级嵌入式 C 语言中完成的。我的设置包括 1x STM32U575 微控制器、1x Can 总线分析器以及连接到板上 Rx 和 Tx 引脚的两根电缆。我能够初始化基本参数,例如位时序、FIFO 操作、操作模式。然而,当涉及到配置数据长度代码 (DLC)、标准 ID 和要传输的实际消息时,我并不完全确定如何执行此操作,因为没有专用于这些参数的寄存器。我相信我必须按照参考手册here中的建议与存储这些参数的RAM进行通信,但它没有指出哪些寄存器需要更改。因此,我对这里需要什么程序感到困惑,因为我以前使用过的微控制器 (STM32F303) 有专用寄存器用于对 DLC、标准 ID 和要传输的消息进行编程。该芯片的工作原理显然有点不同。

[FDCAN RX FIFO 元素](As you can see, the information stored in the RX FIFO element contains DLC and ID data fields which
I need to program.)

[RX FIFO 寄存器](The only dedicated registers to Rx FIFO are the Rx FIFO acknowledge and Rx status. I cannot write the DLC and ID into those registers)

这是我到目前为止生成的代码:

#include "stm32u575xx.h"


typedef struct {
    uint32_t identifier;       // Message identifier
    uint8_t dataLength;        // Number of data bytes (up to 64)
    uint8_t data[64];          // Data bytes
} FDCAN_Message;


FDCAN_Message message;
void FDCAN_SendMessage(FDCAN_Message* message);
static void FDCAN1_Init(void);


int main(void)
{
    FDCAN1_Init();

    message.identifier = 0x123;     // Set the message identifier
    message.dataLength = 8;        // Set the number of data bytes
    message.data[0] = 0xAA;        // Set the data bytes (example values)
    message.data[1] = 0xBB;
    

}


static void FDCAN1_Init(void)
{
    RCC -> APB1ENR2 |= RCC_APB1ENR2_FDCAN1EN;
    RCC -> CCIPR1 &= ~ RCC_CCIPR1_FDCANSEL_0;
    FDCAN1 -> CCCR &= ~ FDCAN_CCCR_INIT;
    
    FDCAN1 -> CCCR |= FDCAN_CCCR_INIT;                              // Set INIT and CCE bits
    while ((FDCAN1->CCCR & FDCAN_CCCR_INIT) == 0U);
    FDCAN1 -> CCCR |= FDCAN_CCCR_CCE;
        FDCAN1 -> CCCR &= ~ FDCAN_CCCR_CSR;//FDCAN1 -> CFGR |= FDCAN_CKDIV_PDIV_Pos;
        FDCAN1 -> CCCR &= ~ FDCAN_CCCR_DAR;                 //AutoRetransmission = ENABLE;                                                                            F       FDCAN1 ->  CCCR |= FDCAN_CCCR_TXP;                    //TransmitPause = ENABLE;                                                           
    FDCAN1 -> CCCR &= ~ FDCAN_CCCR_PXHD_Pos;                    //ProtocolException = DISABLE;                                                                  
    FDCAN1 -> CCCR |= (FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE);      //Frame Format                          
        FDCAN1 -> CCCR |= FDCAN_CCCR_TEST;
    FDCAN1 -> TEST |= FDCAN_TEST_LBCK;      //LOOPBACK mode                                                                 
    FDCAN1->NBTP = 0x000B0905;
    // Configure FDCAN1 bit timings (assuming 500kbps)
    FDCAN1->DBTP = FDCAN_DBTP_DSJW_Pos | FDCAN_DBTP_DTSEG2_Pos| FDCAN_DBTP_DTSEG1_Pos | FDCAN_DBTP_DBRP_Pos;                                                

  FDCAN1 -> TXBC &= ~  FDCAN_TXBC_TFQM;     // TX FIFO operation mode                                                         
    FDCAN1 -> XIDAM &= ~ 0x00000001;                
    FDCAN1 -> XIDAM |= 0x00000001;      //Extended ID mask
    FDCAN1 -> RXGFC |= FDCAN_RXGFC_LSS_Msk;
    FDCAN1 -> RXGFC |= 0x00000020;
    FDCAN1 -> RXGFC |= FDCAN_RXGFC_RRFE;
    FDCAN1 -> RXGFC &= ~ FDCAN_RXGFC_RRFS_Pos;
    FDCAN1 -> CCCR &= ~ FDCAN_CCCR_INIT;
}

我尝试对 STM32CubeMX (FDCAN_LOOPBACK.uvprojx) 中的 HAL 示例代码之一进行逆向工程,并遵循逻辑以查看正在使用哪些寄存器,但我没有成功。理想情况下,我希望有类似于 HAL 示例代码的东西,但转换为低级嵌入式 c。

这是我尝试查看的 HAL 代码的主体:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* STM32U5xx HAL library initialization:
       - Configure the Flash prefetch
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 3
       - Low Level Initialization
     */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the System Power */
  SystemPower_Config();

  /* USER CODE BEGIN SysInit */
  /* Configure LED5 and LED6 */
  BSP_LED_Init(LED5);
  BSP_LED_Init(LED6);

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ICACHE_Init();
  MX_FDCAN1_Init();
  /* USER CODE BEGIN 2 */

  /*##-1 Configure the FDCAN filters ########################################*/
  /* Configure standard ID reception filter to Rx FIFO 0 */
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x444;
  sFilterConfig.FilterID2 = 0x555;
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure extended ID reception filter to Rx FIFO 1 */
  sFilterConfig.IdType = FDCAN_EXTENDED_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_RANGE_NO_EIDM;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
  sFilterConfig.FilterID1 = 0x1111111;
  sFilterConfig.FilterID2 = 0x2222222;
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure global filter:
     Filter all remote frames with STD and EXT ID
     Reject non matching frames with STD ID and EXT ID */
  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
  {
    Error_Handler();
  }

  /*##-2 Start FDCAN controller (continuous listening CAN bus) ##############*/
  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }

  /*##-3 Transmit messages ##################################################*/
  /* Add message to Tx FIFO */
  TxHeader.Identifier = 0x444;
  TxHeader.IdType = FDCAN_STANDARD_ID;
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  TxHeader.DataLength = FDCAN_DLC_BYTES_12;
  TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  TxHeader.BitRateSwitch = FDCAN_BRS_ON;
  TxHeader.FDFormat = FDCAN_FD_CAN;
  TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
  TxHeader.MessageMarker = 0x52;
  if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)
  {
    Error_Handler();
  }

  /* Add second message to Tx FIFO */
  TxHeader.Identifier = 0x1111112;
  TxHeader.IdType = FDCAN_EXTENDED_ID;
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  TxHeader.DataLength = FDCAN_DLC_BYTES_12;
  TxHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  TxHeader.BitRateSwitch = FDCAN_BRS_ON;
  TxHeader.FDFormat = FDCAN_FD_CAN;
  TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
  TxHeader.MessageMarker = 0xCC;
  if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData1) != HAL_OK)
  {
    Error_Handler();
  }

  /* Add third message to Tx FIFO */
  TxHeader.Identifier = 0x1111113;
  TxHeader.IdType = FDCAN_EXTENDED_ID;
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  TxHeader.DataLength = FDCAN_DLC_BYTES_12;
  TxHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
  TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
  TxHeader.FDFormat = FDCAN_FD_CAN;
  TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
  TxHeader.MessageMarker = 0xDD;
  if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData2) != HAL_OK)
  {
    Error_Handler();
  }

  /* Wait transmissions complete */
  while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != 3) {}


  /*##-4 Receive messages ###################################################*/
  /* Check one message is received in Rx FIFO 0 */
  if(HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1)
  {
    Error_Handler();
  }

  /* Retrieve message from Rx FIFO 0 */
  if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
  {
    Error_Handler();
  }

  /* Compare payload to expected data */
  if (BufferCmp8b(TxData0, RxData, 12) != 0)
  {
    Error_Handler();
  }

  /* Check two messages are received in Rx FIFO 1 */
  if(HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2)
  {
    Error_Handler();
  }

  /* Retrieve message from Rx FIFO 1 */
  if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &RxHeader, RxData) != HAL_OK)
  {
    Error_Handler();
  }

  /* Compare payload to expected data */
  if (BufferCmp8b(TxData1, RxData, 12) != 0)
  {
    Error_Handler();
  }

  /* Retrieve next message from Rx FIFO 1 */
  if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &RxHeader, RxData) != HAL_OK)
  {
    Error_Handler();
  }

  /* Compare payload to expected data */
  if (BufferCmp8b(TxData2, RxData, 12) != 0)
  {
    Error_Handler();
  }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* Toggle LED5 */
    BSP_LED_Toggle(LED5);
    HAL_Delay(100);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
embedded stm32 microcontroller can-bus low-level
2个回答
0
投票

更新:我已经成功地在 STM32U575 微控制器上完全使用低级嵌入式 c 设置了 FDCAN 外设。事实证明,该微控制器不提供邮箱或任何可用于将配置和消息写入 RAM 的寄存器。您必须计算您写入的每个地址!此 FDCAN document 列出了有关某些 RAM 地址计算的一些信息。我将把下面的代码发布给将来遇到同样问题的其他人。

    #include "stm32u575xx.h"

#define SET_BIT(REG, BIT)     ((REG) |= (BIT))
#define CLEAR_BIT(REG, BIT)   ((REG) &= ~(BIT))
#define READ_BIT(REG, BIT)    ((REG) & (BIT))
#define CLEAR_REG(REG)        ((REG) = (0x0))
#define WRITE_REG(REG, VAL)   ((REG) = (VAL))
#define READ_REG(REG)         ((REG))
#define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))


/***  RAM defines   ***/
#define SRAMCAN_FLS_NBR                  (28U)         /* Max. Filter List Standard Number      */
#define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
#define SRAMCAN_RF0_NBR                  ( 3U)         /* RX FIFO 0 Elements Number             */
#define SRAMCAN_RF1_NBR                  ( 3U)         /* RX FIFO 1 Elements Number             */
#define SRAMCAN_TEF_NBR                  ( 3U)         /* TX Event FIFO Elements Number         */
#define SRAMCAN_TFQ_NBR                  ( 3U)         /* TX FIFO/Queue Elements Number         */

#define SRAMCAN_FLS_SIZE            ( 1U * 4U)         /* Filter Standard Element Size in bytes */
#define SRAMCAN_FLE_SIZE            ( 2U * 4U)         /* Filter Extended Element Size in bytes */
#define SRAMCAN_RF0_SIZE            (18U * 4U)         /* RX FIFO 0 Elements Size in bytes      */
#define SRAMCAN_RF1_SIZE            (18U * 4U)         /* RX FIFO 1 Elements Size in bytes      */
#define SRAMCAN_TEF_SIZE            ( 2U * 4U)         /* TX Event FIFO Elements Size in bytes  */
#define SRAMCAN_TFQ_SIZE            (18U * 4U)         /* TX FIFO/Queue Elements Size in bytes  */

#define SRAMCAN_FLSSA ((uint32_t)0)                                                      /* Filter List Standard Start
                                                                                            Address                  */
#define SRAMCAN_FLESA ((uint32_t)(SRAMCAN_FLSSA + (SRAMCAN_FLS_NBR * SRAMCAN_FLS_SIZE))) /* Filter List Extended Start
                                                                                            Address                  */
#define SRAMCAN_RF0SA ((uint32_t)(SRAMCAN_FLESA + (SRAMCAN_FLE_NBR * SRAMCAN_FLE_SIZE))) /* Rx FIFO 0 Start Address  */
#define SRAMCAN_RF1SA ((uint32_t)(SRAMCAN_RF0SA + (SRAMCAN_RF0_NBR * SRAMCAN_RF0_SIZE))) /* Rx FIFO 1 Start Address  */
#define SRAMCAN_TEFSA ((uint32_t)(SRAMCAN_RF1SA + (SRAMCAN_RF1_NBR * SRAMCAN_RF1_SIZE))) /* Tx Event FIFO Start
                                                                                            Address */
#define SRAMCAN_TFQSA ((uint32_t)(SRAMCAN_TEFSA + (SRAMCAN_TEF_NBR * SRAMCAN_TEF_SIZE))) /* Tx FIFO/Queue Start
                                                                                            Address                  */
#define SRAMCAN_SIZE  ((uint32_t)(SRAMCAN_TFQSA + (SRAMCAN_TFQ_NBR * SRAMCAN_TFQ_SIZE))) /* Message RAM size         */

#define Tx_Buffer_element_size          (18U * 4U)
#define FDCAN_ELEMENT_MASK_DLC   ((uint32_t)0x000F0000U)                                                                    /* Data Length Code            */

/***************** ------------------------------- Local Types ---------------------------------------------- **************/

typedef struct
{
  uint32_t IdType;           /*!< Specifies the identifier type.
                                  This parameter can be a value of @ref FDCAN_id_type       */

  uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.
                                  This parameter must be a number between:
                                   - 0 and (SRAMCAN_FLS_NBR-1), if IdType is FDCAN_STANDARD_ID
                                   - 0 and (SRAMCAN_FLE_NBR-1), if IdType is FDCAN_EXTENDED_ID */

  uint32_t FilterType;       /*!< Specifies the filter type.
                                  This parameter can be a value of @ref FDCAN_filter_type.
                                  The value FDCAN_FILTER_RANGE_NO_EIDM is permitted
                                  only when IdType is FDCAN_EXTENDED_ID.                    */

  uint32_t FilterConfig;     /*!< Specifies the filter configuration.
                                  This parameter can be a value of @ref FDCAN_filter_config */

  uint32_t FilterID1;        /*!< Specifies the filter identification 1.
                                  This parameter must be a number between:
                                   - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                   - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */

  uint32_t FilterID2;        /*!< Specifies the filter identification 2.
                                  This parameter must be a number between:
                                   - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                   - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */

} FDCAN_FilterTypeDef;


typedef struct
{
  uint32_t Identifier;          /*!< Specifies the identifier.
                                     This parameter must be a number between:
                                      - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                      - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */

  uint32_t IdType;              /*!< Specifies the identifier type for the message that will be
                                     transmitted.
                                     This parameter can be a value of @ref FDCAN_id_type               */

  uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.
                                     This parameter can be a value of @ref FDCAN_frame_type            */

  uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
                                      This parameter can be a value of @ref FDCAN_data_length_code     */

  uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.
                                     This parameter can be a value of @ref FDCAN_error_state_indicator */

  uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
                                     bit rate switching.
                                     This parameter can be a value of @ref FDCAN_bit_rate_switching    */

  uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or
                                     FD format.
                                     This parameter can be a value of @ref FDCAN_format                */

  uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.
                                     This parameter can be a value of @ref FDCAN_EFC                   */

  uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO
                                     element for identification of Tx message status.
                                     This parameter must be a number between 0 and 0xFF                */

} FDCAN_TxHeaderTypeDef;


typedef struct
{
  uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.
                                  This parameter must be a 32-bit word address      */

} FDCAN_MsgRamAddressTypeDef;


typedef struct
{
  uint32_t Identifier;            /*!< Specifies the identifier.
                                       This parameter must be a number between:
                                        - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                        - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */

  uint32_t DataLength;            /*!< Specifies the received frame length.
                                        This parameter can be a value of @ref FDCAN_data_length_code     */


} FDCAN_RxHeaderTypeDef;




/************* ----------------------------------- Local Variables -------------------------------------------- ****************/

static FDCAN_MsgRamAddressTypeDef RAM;
static FDCAN_FilterTypeDef sFilterConfig;
static FDCAN_TxHeaderTypeDef TxMailBox;
static FDCAN_RxHeaderTypeDef RxMailBox;
static const uint8_t DLCtoBytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};

/************* ----------------------------------- Local Functions ---------------------------------------------- **************/
__STATIC_INLINE void LL_RCC_PLL1_ConfigDomain_SYS(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR);
void SystemCoreClockConfigure(void);
void gpio_pins(void);
void FDCAN1_Init(void);
void FDCAN_CalcultateRamBlockAddresses(void);
void StandardFilterConfig(void);
void ExitFDCANInit(void);
void SendMessageToRAM(const uint8_t *TxData);
void TransmissionPending(void);
void ReceiveMessage(void);
void ReadMessage(uint8_t *pRxData);


/************* ----------------------------------- Main Code  --------------------------------------------------- **************/
int main(void)
{
    uint8_t TxData0[] = {0x10, 0x32, 0x54, 0x76, 0x98, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
    uint8_t RxData[12];
    
    RCC -> AHB3ENR |= RCC_AHB3ENR_PWREN;
    SystemCoreClockConfigure();
    gpio_pins();
    FDCAN1_Init();
    StandardFilterConfig();
    ExitFDCANInit();
    SendMessageToRAM(TxData0);
    TransmissionPending();
    ReceiveMessage();
    ReadMessage(RxData);
    
}

void ReadMessage(uint8_t *pRxData)
{
    uint32_t *RxAddress;
    uint32_t GetIndex = 0;
    uint8_t  *pData;
    uint32_t ByteCounter;


/* Check RxFifo not empty                       */
    while(!(FDCAN1->RXF0S & FDCAN_RXF0S_F0FL));
         
/* Calculate Rx FIFO 0 element index */
    GetIndex += ((FDCAN1->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);

/* Calculate Rx FIFO 0 element address */
    RxAddress = (uint32_t *)(SRAMCAN_BASE + SRAMCAN_RF0SA + (GetIndex * SRAMCAN_RF0_SIZE));
                
/****       You can Read First word of RxHeader here with mask values     ****/

/* Increment RxAddress          */
  RxAddress++;
                
/****           You can Read Second word of RxHeader here with mask values      ****/
                
/* Retrieve DataLength          */
  RxMailBox.DataLength = ((*RxAddress & FDCAN_ELEMENT_MASK_DLC) >> 16U);    

/* Increment Rx Address to read received data */
  RxAddress++;
/* Retrieve Rx payload */
    pData = (uint8_t *)RxAddress;
    for (ByteCounter = 0; ByteCounter < DLCtoBytes[RxMailBox.DataLength]; ByteCounter++)
    {
        pRxData[ByteCounter] = pData[ByteCounter];
    }
/* Acknowledge the Rx FIFO 0 that the oldest element is read so that it increments the GetIndex */
    FDCAN1->RXF0A = GetIndex;           
}


void ReceiveMessage(void)
{
    /*  Check one message is received in Rx FIFO 0               */
  while((FDCAN1->RXF0S & FDCAN_RXF0S_F0FL) == 0);
}

void TransmissionPending(void)
{
/* Wait for transmissions to complete                                */
    while((FDCAN1 ->TXFQS  & FDCAN_TXFQS_TFFL) != 3);
}

void SendMessageToRAM(const uint8_t *TxData)
{

    uint32_t TxElementW1;
    uint32_t TxElementW2;
    volatile uint32_t *TxAddress;
    uint32_t ByteCounter;
    uint32_t PutIndex;

    
/* Configure a message to Rx FIF0               */
    TxMailBox.Identifier = 0x444;
  TxMailBox.IdType = 0x00000000U;
  TxMailBox.TxFrameType = ((uint32_t)0x00000000U);                      // Classic frame        
  TxMailBox.DataLength = ((uint32_t)0x00000009U);                           //12 bytes data
  TxMailBox.ErrorStateIndicator = ((uint32_t)0x00000000U);      // Transmission node error-active
  TxMailBox.BitRateSwitch = ((uint32_t)0x00100000U);                    //BRS ON
  TxMailBox.FDFormat = ((uint32_t)0x00200000U);                             //FD ON
  TxMailBox.TxEventFifoControl = ((uint32_t)0x00800000U);           // Store Tx events
  TxMailBox.MessageMarker = 0x52;

/* Copy message to RAM                              */
  while((FDCAN1->TXFQS & FDCAN_TXFQS_TFQF) != 0U);                                  /* Check that the Tx FIFO/Queue is not full */
    
/* Retrieve the Tx FIFO PutIndex */
    PutIndex = ((FDCAN1->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);      
    
/* Add the message to the Tx FIFO/Queue */
    TxElementW1 = (TxMailBox.ErrorStateIndicator | (TxMailBox.Identifier << 18U) | TxMailBox.TxFrameType | (TxMailBox.IdType ));
    TxElementW2 =  ((TxMailBox.MessageMarker << 24U) | TxMailBox.TxEventFifoControl | TxMailBox.FDFormat | TxMailBox.BitRateSwitch | (TxMailBox.DataLength <<16U) );
    
/*  Calculate Tx element address                                                */
  TxAddress = (uint32_t *)(SRAMCAN_BASE + SRAMCAN_TFQSA + (PutIndex * Tx_Buffer_element_size ));
    
/* Write Tx element header to the message RAM                   */
  *TxAddress = TxElementW1;
  TxAddress++;
  *TxAddress = TxElementW2;
  TxAddress++;
    
/* Send Data to RAM                                                                         */
  for (ByteCounter = 0; ByteCounter < DLCtoBytes[TxMailBox.DataLength]; ByteCounter += 4U)
  {
    *TxAddress  = (((uint32_t)TxData[ByteCounter + 3U] << 24U) |
                  ((uint32_t)TxData[ByteCounter + 2U] << 16U) |
                  ((uint32_t)TxData[ByteCounter + 1U] << 8U)  |
                  ((uint32_t)TxData[ByteCounter]));
    TxAddress++;
  }
/* Activate the corresponding transmission request */
    FDCAN1->TXBAR = ((uint32_t)1 << PutIndex);
    
    
}

void ExitFDCANInit(void)
{
    FDCAN1 -> CCCR &= ~ FDCAN_CCCR_INIT;
    while ((FDCAN1->CCCR & FDCAN_CCCR_INIT) != 0U);                                             // wait for FDCAN1 to exit
}

void StandardFilterConfig(void)
{
    volatile uint32_t FilterElementW1;
    volatile uint32_t *FilterAddress;

/* Configure Rx FIF0 Filter                         */
    sFilterConfig.IdType = ((uint32_t)0x00000000U);
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = ((uint32_t)0x00000001U);           /*!< Dual ID filter for FilterID1 or FilterID2                       */
  sFilterConfig.FilterConfig = ((uint32_t)0x00000001U);     /*!< Store in Rx FIFO 0 if filter matches                      */
  sFilterConfig.FilterID1 = 0x444;                                                  // Filter ID1
  sFilterConfig.FilterID2 = 0x555;                                                  // Filter ID2
    
/* Build Rx FIF0 Filter                                         */
    
    FilterElementW1 = ( (sFilterConfig.FilterType << 30U) |                                                                                                     /* Build filter element */
                                     (sFilterConfig.FilterConfig << 27U) |
                                     (sFilterConfig.FilterID1 << 16U)|
                                     sFilterConfig.FilterID2);
    
    FilterAddress = (volatile uint32_t *)(SRAMCAN_BASE + (sFilterConfig.FilterIndex * SRAMCAN_FLS_SIZE));           /* Calculate filter address */
  *FilterAddress = FilterElementW1;                                                                                                                                                 /* Write filter element to the message RAM */
    


}

void FDCAN_CalcultateRamBlockAddresses(void)
{
    uint32_t SramCanInstanceBase = SRAMCAN_BASE;
  uint32_t RAMcounter;
    
/* Standard filter list start address */
  RAM.StandardFilterSA = SramCanInstanceBase + SRAMCAN_FLSSA;
/* Tx FIFO/queue start address */
    RAM.TxFIFOQSA = SramCanInstanceBase + SRAMCAN_TFQSA;
/* Flush the allocated Message RAM area */
  for (RAMcounter = SramCanInstanceBase; RAMcounter < (SramCanInstanceBase + SRAMCAN_SIZE); RAMcounter += 4U)
  {
    *(uint32_t *)(RAMcounter) = 0x00000000U;
  }
    
}

void FDCAN1_Init(void)
{
/*  Enable preipheral & kernal clock for FDCAN1             */
    RCC -> APB1ENR2 |= RCC_APB1ENR2_FDCAN1EN;
    RCC -> CCIPR1 |=  RCC_CCIPR1_FDCANSEL_0;
/*  Enter initialisation mode                                                   */
    FDCAN1 -> CCCR &= ~ FDCAN_CCCR_INIT;
    FDCAN1 -> CCCR |= FDCAN_CCCR_INIT;
    while ((FDCAN1->CCCR & FDCAN_CCCR_INIT) == 0U);                                                 // wait for FDCAN1
    FDCAN1 -> CCCR |= FDCAN_CCCR_CCE;                                                                               // Enable configuration change
/*  Configure FDCAN1                                                                     */
  FDCAN1 -> CCCR &= ~ FDCAN_CCCR_CSR;                                                                           // Stop clock request
    FDCAN_CONFIG->CKDIV |= (0x0 << FDCAN_CKDIV_PDIV_Pos);                                       // Set clock divider to 1
  FDCAN1 -> CCCR &= ~ FDCAN_CCCR_DAR;                                                                           // Enable autoRetransmission
    FDCAN1 -> CCCR |= FDCAN_CCCR_TXP;                                                                               // Enable transmitpause
    FDCAN1 -> CCCR |= FDCAN_CCCR_PXHD;                                                                          // ProtocolException = DISABLE;
    FDCAN1 -> CCCR |= (FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE);                                  // Enable Bit-rate switching & fast data operation
  FDCAN1 -> CCCR |= FDCAN_CCCR_TEST;                                                                            // Enable test mode
    FDCAN1 -> TEST |= FDCAN_TEST_LBCK;                                                                          // LOOPBACK mode
    FDCAN1->NBTP = 0x1E003E0F;                                                                                        // Set Nominal bit timing 
/*  Configure FDCAN1 bit timings (assuming 500kbps)     */
    FDCAN1->DBTP = 0x00000433;                                                                                                                                          
  FDCAN1 -> TXBC &= ~ FDCAN_TXBC_TFQM;                                                                      // TX FIFO operation mode       
    FDCAN1 -> XIDAM |= 0x00000001;                                                                                  // Extended ID mask
/*  Configure Global Filter                                                   */
    FDCAN1 -> RXGFC |= FDCAN_RXGFC_LSS_Msk;                                                                 // List size
    FDCAN1 -> RXGFC |= 0x00000020;
    FDCAN1 -> RXGFC |= 0x00000008;
    FDCAN1 -> RXGFC |= FDCAN_RXGFC_RRFE;
    FDCAN1 -> RXGFC &= ~ FDCAN_RXGFC_RRFS_Pos;
/* Calculate Ram Block Addrresses For FDCAN                     */
  FDCAN_CalcultateRamBlockAddresses();
                        
}


void gpio_pins(void)
{
    /* USER CODE BEGIN MX_GPIO_Init_2 */
    RCC -> AHB2ENR1 |= RCC_AHB2ENR1_GPIODEN;
    //PORT D CONFIGURATION
    GPIOD -> MODER &= ~ (GPIO_MODER_MODE0 | GPIO_MODER_MODE1 | GPIO_MODER_MODE14);
    GPIOD -> MODER |= (GPIO_MODER_MODE1_1 | GPIO_MODER_MODE0_1);                                                                                                                /* < CAN_BUS: PD0-Rx, PD1-Tx > */
    GPIOD->AFR[0] |= 0x00000099;                
}


void SystemCoreClockConfigure(void)
{
/* Set Flash Latency To 4 & Enable Prefetch Buffer              */
    FLASH -> ACR |= FLASH_ACR_LATENCY_4WS;
  while(!(FLASH -> ACR & FLASH_ACR_LATENCY_4WS));
    FLASH -> ACR |= FLASH_ACR_PRFTEN;
/* Turn on VOS                                                          */
  PWR -> VOSR |= PWR_VOSR_VOS;
    while(!(PWR->VOSR & PWR_VOSR_VOSRDY))
    {
        //Wait
    }
/* Turn on MSI Clock                                                */
  RCC -> CR |= RCC_CR_MSISON;
  while(!(RCC -> CR & RCC_CR_MSISRDY));
/* Configure MSI Clock                                          */
  RCC -> ICSCR1 |= RCC_ICSCR1_MSIRGSEL;
  RCC -> ICSCR1 |= RCC_ICSCR1_MSISRANGE_2;
  RCC -> ICSCR2 |= RCC_ICSCR2_MSITRIM0 >> 0x00000005U;
    //RCC -> ICSCR2 |= (16U << (RCC_ICSCR2_MSITRIM0_Pos - RCC_ICSCR2_MSITRIM0));
  
/* Configure PLL as System clock                    */
    RCC -> PLL1CFGR |= RCC_PLL1CFGR_PLL1SRC_0;
    RCC -> PLL1CFGR |= RCC_PLL1CFGR_PLL1M;
    LL_RCC_PLL1_ConfigDomain_SYS(RCC_PLL1CFGR_PLL1SRC_0, 1, 80, 2);
    RCC -> PLL1CFGR |= RCC_PLL1CFGR_PLL1REN;
    RCC -> PLL1CFGR |= RCC_PLL1CFGR_PLL1QEN;
    
/* Turn on PLL                                          */
  RCC -> CR |= RCC_CR_PLL1ON;
/* Wait till PLL is ready                   */
  while(!(RCC -> CR & RCC_CR_PLL1RDY));

   /*AHB prescaler = 3 ---- Clock = 50MHz/2  */
  RCC -> CFGR2 |= RCC_CFGR2_HPRE_3;
  RCC -> CFGR1 |= (RCC_CFGR1_SW_1 | RCC_CFGR1_SW_0);            // Select source clock as PLL1

/* Wait till System clock is ready */
  while(!(RCC-> CFGR1 & RCC_CFGR1_SWS));

/* Ensure 1us transition state at intermediate medium speed clock                   */
  for (__IO uint32_t i = (160 >> 1); i !=0; i--);

/* Configure APB prescalers                                                                                             */                              
    RCC -> CFGR2 &= ~ RCC_CFGR2_HPRE;               
  RCC -> CFGR2 &= ~ RCC_CFGR2_PPRE1;
    RCC -> CFGR2 &= ~ RCC_CFGR2_PPRE2;
    RCC -> CFGR3 &= ~ RCC_CFGR3_PPRE3;
    
}

__STATIC_INLINE void LL_RCC_PLL1_ConfigDomain_SYS(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR)
{
  MODIFY_REG(RCC->PLL1CFGR, RCC_PLL1CFGR_PLL1SRC | RCC_PLL1CFGR_PLL1M, Source | \
             ((PLLM - 1UL) << RCC_PLL1CFGR_PLL1M_Pos));
  MODIFY_REG(RCC->PLL1DIVR, RCC_PLL1DIVR_PLL1N | RCC_PLL1DIVR_PLL1R, ((PLLN - 1UL) << \
                                                                      RCC_PLL1DIVR_PLL1N_Pos) | ((PLLR - 1UL) << \
                                                                           RCC_PLL1DIVR_PLL1R_Pos));
}

0
投票

感谢您的代码。我可以从随附的代码中知道“SRAMCAN_BASE”的值吗

© www.soinside.com 2019 - 2024. All rights reserved.