在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例嵌入式开发 → OSEK_NM-master汽车网络管理源码

OSEK_NM-master汽车网络管理源码

嵌入式开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:0.67M
  • 下载次数:40
  • 浏览次数:869
  • 发布时间:2019-12-24
  • 实例类别:嵌入式开发
  • 发 布 人:mms198259
  • 文件格式:.zip
  • 所需积分:2
 相关标签: 网络管理 汽车 管理 源码 网络

实例介绍

【实例简介】

基于OsekNM 2.5.3协议实现的OsekNM,跨平台的结构,目前只实现了STM32F407ZGT6平台的驱动。
1. 目录结构
1.1 App目录是一个keil5工程,App/keil/Objects/OsekNM.hex是一个可以直接在STM32F407ZGT6平台运    行的hex文件。
1.2 Driver目录包含了stm32f407子目录和Win7子目录,stm32f407目录下就是实现的STM32F407ZGT6平台的底层驱动,包括定时器和CAN模块的驱动,以及Stm32标准库的东西;Win7子目录是在windows7平台下执行的一些文件;Driver_Common.c是一些公用的驱动,由OsekNM_core统一调用。

1.3 OsekNM_core实现了OsekNM 2.5.3协议的核心逻辑,OsekNM.c实现了对各个节点各状态的处理,OsekNMServer.c实现了OsekNM 2.5.3协议提供给应用程序的API。

2. 移植
2.1 在Driver目录新建文件夹,保存新平台的驱动程序,新的平台下需要实现CAN模块和定时器及中断的驱动程序。
2.2 修改Driver_Common.c文件,修改TX_CAN_Transmit()函数,调用新平台发送CAN报文的CAN模块驱动程序,修改InitPlatform()函数,调用新平台初始化CAN模块和定时器的函数;Recv_EveryMessage()被CAN接受报文中断服务函数调用。
2.3 修改Driver_Common.h文件,#define 新的平台,并包含驱动相关的头文件,#define NMID 新的网络管理报文ID,#define ADDR_SELF 新的节点源地址。
2.4 可以参考stm32f407的例子来实现自己平台的移植。

3. 附注
整个代码移植到我的开发板,并且在CANoe平台验证过。
专门在Vspy平台实现了虚拟的网络管理节点

【实例截图】

from clipboard

【核心代码】

#include "Driver_Common.h"

//与平台相关的公用的驱动代码在这里实现,包括NM报文缓冲区、定时器

//定时器设置
static char SetAlarm_TTYP = 0;
static char SetAlarm_TMAX = 0;
static char SetAlarm_TERROR = 0;
static char SetAlarm_TWBS = 0;
//定时器计数器
static int TTYP_Count = 0;
static int TMAX_Count = 0;
static int TERROR_Count = 0;
static int TWBS_Count = 0;
//报文缓冲区定义
static RecvFIFO_t RecvFIFO;

//定时器超时标志
static TimerOutFlag_t TimerOutFlag_TTYP = 0;
static TimerOutFlag_t TimerOutFlag_TMAX = 0;
static TimerOutFlag_t TimerOutFlag_TERROR = 0;
static TimerOutFlag_t TimerOutFlag_TWBS = 0;

//节点当前状态
extern NMStateType_t NMCurrentState;
//节点当前子状态
extern NMStateType_t NMCurrentSubState;
//节点上一个状态
extern NMStateType_t  NMPreState;
extern NMNodeCfg_t NodeCfg;
//DEBUG
//#define DRVCOM_DEBUG
#ifdef DRVCOM_DEBUG
#define DRVCOM_PRINT(...) printf(__VA_ARGS__)
#else 
#define DRVCOM_PRINT(...)
#endif

/*函数名:TX_CAN_Transmit
*参数:NMPDU
*返回值:成功 1
*说明:调用平台相关的报文发送函数
*/
NMTypeU8_t TX_CAN_Transmit(NMPDU_t* NMPDU)
{
	/*发送报文到总线*/
	#ifdef STM32F407
	return STM32_TX_CAN_Transmit(NMPDU);
	#endif
}

//NMPDU初始化,保留位置1
void InitNMPDU(NMPDU_t* NMPDU)
{
	int i = 0;
	NMPDU->MsgCtl = 0xc8;
	//NMPDU->MsgID = ((NMID << 8) | ADDR_SELF);
	//NMPDU->MsgDA = ADDR_SELF;

	for (; i < 6; i  )
	{
		NMPDU->MsgData[i] = 0xff;
	}
}

