串口搞得差不多了,接下来研究下这个芯片的FDCAN
54616的FDCAN模块
首先这个芯片是支持FDCAN和普通的CAN的。
然后去隔壁的ST看看H743【同样支持FDCAN】的芯片看一看
是不是有些类似呢,其实你仔细看手册,对比NXP和ST对FDCAN这个IP的实现和其手册的描述,你会发现很有意思的事情
基本上都是差不多的,甚至有些描述基本就是一样的,寄存器也是
除了有些细微的不同之外,大部分功能基本上都是一致的【ST的CAN1有TTCAN的功能,NXP这个就没有,都是FDCAN】
估计都是按照某个标准做的吧,可能要实现一个FDCAN的IP核都得这样子实现吧^_^
这么弄的话倒是很友好了,ST的手册是有中文版的,NXP就没得了,可以互相对照着看一看,很有参考的价值
54616的CAN功能代码实现
这里我们先以基础的普通CAN功能来举例子,估计这个FDCAN的功能应该也是类似的
这里第一次探索性的实验,我们采用SDK配置工具生成代码的方式,这个比较方便
以后熟悉了可以研究研究寄存器如何实现
打开MCUexpress,打开配置工具
按图配置时钟树
打开CAN0的时钟,配置为90MHz
到引脚这边,配置CAN的GPIO
然后到外设部分配置CAN的底层驱动
我这里按500Kbps配置,注意我们现在弄正常的CAN,FDCAN的选项去掉
这里会有一个警告,但是我现在也不知道到底是什么意思,反正生成的代码可以用
注意CAN总线的时序参数一定要设置对,500Kbps就尽可能的设置到500Kbps
不然CAN盒子是接收不到的
它有辅助你设置时序的计算器在上方,很方便的
接下来是消息缓冲区的分配
关于这个可以看看我之前写的H743 FDCAN的过滤表设置
因为这两个芯片的FDCAN是很类似的
唯一有点不同的是,这款芯片的缓冲区是需要用程序的SRAM作为分配来源的,不像H743是专有SRAM
这里我使用RX FIFO0,分配了20个,标准帧过滤表1个
发送FIFO分配了20个
过滤器我们试一试,标准帧范围过滤,范围内的进来
这个工具真的是太方便了
最后打开RX FIFO0中断
然后生成代码,接下来就是发送和接收实现了.
CAN的发送和接收功能实现
发送的步骤,简单说就3步
- 填发送数据结构体
- 发送数据结构体写入芯片内部的发送缓冲区
- 请求芯片发送
接收的步骤
- 打开指定的接收缓冲新数据到来中断
- 中断函数里面判断中断标志,中断标志出现以后,执行对应的数据接收到接收数据结构体的函数
- 清除对应的中断标志
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "LPC54616.h"
#include "fsl_common.h"
/* TODO: insert other include files here. */
/* TODO: insert other definitions and declarations here. */
volatile bool txComplete = false;
volatile bool rxComplete = false;
mcan_tx_buffer_frame_t txFrame;
mcan_rx_buffer_frame_t rxFrame;
uint8_t tx_data[8];
uint8_t rx_data[8];
mcan_buffer_transfer_t txXfer;
/* CAN0中断 */
void CAN0_INT_0_IRQHANDLER(void) {
if ((CAN0->IR & (1 << 0)) != 0) {
//新消息到来
CAN0->IR |= 1 << 0;
//清除中断标志
//取出数据
MCAN_ReadRxFifo(CAN0, 0, &rxFrame);
//接收标记
rxComplete = true;
}
/* Place your code here */
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
Store immediate overlapping exception return operation might vector to incorrect interrupt. */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
/*
* @brief Application entry point.
*/
void Delay_xMs(uint32_t i) {
uint16_t cnt = 22727;
while (i--) {
cnt = 22727;
while (cnt--) {
__asm volatile ("nop");
}
}
}
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
printf("Hello World\n");
/* Force the counter to be placed into memory. */
volatile static int i = 0;
/* Config TX frame data. */
memset(tx_data, 0, sizeof(uint8_t) * 8);
uint8_t cnt = 0;
for (cnt = 0; cnt < 8; cnt++) {
tx_data[cnt] = cnt;
}
//配置发送帧的ID和长度
txFrame.xtd = kMCAN_FrameIDStandard;
txFrame.rtr = kMCAN_FrameTypeData;
txFrame.fdf = 0;
txFrame.brs = 0;
txFrame.dlc = 8U;
txFrame.id = 1 << 18;//标准帧需要左移18位
txFrame.data = tx_data;
txFrame.size = 8;
txXfer.frame = &txFrame;
txXfer.bufferIdx = 0;
/* Create MCAN handle structure and set call back function. */
/* Enter an infinite loop, just incrementing a counter. */
while (1) {
Delay_xMs(100);//延时100ms
MCAN_WriteTxBuffer(CAN0, 0, &txFrame);//发送数据结构体写到内部缓冲
MCAN_TransmitAddRequest(CAN0, 0);//请求发送
/*处理接收 */
if (rxComplete) {
rxComplete = false;
uint8_t j = 0;
printf("RX ID: 0x%x\r\n", (rxFrame.id >>18));
for (j = 0; j < rxFrame.dlc; j++) {
rx_data[j] = rxFrame.data[j];
printf("0x%x\t", rxFrame.data[j]);
}
printf("\r\n");
}
memset(rx_data, 0, 8);
}
return 0;
}
以后用到FDCAN的功能时再来补充FDCAN
来试一试FDCAN吧
目前只把发送调出来了,接收还不行
我买的USB转FDCAN发送的数据,不仅我的板子收不到,我的逻辑分析仪也抓不到,不知道为啥
但是它收得到我发的
目前只弄出来速率不会变化的FDCAN【也就是数据域和仲裁域速率一致的FDCAN功能】
变速率的我还没有调出来,USB转FDCAN好像识别不出来,不知道为什么
FDCAN配置
我把SDK里面的配置截图,截取下来
我自己觉得是不是我的速率和位时序那里填的不对呢
虽然我配的是仲裁域500K,数据域1M
把变速率FDCAN打开
我接收器那边也确实按这个配了,但是依然有问题
但是我调成下图的不变速率,我的FDCAN接收器和逻辑分析仪那边就可以正常收到了
看看以后能不能有新发现
FDCAN发送代码
和之前差不多
我就贴不一样的部分
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
printf("Hello World\n");
/* Force the counter to be placed into memory. */
volatile static int i = 0;
/* Config TX frame data. */
memset(tx_data, 0, sizeof(uint8_t) * 8);
uint8_t cnt = 0;
for (cnt = 0; cnt < 64; cnt++) {
tx_data[cnt] = cnt;//数据按1-64这样
}
txFrame.xtd = kMCAN_FrameIDStandard;
txFrame.rtr = kMCAN_FrameTypeData;
txFrame.fdf = 1;//FDCAN数据
txFrame.brs = 0;//变速率关闭,打开我的USB转FDCAN收不到,不知道是不是那边配置有问题
txFrame.dlc = 15;
txFrame.id = 1 << 18;
txFrame.data = tx_data;
txFrame.size = 64;//64字节
txXfer.frame = &txFrame;
txXfer.bufferIdx = 0;
/* Create MCAN handle structure and set call back function. */
/* Enter an infinite loop, just incrementing a counter. */
while (1) {
Delay_xMs(500);
MCAN_WriteTxBuffer(CAN0, 0, &txFrame);
MCAN_TransmitAddRequest(CAN0, 0);
/* Wait until message received. */
if (rxComplete) {
rxComplete = false;
uint8_t j = 0;
printf("RX ID: 0x%x\r\n", (rxFrame.id >>18));
for (j = 0; j < rxFrame.dlc; j++) {
rx_data[j] = rxFrame.data[j];
printf("0x%x\t", rxFrame.data[j]);
}
printf("\r\n");
}
memset(rx_data, 0, 64);
i++;
/* 'Dummy' NOP to allow source level single stepping of
tight while() loop */
__asm volatile ("nop");
}
return 0;
}
我买的USB转FDCAN的上位机截图
这个速率不变的FDCAN是能够收到的
逻辑分析仪的部分截图
完整的一包截图【好像有一个Warning】
CRC分隔符必须是隐性位
会不会还是那个位时序取得不合理导致的呢?暂时就不知道了
以后再看看能不能分析出问题在哪里