Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
先楫HPM_RISCV
CAN总线
HPM5300基于rt-thread移植sae j1939
5.00
发布于 2024-01-10 17:04:39 浏览:480
订阅该版
[tocm] ### 本篇文章记录下hpm5300基于rt-thread移植sae j1939 ------------ > 为什么移植j1939,并发布文章 1.工作的需要,需要使用J1939协议 2.为了记录下,让大家也能快速移植起来 ## J1939的简介 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/bed4464637f525619c08e08f3210f50c.png.webp) ## J1939的报文格式 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/90c5393874afccc56b808a70802f237e.png.webp) PF的数值不同,把报文分为PDU1和PDU2, ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/a6971d01fb2c14ac4333dc7c9137bd3c.png.webp) ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/1bb14c6e1dc3844812cf246c4208203d.png) ### PDU1 此格式允许将适用的参数组发送到特定的或全局目标。PDU特定字段包含一个目标地址。PDU1格式消息可以被请求或发送。\ PDU1格式消息由**PF字段确定。当PF字段值为0到239时,消息为PDU1格式**。 PDU特定**域(PS)占8bit**,PS的定义取决于PF, 它可能表示目标地址( Destination Address, DA),可能表示组扩展(Group Extension,GE), 目标地址(DA)占8bit,DA是报文的目标地址,除目标地址的设备外,其他设备应该忽略此报文。 **如果目标地址为0xFF,则表示为全局地址**,此时所有设备都应该监听此报文并在收到报文后做出响应 ## 参考资料 1、OpenSAEJ1939开源地址 https://github.com/DanielMartensson/Open-SAE-J1939 2、SAE J1939官方文档 [https://www.sae.org/standards/development/ground-vehicle/sae-j1939-standards-collection-on-the-web](https://www.sae.org/standards/development/ground-vehicle/sae-j1939-standards-collection-on-the-web "https://www.sae.org/standards/development/ground-vehicle/sae-j1939-standards-collection-on-the-web") ### 源码结构 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/342698de42b8fcf2dc86684278ec301d.png.webp) ### 复制到工程目录下去 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/91c31bf552f99a5bde498d7c65a04499.png) 只需要去关注 CAN_Transmit_Receive.c ```c #include "Hardware.h" #include
#include "Open_SAE_J1939/Open_SAE_J1939.h" #include "ISO_11783/ISO_11783-7_Application_Layer/Application_Layer.h" /*=========创建一个线程去接收can消息并让协议栈去解=============================================*/ static struct rt_thread can_sae1939 ;//创建静态线程 #define SAE1939_PRIORITY 19 #define SAE1939_STACK_SIZE 2048 #define SAE1939_TIMESLICE 10 static char SAE1939_Stack[SAE1939_STACK_SIZE]; #define SAE1939_NAME "SAE1939" //====================================================== //sae j1939使用的句柄 static J1939 j1939_handler; //信号量 开启can接收中断,一收到消息就通知处理线程读取数据并处理 static rt_sem_t can1939_sem = RT_NULL; /* This is a call back function e.g listener, that will be called once SAE J1939 data is going to be sent */ static void (*Callback_Function_Send)(uint32_t, uint8_t, uint8_t[]) = NULL; static void (*Callback_Function_Read)(uint32_t*, uint8_t[], bool*) = NULL; static void (*Callback_Function_Traffic)(uint32_t, uint8_t, uint8_t[], bool) = NULL; /* * 消息发送 底层的消息发送函数 */ ENUM_J1939_STATUS_CODES CAN_Send_Message(uint32_t ID, uint8_t data[]) { ENUM_J1939_STATUS_CODES status = STATUS_SEND_BUSY; mcan_tx_frame_t tx_buf; status = STATUS_SEND_OK; tx_buf.dlc =8; tx_buf.ext_id =ID; tx_buf.use_ext_id=1; rt_memcpy(tx_buf.data_8, data,8); status =mcan_transmit_blocking(BOARD_APP_CAN_BASE, &tx_buf); if (status != status_success) { rt_kprintf("CAN sent message failed, error_code:%d\n", status); return -1; } status = STATUS_SEND_OK; err: return status; } /* Send a PGN request * PGN: 0x00EA00 (59904) 是因为发送请求只需要发送三个字节 */ ENUM_J1939_STATUS_CODES CAN_Send_Request(uint32_t ID, uint8_t PGN[]) { ENUM_J1939_STATUS_CODES status = STATUS_SEND_BUSY; mcan_tx_frame_t tx_buf; status = STATUS_SEND_OK; tx_buf.dlc =3;//只需要发三个字节 tx_buf.ext_id =ID; tx_buf.use_ext_id=1; rt_memcpy(tx_buf.data_8, PGN,3); status =mcan_transmit_blocking(BOARD_APP_CAN_BASE, &tx_buf); if (status != status_success) { rt_kprintf("CAN sent message failed, error_code:%d\n", status); return -1; } status = STATUS_SEND_OK; err: return status; } /* Read the current CAN-bus message. Returning false if the message has been read before, else true */ bool CAN_Read_Message(uint32_t *ID, uint8_t data[]) { bool is_new_message = false; mcan_rx_message_t can_rx; //从缓冲区中获取数据 mcan_read_rxfifo(BOARD_APP_CAN_BASE, 0, (mcan_rx_message_t *) &can_rx);//接收 *ID =can_rx.ext_id; rt_memcpy(data, can_rx.data_8, 8); if(can_rx.dlc==0)//需要判断下是不是真的接收到了数据 { is_new_message = 0; } else { is_new_message=1; } return is_new_message; } //设置回调函数 一个是发送,一个是接收,还有一个还没研究 void CAN_Set_Callback_Functions(void (*Callback_Function_Send_)(uint32_t, uint8_t, uint8_t[]), void (*Callback_Function_Read_)(uint32_t*, uint8_t[], bool*), void (*Callback_Function_Traffic_)(uint32_t, uint8_t, uint8_t[], bool)){ Callback_Function_Send = Callback_Function_Send_; Callback_Function_Read = Callback_Function_Read_; Callback_Function_Traffic = Callback_Function_Traffic_; } void CAN_Delay(uint8_t milliseconds) { //延时函数 rt_thread_mdelay(milliseconds); } //can3的中断处理函数 void can3_isr(void) { uint32_t flags = mcan_get_interrupt_flags(BOARD_APP_CAN_BASE); #if 1 if ((flags & MCAN_INT_RXFIFI0_NEW_MSG) != 0) //收到了新的数据 标准帧 {//接收缓冲区 rt_sem_release(can1939_sem);//释放信号量 } #endif mcan_clear_interrupt_flags(BOARD_APP_CAN_BASE, flags); } SDK_DECLARE_EXT_ISR_M(BOARD_APP_CAN_IRQn,can3_isr); //初始化硬件can 打开中断接收 void Can_Init(void) { MCAN_Type *base = BOARD_APP_CAN_BASE; mcan_config_t can_config; mcan_get_default_config(base, &can_config);//获取默认Can配置 can_config.baudrate = 125000; /* 500kbps */ can_config.mode = mcan_mode_normal;//设置工作模式为标准模式 board_init_can(base);//初始化使用的时钟和io口 uint32_t can_src_clk_freq = board_init_can_clock(base);//获取时钟 uint32_t interrupt_mask = MCAN_EVENT_RECEIVE ;//中断 接收中断 hpm_stat_t status = mcan_init(base, &can_config, can_src_clk_freq); if (status != status_success) { rt_kprintf("CAN initialization failed, error code: %d\n", status); return; } can1939_sem = rt_sem_create("can1939", 0, RT_IPC_FLAG_FIFO); //使用使用到的中断 mcan_enable_interrupts(base, interrupt_mask);//使能中断 intc_m_enable_irq_with_priority(BOARD_APP_CAN_IRQn, 1);//打开中断,然后设置优先级 打开中断,设置优先级 rt_kprintf("can init success\r\n"); } void sae1939_recv_thread_entry(void* parameter) { Open_SAE_J1939_Startup_ECU(&j1939_handler); /* 启动本机 */ j1939_handler.information_this_ECU.this_ECU_address = 0x80; /* 设置本机地址,范围0-253, 而255用于广播地址,254用于错误地址 */ rt_kprintf("sae1939 run ...\r\n"); while(1) { if(rt_sem_take(can1939_sem, RT_WAITING_FOREVER)==RT_EOK) { Open_SAE_J1939_Listen_For_Messages(&j1939_handler); //监听消息 } } } int Start_Can(void) { Can_Init();// 初始化硬件 //创建线程 rt_thread_init(&can_sae1939,SAE1939_NAME, sae1939_recv_thread_entry, RT_NULL, &SAE1939_Stack[0], sizeof(SAE1939_Stack), SAE1939_PRIORITY, SAE1939_TIMESLICE); //启动线程 rt_thread_startup(&can_sae1939); return RT_EOK; } INIT_APP_EXPORT(Start_Can); ``` 编译的时候可能会提示头文件找不到。全部加入进去 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/0ee25f90f1bc1db4f1615d37dc644927.png) 烧录到设备上,会发送出两条指令 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/15c4d4f74ad47f34da2503a344366d5d.png) ```c //在初始化协议栈时他会上电地址信息处理 Open_SAE_J1939_Startup_ECU-> SAE_J1939_Response_Request_Address_Claimed()//这里会发送自身的地址 SAE_J1939_Send_Request_Address_Claimed()//请求其他节点,获取其他节点的地址信息记录到本地 ``` ### PGN请求 PGN请求的作用就是一个设备对其他设备发送PGN命令请求,其他设备相应回复信息 PGN请求的帧ID 18EA'DA'SA' 其中DA是目标地址,如果为0xff那么就是广播 同理SA是源地址 例如:请求地址信息 ![screenshot_image.png](https://oss-club.rt-thread.org/uploads/20240110/280daf359961112acf103338218a2163.png)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
ZWH
这个人很勤快,没空留下点什么
文章
3
回答
141
被采纳
3
关注TA
发私信
相关文章
1
我也来传一个CANOpen移植,RTT+STM32F107+CanOpenNode
2
谁有STM32裸跑的CANopen程序啊???
3
CAN驱动程序框架
4
CAN驱动接口如何规范一下
5
RTT无法进入线程.Cannot access Memory
6
编译提示arm-none-eabi/bin/ld: cannot find crt0.o: No such file o
7
rtt 2.1.0 正式版 mdk4 bsp/stm32 编译canapp.c错误
8
STM32F10XCAN驱动使用的问题
9
2.1版本stm32f10x分支bxcan驱动波特率设置的bug
10
rtthread2.1.0下,找不到can1设备
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
a1012112796
20
个答案
3
次被采纳
张世争
11
个答案
3
次被采纳
踩姑娘的小蘑菇
7
个答案
3
次被采纳
rv666
9
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部