//返回定时器是否超时,-1 失败
TimerOutFlag_t GetTimerIsOut(NMTimerType_t TimerType)
{
	switch (TimerType)
	{
	case NM_TIMER_TTYP:
		return TimerOutFlag_TTYP;
	case NM_TIMER_TMAX:
		return TimerOutFlag_TMAX;
	case NM_TIMER_TERROR:
		return TimerOutFlag_TERROR;
	case NM_TIMER_TWBS:
		return TimerOutFlag_TWBS;
	}
	return -1;
}

//清除定时器超时标志
void ClcTimerOutFlag(NMTimerType_t TimerType)
{
	switch (TimerType)
	{
	case NM_TIMER_TTYP:
		TimerOutFlag_TTYP = 0;
		break;
	case NM_TIMER_TMAX:
		TimerOutFlag_TMAX = 0;
		break;
	case NM_TIMER_TERROR:
		TimerOutFlag_TERROR = 0;
		break;
	case NM_TIMER_TWBS:
		TimerOutFlag_TWBS = 0;
		break;
	}
}


//FIFO相关的函数
/*说明:SetFIFO,将收到的报文放入FIFO,并调整FIFO
* 参数:GenericMessage* msg,报文指针
* 返回值:1:成功放入报文到FIFO,0:放入失败
*/
char SetToFIFO(NMPDU_t* msg)
{
	if (RecvFIFO.FullFlag == 1)//先判断缓冲区满否
		return 0;
	/*放入报文到缓冲区*/
	RecvFIFO.MSGs[RecvFIFO.Tail% FIFOMAX] = *msg;
	RecvFIFO.Tail = (RecvFIFO.Tail   1) % FIFOMAX;
	/*清除空标识*/
	RecvFIFO.EmptyFlag = 0;
	if ((RecvFIFO.Tail   1) == RecvFIFO.Head)//缓冲区满
		RecvFIFO.FullFlag = 1;
	return 1;
}
/*说明:GetFIFO,从FIFO取出报文,并调整FIFO
* 参数:GenericMessage* msg,报文指针
* 返回值:1:成功取出报文,0:取出失败
*/
char GetFromFIFO(NMPDU_t* msg)
{
	int i = 2;
	if (RecvFIFO.EmptyFlag == 1)//先判断缓冲区空否
		return 0;
	/*从缓冲区取出报文*/
	msg->MsgDA = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgDA;
	msg->MsgCtl = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgCtl;
	msg->MsgID = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgID;
	//数据域直接复制
	for (; i < OSEKNM_DLC; i  )
	{
		msg->MsgData[i] = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgData[i];
	}
	RecvFIFO.Head = (RecvFIFO.Head   1) % FIFOMAX;
	/*清除满标识*/
	RecvFIFO.FullFlag = 0;
	if ((RecvFIFO.Tail) == RecvFIFO.Head)//缓冲区空
		RecvFIFO.EmptyFlag = 1;
	return 1;
}
/*说明:ClearFIFO,清空整个FIFO
* 参数:void
* 返回值:void
*/
void ClearFIFO(void)
{
	RecvFIFO.Total = 0;
	RecvFIFO.Head = 0;
	RecvFIFO.Tail = 0;
	RecvFIFO.FullFlag = 0;
	RecvFIFO.EmptyFlag = 1;
}

//定时器超时函数
/*LimpHome定时器*/
static void TimerOutTERROR()
{
	TimerOutFlag_TERROR = 1;
#ifdef PRINT_LOG
	char buf[100];
	sprintf(buf, "TError out State:%d\n", NMCurrentState);
	LogOutPut(buf);
#endif
}

/*TMax超时定时器*/
static void TimerOutTMAX()
{
	TimerOutFlag_TMAX = 1;
#ifdef PRINT_LOG
	char buf[100];
	sprintf(buf, "TMAX out State:%d\n", NMCurrentState);
	LogOutPut(buf);
#endif
}

/*TTYP定时器*/
static void TimerOutTTYP()
{
	TimerOutFlag_TTYP = 1;
#ifdef PRINT_LOG
	char buf[100];
	sprintf(buf, "TTYP out State:%d\n", NMCurrentState);
	LogOutPut(buf);
#endif
}
/*WaitBusSleep定时器*/
static void TimerOutTWBS()
{
	TimerOutFlag_TWBS = 1;
#ifdef PRINT_LOG
	char buf[100];
	sprintf(buf, "TWBS out State:%d\n", NMCurrentState);
	LogOutPut(buf);
#endif
}

