CAN总线是工业、汽车上应用较多,本次介绍如何在MPLAB X环境下进行SAME51 CAN驱动。
SAME51有两路CAN-FD模块:
符合CAN协议2.0版A、B部分和ISO 11898-1:2015
•最多两个控制器区域网络CAN
-支持CAN2.0 A/B和CAN-FD (ISO 11898-1:2015)
•支持最多64个数据字节的CAN FD
•CAN错误日志
•AUTOSAR优化
•SAE J1939优化
•两个可配置的接收fifo
•在接收高优先级消息时分离信令
•多达64个专用接收缓冲区和多达32个专用发送缓冲区
•可配置发送FIFO,发送队列,发送事件FIFO
•直接消息RAM访问CPU
•可编程环回测试模式
•屏蔽模块中断
•断电支持;在CAN支持上调试
•传输速率:
- 1mb /s的CAN 2.0模式
- CAN-FD模式10mb /s
其引脚分配如下所示:
本次使用的是CAN0 (PA22, PA23)。在MCC里面配置CAN0:
CAN参数配置:
生成CAN0模块初始化代码:
void CAN0_Initialize(void) { /* Start CAN initialization */ CAN0_REGS->CAN_CCCR = CAN_CCCR_INIT_Msk; while ((CAN0_REGS->CAN_CCCR & CAN_CCCR_INIT_Msk) != CAN_CCCR_INIT_Msk) { /* Wait for initialization complete */ } /* Set CCE to unlock the configuration registers */ CAN0_REGS->CAN_CCCR |= CAN_CCCR_CCE_Msk; /* Set Nominal Bit timing and Prescaler Register */ CAN0_REGS->CAN_NBTP = CAN_NBTP_NTSEG2(3UL) | CAN_NBTP_NTSEG1(10UL) | CAN_NBTP_NBRP(0UL) | CAN_NBTP_NSJW(3UL); /* Global Filter Configuration Register */ CAN0_REGS->CAN_GFC = CAN_GFC_ANFS_RXF0 | CAN_GFC_ANFE_REJECT; /* Set the operation mode */ CAN0_REGS->CAN_CCCR &= ~CAN_CCCR_INIT_Msk; while ((CAN0_REGS->CAN_CCCR & CAN_CCCR_INIT_Msk) == CAN_CCCR_INIT_Msk) { /* Wait for initialization complete */ } (void) memset(&can0Obj.msgRAMConfig, 0x00, sizeof(CAN_MSG_RAM_CONFIG)); }
配置发送Fifo:
printf(" ------------------------------ \r\n"); printf(" CAN Demo \r\n"); printf(" ------------------------------ \r\n"); /* Set Message RAM Configuration */ CAN0_MessageRAMConfigSet(Can0MessageRAM); /* Prepare the message to send*/ uint8_t txFiFo[CAN0_TX_FIFO_BUFFER_SIZE]; CAN_TX_BUFFER *txBuffer = (CAN_TX_BUFFER *) txFiFo; memset(txFiFo, 0x00, CAN0_TX_FIFO_BUFFER_ELEMENT_SIZE); txBuffer->id = 0x168; txBuffer->dlc = 8; txBuffer->xtd = 1; txBuffer->fdf = 1; txBuffer->brs = 1; for (uint8_t count = 8; count >= 1; count--) { txBuffer->data[count - 1] = 51; }
在循环中进行CAN报文发送:
while (true) { /* Maintain state machines of all polled MPLAB Harmony modules. */ SYS_Tasks(); printf(" Transmitting Message:"); txBuffer->data[1] = Index; txBuffer->data[0] = Tune; if (CAN0_InterruptGet(CAN_INTERRUPT_TC_MASK)) { CAN0_InterruptClear(CAN_INTERRUPT_TC_MASK); } //if (CAN0_MessageTransmit(messageID, messageLength, message, CAN_MODE_NORMAL, CAN_MSG_ATTR_TX_FIFO_DATA_FRAME) == true) { if (CAN0_MessageTransmitFifo(1, txBuffer) == true) { printf("CAN Send Success. Speed =%lu, Bright=%d \r\n", currentIndex, TuneLED); } else { printf("CAN Send Failed \r\n"); } }//end of while
还有一点需要注意,新版本的CAN API接口发生了变化。可参考: https://microchip.my.site.com/s/article/Harmony-3-bootloader-V3-5-0-does-not-compile-with-the-Can-driver-generated-by-CSP-V3-10-0
In CSP V3.10.0 the transmit interface for the can driver was changed from:
bool CAN0_MessageTransmit(uint32_t id, uint8_t length, uint8_t* data, CAN_MODE mode, CAN_MSG_TX_ATTRIBUTE msgAttr);
to
bool CAN0_MessageTransmitFifo(uint8_t numberOfMessage, CAN_TX_BUFFER *txBuffer);
编译烧录,遇到错误:
在网上查找了资料,找到了原来ATMEL公司的一个KBA:
ATSAM device - RDDI_DAP_OPERATION_FAILED Error https://microchip.my.site.com/s/article/ATSAM-device---RDDI-DAP-OPERATION-FAILED-Error
【临时方案】后来尝试把连接到开发板的TJA1050 GND引脚暂时与开发板断开,竟然可以成功烧录了。烧录成功后,再连接TJA1050与开发板。
打开串口:
USB CAN工具:
改变发送数据,CAN调试工具成功接收到更新后的数据。
参考:
CANx_MessageTransmitFifo Function https://onlinedocs.microchip.com/oxy/GUID-450989FA-38E4-4D68-AB61-15ADB29AD718-en-US-6/GUID-4BBEDABD-6866-446F-BE57-7C5117D86F44.html
Harmony 3 bootloader V3.5.0 does not compile with the Can driver generated by CSP V3.10.0 https://microchip.my.site.com/s/article/Harmony-3-bootloader-V3-5-0-does-not-compile-with-the-Can-driver-generated-by-CSP-V3-10-0