TMS320F28379D笔记4:CAN通信的收发配置

发布时间:2026/6/6 20:57:05

TMS320F28379D笔记4:CAN通信的收发配置 今日配置下CAN通信顺带理解下CAN 的一些基础知识目录CAN基础知识CAN控制器CAN收发器CAN总线上的0和1CAN通信示波器信号直观感受CAN盒与MCU的连接Ti 例程代码注意点代码贴出#include my_can.h主函数测试效果CAN BUSOFFCAN基础知识CAN控制器CAN控制器内部结构还是挺复杂的一般现在CAN控制器都是与处理器集成在一起。其实对于编程的人来说无非也就是包含一些控制、状态、配置等寄存器。比如我们看到有些STM32芯片带有CAN也就是说CAN控制器已经集成在STM32芯片中了我们只需要编程操作其中的寄存器即可。F28379D里面有CAN芯片CAN收发器将CAN收发引脚CAN_TX和CAN_RX的TTL信号转换成CAN总线的电平信号。CAN总线上的0和1CAN总线为「两线」「差分」信号用隐形代表逻辑1显性代表逻辑0。CAN通信示波器信号直观感受CAN的波形差不多是这样的这里由于Ti例程的时钟影响说不清是什么波特率的CAN但波形是正确的只是频率未知加了逻辑分析的效果如下CAN盒与MCU的连接CAN盒子CAN-H 接 CAN-HCAN-L 接 CAN-LGND 接 GND设置普通CAN通信波特率正常通信 就能看到 如图所示右下角会有接收成功与错误计数一般都是波特率不匹配总线电平不对会错误帧Ti 例程代码注意点Ti的CAN例程时钟频率不是很对这会导致没法通信成功主要是device.h这俩块需要注意对比清楚必要时示波器分析我的程序在使用时发现需要将他的频率计算/2才正常代码贴出#include my_can.h#ifndef _MY_CAN_H_ #define _MY_CAN_H_ #include driverlib.h #include device.h #include board.h #include c2000ware_libraries.h #define GPIO_CFG_CANRXB GPIO_17_CANRXB // pinConfig for CANB RX #define GPIO_CFG_CANTXB GPIO_12_CANTXB // pinConfig for CANB TX #define MSG_DATA_LENGTH 8 #define MSG_DATARX_LENGTH 0 #define TX_MSG_OBJ_ID 1 // 发送邮箱 #define RX_MSG_OBJ_ID 2 // 接收邮箱 #define CAN_ID 0x1 // 收发ID都是 0x1 extern uint16_t txMsgData[8]; extern uint16_t txMsgData2[8]; extern uint16_t rxMsgData[8]; void MY_can_bsp_init(); __interrupt void canB_ISR(void);// 接收中断函数 #endif#include my_can.h uint16_t txMsgData[8]; uint16_t txMsgData2[8]; uint16_t rxMsgData[8]; uint16_t rxMsgCount 0; void MY_can_bsp_init() { txMsgData[0] 0x55;txMsgData[1] 0xff;txMsgData[2] 0x55;txMsgData[3] 0xff; txMsgData[4] 0x55;txMsgData[5] 0xff;txMsgData[6] 0x55;txMsgData[7] 0xff; txMsgData2[0] 0x12;txMsgData2[1] 0x34;txMsgData2[2] 0x56;txMsgData2[3] 0x78; txMsgData2[4] 0x21;txMsgData2[5] 0x43;txMsgData2[6] 0x65;txMsgData2[7] 0x87; GPIO_setPinConfig(GPIO_CFG_CANRXB); // CANB RX GPIO_setPinConfig(GPIO_CFG_CANTXB); // CANB TX // Initialize the CAN controllers CAN_initModule(CANB_BASE); // Set up the CAN bus bit rate to 500 kbps // 500k 20 // 250k 20 / 16 // 1000k 10 CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ/2,500000, 20); // CANB //CAN_enableTestMode(CANB_BASE, CAN_TEST_EXL); // Initialize the transmit message object used for sending CAN messages. // Message Object Parameters: // CAN Module: A // Message Object ID Number: 1 // Message Identifier: 0x01 // Message Frame: Standard // Message Type: Transmit // Message ID Mask: 0x0 // Message Object Flags: None // Message Data Length: 4 Bytes // CAN_setupMessageObject(CANB_BASE, TX_MSG_OBJ_ID, CAN_ID, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_DATA_LENGTH); // 配置接收邮箱 2 // Message Data Length: Dont care for a Receive mailbox CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, CAN_ID, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_RX_INT_ENABLE, MSG_DATA_LENGTH); // 注册 CANB 中断 //CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0 | CAN_INT_ERROR | CAN_INT_STATUS); // CANB CAN_enableInterrupt(CANB_BASE, CAN_INT_IE0 | CAN_INT_ERROR |CAN_INT_STATUS); // CANB Interrupt_register(INT_CANB0, canB_ISR); Interrupt_enable(INT_CANB0); CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0); // Start CANB module operations CAN_startModule(CANB_BASE); } uint32_t status; // 接收中断函数 __interrupt void canB_ISR(void) { int i0; uint32_t errReg; status CAN_getInterruptCause(CANB_BASE); if(status CAN_INT_INT0ID_STATUS) { errReg CAN_getStatus(CANB_BASE); if((errReg 0x8000U) ! 0U) // BUSOFF触发 { // 软复位CAN退出BUSOFF CAN_initModule(CANB_BASE); CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ/2,500000, 20); CAN_startModule(CANB_BASE); } } else if(status TX_MSG_OBJ_ID) { CAN_clearInterruptStatus(CANB_BASE, TX_MSG_OBJ_ID); //errorFlag 0; } else if(status RX_MSG_OBJ_ID) { CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, rxMsgData); CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID); for(i0;i8;i) { txMsgData[i] rxMsgData[i]; } rxMsgCount; //errorFlag 0; } CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); }主函数#include driverlib.h #include device.h #include board.h #include c2000ware_libraries.h #include my_can.h #define delay_s(x) SysCtl_delay(((((long double)(x)) / (2.0L /(long double)DEVICE_SYSCLK_FREQ)) - 9.0L) / 5.0L) #define delay_ms(x) SysCtl_delay(((((long double)(x)) / (2000.0L /(long double)DEVICE_SYSCLK_FREQ)) - 9.0L) / 5.0L) #define delay_us(x) SysCtl_delay(((((long double)(x)) / (2000000.0L /(long double)DEVICE_SYSCLK_FREQ)) - 9.0L) / 5.0L) void main(void) { Device_init(); Device_initGPIO(); Interrupt_initModule(); Interrupt_initVectorTable(); EINT; ERTM; Board_init(); //GPIO11 用于呼吸灯指示程序有没有卡住 GPIO_setPinConfig(GPIO_11_GPIO11); GPIO_setPadConfig(11, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(11, GPIO_QUAL_SYNC); GPIO_setDirectionMode(11, GPIO_DIR_MODE_OUT); GPIO_setControllerCore(11, GPIO_CORE_CPU1); //C2000Ware_libraries_init(); MY_can_bsp_init(); Interrupt_enableMaster(); //开启总中断 while(1) { CAN_sendMessage(CANB_BASE, TX_MSG_OBJ_ID, MSG_DATA_LENGTH, txMsgData); // Poll TxOk bit in CAN_ES register to check completion of transmission //while(((HWREGH(CANB_BASE CAN_O_ES) CAN_ES_TXOK)) ! CAN_ES_TXOK){} delay_ms(10); CAN_sendMessage(CANB_BASE, TX_MSG_OBJ_ID, MSG_DATA_LENGTH, txMsgData2); // Poll TxOk bit in CAN_ES register to check completion of transmission //while(((HWREGH(CANB_BASE CAN_O_ES) CAN_ES_TXOK)) ! CAN_ES_TXOK){} GPIO_togglePin(11); delay_ms(1000); } }测试效果我的程序很简单DSP每隔约1s先后发送俩条信息其中第一条可以被接收中断替换掉如果接收中断收到新信息那DSP发送的第一条就被替换为收到的信息CAN BUSOFFCAN 控制器里面有两个错误计数器发送错误 / 接收错误 计数器错一次 1 正常 -1≥ 128→BUSOFF直接断开总线我的代码有软启恢复CAN的笨办法因为我不知道为何通信老是进CAN BUSOFF

相关新闻