//10ms定时器
void Timer10()
{
	/*调用SetAlarm(xx),定时器开始递增*/
	if (SetAlarm_TTYP)
	{
		TTYP_Count  ;

		if (TTYP_Count >= 10)//TTYP=100ms
		{
			TTYP_Count = 0;//重新计数
			TimerOutTTYP();
			SetAlarm_TTYP = 0;//每次用完定时器都将其关闭,从而简化定时器管理
		}
	}
	else {
		TTYP_Count = 0;
	}
	if (SetAlarm_TMAX)
	{
		TMAX_Count  ;
		if (TMAX_Count >= 26)//TMAX=260ms
		{
			TMAX_Count = 0;//重新计数
			TimerOutTMAX();
			SetAlarm_TMAX = 0;//每次用完定时器都将其关闭
		}
	}
	else {
		TMAX_Count = 0;
	}
	if (SetAlarm_TERROR)
	{
		TERROR_Count  ;
		if (TERROR_Count >= 100)//TError=1000ms
		{
			TERROR_Count = 0;//重新计数
			TimerOutTERROR();
			SetAlarm_TERROR = 0;//每次用完定时器都将其关闭
		}
	}
	else {
		TERROR_Count = 0;
	}
	if (SetAlarm_TWBS)
	{
		TWBS_Count  ;
		if (TWBS_Count >= 500)//TError=5000ms
		{
			TWBS_Count = 0;//重新计数
			TimerOutTWBS();
			SetAlarm_TWBS = 0;//每次用完定时器都将其关闭
		}
	}
	else {
		TWBS_Count = 0;
	}
}

//平台相关的初始化
void InitPlatform()
{
	/*缓冲区初始化*/
	RecvFIFO.GetMsg = GetFromFIFO;
	RecvFIFO.SetMsg = SetToFIFO;
	RecvFIFO.ClearBuff = ClearFIFO;
	RecvFIFO.ClearBuff();
	/*1.STM32相关的初始化*/
	#ifdef STM32F407
	/*定时器初始化*/
	Stm32Timer3Init();//10ms中断一次
	/*CAN模块初始化*/
	STM32_CAN1_Init();
	#endif
}


/*
*自定义定时器函数:SetAlarm
参数:定时器类型
说明:每次调用都使定时器重新从0开始
*返回值:定时器ID,用定时器类型ID代替定时器ID
*/
int SetAlarm(NMTimerType_t timer)
{
	int Tid = 0;
	switch (timer)
	{
	case NM_TIMER_TTYP:
		SetAlarm_TTYP = 1;
		TTYP_Count = 0;
		TimerOutFlag_TTYP = 0;//每次设置定时器前先清除标志位
		Tid = NM_TIMER_TTYP;
		break;
	case NM_TIMER_TMAX:
		TMAX_Count = 0;
		SetAlarm_TMAX = 1;
		TimerOutFlag_TMAX = 0;//每次设置定时器前先清除标志位
		Tid = NM_TIMER_TMAX;
		break;
	case NM_TIMER_TERROR:
		TERROR_Count = 0;
		SetAlarm_TERROR = 1;
		TimerOutFlag_TERROR = 0;//每次设置定时器前先清除标志位
		Tid = NM_TIMER_TERROR;
		break;
	case NM_TIMER_TWBS:
		TWBS_Count = 0;
		SetAlarm_TWBS = 1;
		TimerOutFlag_TWBS = 0;//每次设置定时器前先清除标志位
		Tid = NM_TIMER_TWBS;
		break;
	}
	return Tid;
}
/*
*自定义定时器函数:CancelAlarm
参数:定时器类型
说明:定时器清0,不再计数
*/
void CancelAlarm(NMTimerType_t timer)
{
	switch (timer)
	{
	case NM_TIMER_TTYP:
		TTYP_Count = 0;
		SetAlarm_TTYP = 0;
		TimerOutFlag_TTYP = 0;//每次关闭定时器先清除标志位
		break;
	case NM_TIMER_TMAX:
		TMAX_Count = 0;
		SetAlarm_TMAX = 0;
		TimerOutFlag_TMAX = 0;//每次关闭定时器先清除标志位
		break;
	case NM_TIMER_TERROR:
		TERROR_Count = 0;
		SetAlarm_TERROR = 0;
		TimerOutFlag_TERROR = 0;//每次关闭定时器先清除标志位
		break;
	case NM_TIMER_TWBS:
		TWBS_Count = 0;
		SetAlarm_TWBS = 0;
		TimerOutFlag_TWBS = 0;//每次关闭定时器先清除标志位
		break;
	}
}
/*CAN中断收到的报文*/
void Recv_EveryMessage(NMPDU_t* p_Msg)
{
	/*将所有收到的NM报文放入缓冲区FIFO*/
	if (((p_Msg->MsgID) != NMID) && ((p_Msg->MsgID>>8) == (NMID>>8)))//过滤网络报文,不接收自己发出去的
	{
		RecvFIFO.SetMsg(p_Msg);//暂时不处理返回值
	}
}

实例下载地址

OSEK_NM-master汽车网络管理源码

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警