news 2026/6/6 20:56:47

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TMS320F28379D笔记4:CAN通信的收发配置

今日配置下CAN通信,顺带理解下CAN 的一些基础知识

目录

CAN基础知识:

CAN控制器

CAN收发器

CAN总线上的0和1

CAN通信示波器信号直观感受:

CAN盒与MCU的连接:

Ti 例程代码注意点:

代码贴出:

#include "my_can.h"

主函数:

测试效果:

CAN BUSOFF


CAN基础知识:

CAN控制器

CAN控制器内部结构还是挺复杂的,一般现在CAN控制器都是与处理器集成在一起

其实对于编程的人来说,无非也就是包含一些控制、状态、配置等寄存器。

比如我们看到有些STM32芯片带有CAN,也就是说CAN控制器已经集成在STM32芯片中了,我们只需要编程操作其中的寄存器即可。

F28379D里面有CAN芯片:

CAN收发器

将CAN收发引脚(CAN_TX和CAN_RX)的TTL信号转换成CAN总线的电平信号

CAN总线上的0和1

CAN总线为「两线」「差分」信号,用隐形代表逻辑1,显性代表逻辑0。

CAN通信示波器信号直观感受:

CAN的波形差不多是这样的,这里由于Ti例程的时钟影响,说不清是什么波特率的CAN,但波形是正确的,只是频率未知:

加了逻辑分析的效果如下:

CAN盒与MCU的连接:

CAN盒子

CAN-H 接 CAN-H

CAN-L 接 CAN-L

GND 接 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: "Don't 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 i=0; 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(i=0;i<8;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 BUSOFF

CAN 控制器里面有两个错误计数器发送错误 / 接收错误 计数器

错一次 +1 正常 -1

≥ 128BUSOFF(直接断开总线)

我的代码有软启恢复CAN的笨办法,因为我不知道为何通信老是进CAN BUSOFF:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/6 20:55:40

终极宝可梦随机化工具:Universal Pokemon Randomizer ZX 完整指南

终极宝可梦随机化工具&#xff1a;Universal Pokemon Randomizer ZX 完整指南 【免费下载链接】universal-pokemon-randomizer-zx Public repository of source code for the Universal Pokemon Randomizer ZX 项目地址: https://gitcode.com/gh_mirrors/un/universal-pokemo…

作者头像 李华
网站建设 2026/6/6 20:55:15

终极英雄联盟工具箱:三步实现智能游戏体验的完整指南

终极英雄联盟工具箱&#xff1a;三步实现智能游戏体验的完整指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 你是否曾经在英雄联盟的选人阶…

作者头像 李华
网站建设 2026/6/6 20:49:52

全国电动车工厂分布在哪些地区?主要产区数据梳理

电动车&#xff08;两轮电动自行车与轻型电动摩托车&#xff09;是过去二十年中国增长最快的消费品制造业之一。从最初几十家拼装厂&#xff0c;到如今规模以上工厂超过三千家&#xff0c;这条产业链的地理分布既有历史路径依赖&#xff0c;也在近几年悄然位移。天下工厂是覆盖…

作者头像 李华
网站建设 2026/6/6 20:47:01

第6章:用AI辅助快速开发外包项目——Cursor实战

本章你将收获 Cursor的完整配置与使用流程(从安装到第一个AI生成的项目,含14个快捷键) 6个不同规模项目的AI辅助开发案例(Chrome扩展、React后台、Python脚本、小程序、数据爬虫、AI聊天机器人) 全栈项目模板(React+Node+PostgreSQL、Vue+Express+MongoDB)的AI生成方法 …

作者头像 李华