【FM33LG0系列开发板测评】06.CAN
<p>1、简介<br />FM33LG048带有一路CNA(控制器区域网络)接口,支持CAN 2.0A和CAN 2.0B标准,支持11位的标准ID和29位的扩展ID;最高传输速率可以达到1Mbps,同时具有2个发送FIFO、2个接收FIFO和4个接收滤波器;在总线错误或者传输仲裁失败的情况下,还支持自动重发的功能。</p>
<p>FM33LG0xx DEMO V1.1开发板上将FM33LG048的CAN接口通过排针的形式接出来了,分别是PD10(CAN_RX)、PE9(CAN_TX),对应开发板上的J17这个接口;</p>
<p>FM33LG048的CAN时钟源有多种选择:RCHF、XTHF、PLL、APBCLK;选择哪一个时钟源是可以通过软件来配置的;为了提高通讯速率的精准度,使用的时钟频率需要满足ISO11898-1规定的容差范围,<strong><span style="color:#e74c3c;">本例程中使用了XTHF外部晶振作为CAN的时钟源,所以在初始化CAN配置参数的时候,需要先配置XTHF使能</span></strong>。</p>
<p> </p>
<p>2、软件功能<br />
使用XTHF外部晶振作为CAN的时钟源,将CAN的通讯速率配置为100kbps,程序中每间隔500ms向CAN总线上发送一条测试数据;开启CAN接收中断,在有接收到新数据时,通过串口打印出CAN收到的数据信息;</p>
<p> </p>
<p>3、实现代码</p>
<pre>
<code class="language-cpp">/*******************************************************************************
* @file CAN.c
* @authorKing
* @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 = (uint8_t)(Data1 >> 0x00) & 0xFF;
RxMessage.Data = (uint8_t)(Data1 >> 0x08) & 0xFF;
RxMessage.Data = (uint8_t)(Data1 >> 0x10) & 0xFF;
RxMessage.Data = (uint8_t)(Data1 >> 0x18) & 0xFF;
RxMessage.Data = (uint8_t)(Data2 >> 0x00) & 0xFF;
RxMessage.Data = (uint8_t)(Data2 >> 0x08) & 0xFF;
RxMessage.Data = (uint8_t)(Data2 >> 0x10) & 0xFF;
RxMessage.Data = (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 << 0x18) |
((uint32_t)TxMessage->Data << 0x10) |
((uint32_t)TxMessage->Data << 0x08) |
((uint32_t)TxMessage->Data << 0x00);
Data2 = ((uint32_t)TxMessage->Data << 0x18) |
((uint32_t)TxMessage->Data << 0x10) |
((uint32_t)TxMessage->Data << 0x08) |
((uint32_t)TxMessage->Data << 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***/
</code></pre>
<p> </p>
<p>4、调试运行</p>
<p>由于开发板本身没有带有CAN收发器,所以我们在进行CAN实验的时候,需要外接一个CAN收发模块;本实验选用的VP230这个芯片,支持与MCU相同的3.3V工作电压;另外再连接一个CAN调试工具,与PC端的软件进行配合,查看CAN总线上传输的数据、或者是向CAN总线上发送测试数据等操作。</p>
<p>4.1.硬件连线</p>
<p></p>
<p> </p>
<p>4.2.监测数据</p>
<p></p>
<p> </p>
<p>4.3.接收数据</p>
<p></p>
<p> </p>
<p>5、工程源码</p>
<p></p>
<p> </p>
大佬你好,看你log上打印的是理论上PLL倍频完的频率?是超过这个芯片的最大主频限制了吗? fiee 发表于 2023-4-21 15:50
大佬你好,看你log上打印的是理论上PLL倍频完的频率?是超过这个芯片的最大主频限制了吗?
<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/puzzle.gif" width="53" /></p>
<p> </p>
<p>8000000Hz = 8MHz,有超过吗?</p>
页:
[1]