4344 views|2 replies

205

Posts

0

Resources
The OP
 

[FM33LG0 Series Development Board Review] 06.CAN [Copy link]

 

1. Introduction
FM33LG048 has one CNA (Controller Area Network) interface, supports CAN 2.0A and CAN 2.0B standards, supports 11-bit standard ID and 29-bit extended ID; the maximum transmission rate can reach 1Mbps, and it has 2 transmit FIFOs, 2 receive FIFOs and 4 receive filters; in the case of bus error or transmission arbitration failure, it also supports automatic retransmission function.

The CAN interface of FM33LG048 is connected through pin headers on the FM33LG0xx DEMO V1.1 development board, namely PD10 (CAN_RX) and PE9 (CAN_TX), corresponding to the J17 interface on the development board;

There are many options for the CAN clock source of FM33LG048: RCHF, XTHF, PLL, APBCLK; the selection of which clock source can be configured by software; in order to improve the accuracy of the communication rate, the clock frequency used needs to meet the tolerance range specified in ISO11898-1. In this example, the XTHF external crystal oscillator is used as the CAN clock source, so when initializing the CAN configuration parameters, you need to configure XTHF to enable it first .

2. Software function
Use XTHF external crystal oscillator as the clock source of CAN, configure the communication rate of CAN to 100kbps, send a test data to the CAN bus every 500ms in the program; turn on CAN receive interrupt, and print out the data information received by CAN through the serial port when new data is received;

3. Implementation code

/*******************************************************************************
 * @file    CAN.c
 * @author  King
 * [url=home.php?mod=space&uid=252314]@version[/url] V1.00
 * [url=home.php?mod=space&uid=311857]@date[/url] 27-Nov-2021
 * [url=home.php?mod=space&uid=159083]@brief[/url] ......
*******************************************************************************/


/* Define to prevent recursive inclusion -------------------------------------*/
#define __CAN_C__


/* Includes ------------------------------------------------------------------*/
#include "CAN.h"


#if CAN_ENABLE


