826|0

151

帖子

0

资源

一粒金砂(高级)

【FM33LG0系列开发板测评】06.CAN [复制链接]

1、简介
FM33LG048带有一路CNA(控制器区域网络)接口,支持CAN 2.0A和CAN 2.0B标准,支持11位的标准ID和29位的扩展ID;最高传输速率可以达到1Mbps,同时具有2个发送FIFO、2个接收FIFO和4个接收滤波器;在总线错误或者传输仲裁失败的情况下,还支持自动重发的功能。

FM33LG0xx DEMO V1.1开发板上将FM33LG048的CAN接口通过排针的形式接出来了,分别是PD10(CAN_RX)、PE9(CAN_TX),对应开发板上的J17这个接口;

FM33LG048的CAN时钟源有多种选择:RCHF、XTHF、PLL、APBCLK;选择哪一个时钟源是可以通过软件来配置的;为了提高通讯速率的精准度,使用的时钟频率需要满足ISO11898-1规定的容差范围,本例程中使用了XTHF外部晶振作为CAN的时钟源,所以在初始化CAN配置参数的时候,需要先配置XTHF使能

 

2、软件功能
使用XTHF外部晶振作为CAN的时钟源,将CAN的通讯速率配置为100kbps,程序中每间隔500ms向CAN总线上发送一条测试数据;开启CAN接收中断,在有接收到新数据时,通过串口打印出CAN收到的数据信息;

 

3、实现代码

/*******************************************************************************
 * @file    CAN.c
 * @author  King
 * @version V1.00
 * @date 27-Nov-2021
 * @brief ......
*******************************************************************************/


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

    }

    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;
    }

    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、调试运行

由于开发板本身没有带有CAN收发器,所以我们在进行CAN实验的时候,需要外接一个CAN收发模块;本实验选用的VP230这个芯片,支持与MCU相同的3.3V工作电压;另外再连接一个CAN调试工具,与PC端的软件进行配合,查看CAN总线上传输的数据、或者是向CAN总线上发送测试数据等操作。

4.1.硬件连线

3.jpg

 

4.2.监测数据

1.png

 

4.3.接收数据

2.png

 

5、工程源码

Project_CAN.zip (382.16 KB, 下载次数: 3)

个人签名We are a team and we work as a team !

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

最新文章 更多>>
    推荐帖子
    stm32的mcu,外部主晶振一般选高频的还是低频的?有什么技术原理吗?

    RT! 比如stm32L486xx, 4Mhz, 8Mhz, 16Mhz的外部主晶振,哪个最合适?什么技术原理?

    【树莓派4B测评】树莓派4连接USB摄像头实现网络视频监控

    树莓派4本身具有USB接口,还具有千兆网口,CPU的速度也很快,正好可以使用树莓派连接一个USB的摄像头作为网络视频监控,可以查看 ...

    自己画的一个简易的斩波电路

    529001 ,请大家指导一下,有什么需要注意的问题或者啥啥啥的

    Windows 10 和 Windows 11 有什么区别?

    Windows 10 和 Windows 11 有什么区别? Windows 11 具有 Windows 10 的全部功能和安全性,同时具有经重新设计而焕然一新 ...

    清华虚拟学生弹唱是真人AI换脸?研发团队再回应!

    10月19日,有关“清华虚拟学生被质疑真人AI换脸”的话题在网上引发关注。 有网友质疑,此前曾受到关 ...

    找不到目标单片机,请高手指点,谢谢

    574491574490 电路图如前两幅图所示,点“检查MCU选项”或“下载/编程”后,一直显示“正在检查目 ...

    关闭
    站长推荐上一条 1/9 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表