/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * [url=home.php?mod=space&uid=1020061]@attention[/url] *******************************************************************************/
void CAN_Configure(void)
{
    FL_GPIO_InitTypeDef      GPIO_InitStruct;
    FL_CAN_InitTypeDef       CAN_InitStruct;
    FL_CAN_FilterInitTypeDef CAN_FilterInitStruct;

    //---Enable XTHF For CAN Clock Source
    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_2 | FL_GPIO_PIN_3;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    FL_CMU_XTHF_Enable();
    FL_CMU_XTHF_WriteDriverStrength(0x1F);
    FL_DelayMs(3);


    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_9;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull       = FL_ENABLE;
    FL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_10;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull       = FL_ENABLE;
    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* CAN Baudrate = CAN_CLK / (BRP + 1) / (TS1 + TS2 + 1) */
    FL_CAN_StructInit(&CAN_InitStruct);
    CAN_InitStruct.mode        = FL_CAN_MODE_NORMAL;
    CAN_InitStruct.BRP         = 7;
    CAN_InitStruct.clockSource = FL_CMU_CAN_CLK_SOURCE_XTHF;
    CAN_InitStruct.SJW         = FL_CAN_SJW_1Tq;
    CAN_InitStruct.TS1         = FL_CAN_TS1_5Tq;
    CAN_InitStruct.TS2         = FL_CAN_TS2_4Tq;
    FL_CAN_Init(CAN, &CAN_InitStruct);

    FL_CAN_StructFilterInit(&CAN_FilterInitStruct);
    CAN_FilterInitStruct.filterIdStandard = 0x6AD;
    CAN_FilterInitStruct.filterIdSRR      = 0;
    CAN_FilterInitStruct.filterIdIDE      = 0;
    CAN_FilterInitStruct.filterIdRTR      = 0;

    CAN_FilterInitStruct.filterMaskIdHigh = 0x7FF;
    CAN_FilterInitStruct.filterMaskIdSRR  = 0x01;
    CAN_FilterInitStruct.filterMaskIdIDE  = 0x01;
    CAN_FilterInitStruct.filterMaskIdRTR  = 0x01;
    CAN_FilterInitStruct.filterEn         = FL_ENABLE;
    FL_CAN_FilterInit(CAN, &CAN_FilterInitStruct, FL_CAN_FILTER1);

    FL_CAN_ClearFlag_CRXOK(CAN);
    FL_CAN_EnableIT_RXOK(CAN);

    NVIC_DisableIRQ(CAN_IRQn);
    NVIC_SetPriority(CAN_IRQn, 2);
    NVIC_EnableIRQ(CAN_IRQn);

    TASK_Append(TASK_ID_CAN, CAN_Handler, 500);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void FL_CAN_FIFO_Write(uint32_t ID, uint32_t Length, uint32_t Data1, uint32_t Data2)
{
    uint32_t Timeout = 5;

    while((FL_CAN_IsActiveFlag_TXBuffFull(CAN) != FL_RESET) & Timeout)
    {
        Timeout--;
        FL_DelayMs(1);
    }

    FL_CAN_WriteTXMessageID(CAN, ID);
    FL_CAN_WriteTXMessageLength(CAN, Length);
    FL_CAN_WriteTXMessageWord1(CAN, Data1);
    FL_CAN_WriteTXMessageWord2(CAN, Data2);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void FL_CAN_HPBUF_Write(uint32_t ID, uint32_t Length, uint32_t Data1, uint32_t Data2)
{
    uint32_t Timeout = 5;

    while((FL_CAN_IsActiveFlag_TXHighPriorBuffFull(CAN) != FL_RESET) & Timeout)
    {
        Timeout--;
        FL_DelayMs(1);
    }

    FL_CAN_WriteHighPriorTXMessageID(CAN, ID);
    FL_CAN_WriteHighPriorMessageLength(CAN, Length);
    FL_CAN_WriteHighPriorMessageWord1(CAN, Data1);
    FL_CAN_WriteHighPriorMessageWord2(CAN, Data2);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void FL_CAN_Receive(void)
{
    uint32_t Data1 = 0;
    uint32_t Data2 = 0;

    CAN_MSG_TypeDef RxMessage;

    RxMessage.StdId = FL_CAN_ReadRXMessageID(CAN);
    RxMessage.DLC   = FL_CAN_ReadRXMessageLength(CAN);

    Data1 = FL_CAN_ReadRXMessageWord1(CAN);
    Data2 = FL_CAN_ReadRXMessageWord2(CAN);

    RxMessage.Data[0] = (uint8_t)(Data1 >> 0x00) & 0xFF;
    RxMessage.Data[1] = (uint8_t)(Data1 >> 0x08) & 0xFF;
    RxMessage.Data[2] = (uint8_t)(Data1 >> 0x10) & 0xFF;
    RxMessage.Data[3] = (uint8_t)(Data1 >> 0x18) & 0xFF;
    RxMessage.Data[4] = (uint8_t)(Data2 >> 0x00) & 0xFF;
    RxMessage.Data[5] = (uint8_t)(Data2 >> 0x08) & 0xFF;
    RxMessage.Data[6] = (uint8_t)(Data2 >> 0x10) & 0xFF;
    RxMessage.Data[7] = (uint8_t)(Data2 >> 0x18) & 0xFF;

    printf("\r\nCAN Receive : 0x%x, %d, ", RxMessage.StdId, RxMessage.DLC);

    for(uint32_t i = 0; i < 8; i++)
    {
        printf("%02x ", RxMessage.Data[i]);

    }

    printf("\r\n");
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void FL_CAN_Transmit(uint32_t FrameFormat, CAN_MSG_TypeDef *TxMessage)
{
    uint32_t ID     = 0;
    uint32_t Length = 0;
    uint32_t Data1 = 0;
    uint32_t Data2 = 0;

    if(FrameFormat == FL_CAN_FORMAT_STANDARD_DATA)
    {
        ID = TxMessage->StdId & 0x7FF;
    }

    else if(FrameFormat == FL_CAN_FORMAT_STANDARD_REMOTE)
    {
        ID = (TxMessage->StdId & 0x7FF) | (1 << 11);
    }

    else if(FrameFormat == FL_CAN_FORMAT_EXTEND_DATA)
    {
        ID = ((TxMessage->ExtId & 0x3FFFF) << 13) |
             ((uint32_t)1 << 12)                  |
             ((uint32_t)1 << 11)                  |
             ((TxMessage->ExtId & 0x1FFC0000) >> 18);
    }

    else if(FrameFormat == FL_CAN_FORMAT_EXTEND_REMOTE)
    {
        ID = ((TxMessage->ExtId & 0x3FFFF) << 13) |
             ((uint32_t)1 << 12)                  |
             ((uint32_t)1 << 31)                  |
             ((TxMessage->ExtId & 0x1FFC0000) >> 18);
    }


    Length = TxMessage->DLC;

    Data1 = ((uint32_t)TxMessage->Data[3] << 0x18) |
            ((uint32_t)TxMessage->Data[2] << 0x10) |
            ((uint32_t)TxMessage->Data[1] << 0x08) |
            ((uint32_t)TxMessage->Data[0] << 0x00);

    Data2 = ((uint32_t)TxMessage->Data[7] << 0x18) |
            ((uint32_t)TxMessage->Data[6] << 0x10) |
            ((uint32_t)TxMessage->Data[5] << 0x08) |
            ((uint32_t)TxMessage->Data[4] << 0x00);

#if 1
    FL_CAN_FIFO_Write(ID, Length, Data1, Data2);
#else
    FL_CAN_HPBUF_Write(ID, Length, Data1, Data2);
#endif
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void CAN_Handler(void)
{
    CAN_MSG_TypeDef TxMessage;

    TxMessage.StdId = 0x6AD;
    TxMessage.DLC   = 8;

    for(uint8_t i = 0; i < TxMessage.DLC; i++)
    {
        TxMessage.Data[i] = i;
    }

    FL_CAN_Transmit(FL_CAN_FORMAT_STANDARD_DATA, &TxMessage);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void CAN_IRQHandler(void)
{
    if((FL_ENABLE == FL_CAN_IsEnabledIT_RXOK(CAN)) &&
       (FL_SET    == FL_CAN_IsActiveFlag_RXOK(CAN)))
    {
        FL_CAN_Receive();
        FL_CAN_ClearFlag_CRXOK(CAN);
    }
}


#endif


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

4. Debugging and running

Since the development board itself does not have a CAN transceiver, we need to connect an external CAN transceiver module when conducting CAN experiments. The VP230 chip used in this experiment supports the same 3.3V operating voltage as the MCU. In addition, a CAN debugging tool is connected to cooperate with the PC software to view the data transmitted on the CAN bus, or send test data to the CAN bus.

4.1. Hardware Connection

Monitoring data

4.3. Receiving Data

5. Project source code

Project_CAN.zip (382.16 KB, downloads: 31)

This post is from Domestic Chip Exchange

Latest reply

Hi, I see that the frequency printed in your log is the theoretical frequency after PLL multiplication? Does it exceed the maximum main frequency limit of this chip?  Details Published on 2023-4-21 15:50
Personal signatureWe are a team and we work as a team !
 
 

2

Posts

0

Resources
2
 
Hi, I see that the frequency printed in your log is the theoretical frequency after PLL multiplication? Does it exceed the maximum main frequency limit of this chip?
This post is from Domestic Chip Exchange

Comments

8000000Hz = 8MHz, is there a higher frequency?  Details Published on 2023-4-23 15:37
 
 
 

205

Posts

0

Resources
3
 
fiee posted on 2023-4-21 15:50 Hi, what is printed on your log is the theoretical frequency after PLL multiplication? Is it exceeding the maximum main frequency limit of this chip?

8000000Hz = 8MHz, is there a higher frequency?

This post is from Domestic Chip Exchange
Personal signatureWe are a team and we work as a team !
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list