AUTOSAR-Communication-准备工作

前言

  • 目前在学习AutoSar的通信模块,根据4.4.0的文档逐一实现通信。
  • 底层是基于STM32固件库的Can通信模块,在他之上进行CAN、CanIf、PduR等模块的功能实现。
  • 此博文不做过多的讲解,只贴代码,代码上会有官方文档的需求号和我的一些理解注释。
  • 每一个模块我都是按照AutoSar官方文档需求去实现每一个功能,但是我也知道我水平所限,有些需求我暂时无法理解,我就没有去实现,望见谅。
  • 具体模块的分析,希望读者自行参考文档、百度等途径。

本章说明

  • 本章是做一些前提工作,主要是基本模块的说明等;
  • 项目的搭建可以参考我另一篇文章搭建项目工程;
  • 我贴出的代码,主要是和本次实验相关的,其他的一些无关代码,读者自行忽略,我就不做删除;

目录结构

 

公共代码

BswM模块

BSWM模块设计主要是为往后BSW模块做其他操作,比如初始化等。

//----------------------------------------------BswM.h
#ifndef BSWM_H
#define BSWM_H

#include "CanIf.h"

void BswM_Init();

#endif

//----------------------------------------------BswM.c
#include "BswM.h"

void BswM_Init(){
	//CANIF模块初始化
	CanIf_Init(NULL_PTR);

	//TODO还需要其他模块的初始化
	
	//开启控制器-理论上这里不能开启,我是为了测试用的
	CanIf_SetControllerMode(Can_CanController_ECAN , CANIF_CS_STARTED);
}

EcuM模块

本模块的设计主要是对MACL模块的初始化工作

//----------------------------------------------EcuM.h
/*
    [1]:EcuM在这里主要做的是处理整块Ecu需要初始化等一系列动作的开始
*/
#ifndef ECUM_H
#define ECUM_H

#include "EcuM_Cfg.h"

#define ECUM_EXTERNAL_DRIVER_INIT_ZERO 	Ecu_External_Driver_Init_Zero

/*
    外设的初始化
    目前:Port Spi CAN
    待完善:IIC ADC FLASH(SPI) EEPROM(IIC) PWM WDG
*/

extern void EcuM_Init();

#endif

//----------------------------------------------EcuM_Cfg.h
#ifndef ECUM_CFG_H
#define ECUM_CFG_H

#include "TIM.h"
#include "Port.h"
#include "SPI.h"
#include "CAN.h"
#include "CanIf.h"
#include "Irq.h"

#include "CanIf.h"

void Ecu_External_Driver_Init_Zero();

#endif

//----------------------------------------------EcuM.c
#include "EcuM.h"
#include "CanIf.h"

void EcuM_Init(){

    //TODO:做其他的处理
    
    //外设初始化
    Ecu_External_Driver_Init_Zero();
}


//----------------------------------------------EcuM_Cfg.c
#include "EcuM_Cfg.h"

void Ecu_External_Driver_Init_Zero(){
    //Port初始化
    Port_Init();
    //IIC初始化
    
    //SPI初始化
    Spi_Init();
    
    /*
        The ECU State Manager module shall initialize the Can module 
        during startup phase by calling the function Can_Init before 
        using any other functions of the Can module.
    */
    Can_Init(NULL_PTR);

	//中断外设主函数
	IRQ_Init();
	//系统定时器初始化
    System_TIM_Init();

}

Base模块

本模块主要是在CAN实现过程中定义的一些公共数据

//----------------------------------------------ComStack.h
#ifndef COM_STACK_CFG_H
#define COM_STACK_CFG_H

/**
* @brief   This type serve as a unique identifier of a PDU within a software module.
*          Allowed ranges: uint8 .. uint16
* @implements PduIdType_type
*/
typedef uint16_t       PduIdType;

/**
* @brief   This type serve as length information of a PDU in bytes.
*          Allowed ranges: uint8 .. uint32
* @implements PduLengthType_Type
*/
typedef uint32_t       PduLengthType;

#endif

//----------------------------------------------ComStack_Types.h
#ifndef COM_STACK_TYPES_H
#define COM_STACK_TYPES_H

#include "ComStack_Cfg.h"

typedef struct {
    uint8_t* SduDataPtr; 
    PduLengthType  SduLength;                                  
} PduInfoType;

typedef enum {
    TP_DATACONF,
    TP_DATARETRY,
    TP_CONFPENDING,
    TP_NORETRY,
} TpDataStateType;
	
typedef struct {
    TpDataStateType TpDataState;
    PduLengthType TxTpDataCnt;
} RetryInfoType;

typedef enum {
    BUFREQ_OK=0,
    BUFREQ_NOT_OK=1,
    BUFREQ_BUSY=2,
    BUFREQ_OVFL=3,
} BufReq_ReturnType;

#endif

//----------------------------------------------Std_Types.h
#ifndef STD_TYPES
#define STD_TYPES

#include "stm32f10x.h"

/**
 * @brief Success return code
 */
#define E_OK            0x00u

/**
 * @brief Return code for failure/error.
 */
#define E_NOT_OK        0x01u

/**
 * @brief ON State.
 */
#define STD_ON      0x01u

/**
 * @brief OFF state.
 */
#define STD_OFF     0x00u

/**
 * @brief The compiler abstraction shall provide the NULL_PTR define with a void pointer
 *        to zero definition.
 */
#define NULL_PTR ((void *)0)

#ifndef TRUE
#define TRUE (1u)
#endif
#ifndef FALSE
#define FALSE (0u)
#endif

typedef uint8_t Std_ReturnType;

typedef unsigned char boolean;

typedef struct{
	uint16_t vendorID;
   	uint16_t moduleID;
   	uint8_t  sw_major_version;
   	uint8_t  sw_minor_version;
   	uint8_t  sw_patch_version;
}Std_VersionInfoType;

#endif

IrqM模块

本模块为中断模块

//----------------------------------------------Irq.h
#ifndef IRQ_H
#define IRQ_H

#include "stm32f10x.h"
//------------中断分组
#define NVIC_IRQ_PRIORITY_GROUP 			NVIC_PriorityGroup_1

//------------CAN1控制器的FIFO0接收中断
#define NVIC_IRQ_CHANNEL_CAN_RX0_FUNCTION	USB_LP_CAN1_RX0_IRQn
#define NVIC_IRQ_CHANNEL_CAN_RX0_PRE		1
#define NVIC_IRO_CHANNEL_CAN_RX0_SUB		0

//------------CAN1控制器的FIFO1接收中断
#define NVIC_IRQ_CHANNEL_CAN_RX1_FUNCTION	CAN1_RX1_IRQn
#define NVIC_IRQ_CHANNEL_CAN_RX1_PRE		1
#define NVIC_IRO_CHANNEL_CAN_RX1_SUB		0

//------------TIM2通用定时器中断
#define NVIC_IRQ_CHANNEL_TIM_COS_FUNCTION 	TIM2_IRQn
#define NVIC_IRQ_CHANNEL_TIM_COS_PRE 		0
#define NVIC_IRQ_CHANNEL_TIM_COS_SUB 		0

extern void IRQ_Init();
#endif

//----------------------------------------------Irq.c
#include "Irq.h"

/**
	STM32存在抢占优先级和响应(子)优先级
	1:抢占优先级高的会抢占优先级低的,如果抢占优先级相同则看子优先级。
		中断1:抢占-1,响应-2
		中断2:抢占-2,响应-1
		中断3:抢占-1,响应-3
		顺序:中断1>中断3>中断2

	2:中断顺序
		设置中断分组
		设置中断的抢占优先级和响应优先级
		开启中断
*/
static void IRQ_CAN_Controller_One_Rx0_Init(){
	NVIC_InitTypeDef CAN_Controller_One_Rx;
	CAN_Controller_One_Rx.NVIC_IRQChannel = NVIC_IRQ_CHANNEL_CAN_RX0_FUNCTION;
	CAN_Controller_One_Rx.NVIC_IRQChannelPreemptionPriority = NVIC_IRQ_CHANNEL_CAN_RX0_PRE;
	CAN_Controller_One_Rx.NVIC_IRQChannelSubPriority = NVIC_IRO_CHANNEL_CAN_RX0_SUB;
	CAN_Controller_One_Rx.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&CAN_Controller_One_Rx);
}
static void IRQ_CAN_Controller_One_Rx1_Init(){
	NVIC_InitTypeDef CAN_Controller_One_Rx;
	CAN_Controller_One_Rx.NVIC_IRQChannel = NVIC_IRQ_CHANNEL_CAN_RX1_FUNCTION;
	CAN_Controller_One_Rx.NVIC_IRQChannelPreemptionPriority = NVIC_IRQ_CHANNEL_CAN_RX1_PRE;
	CAN_Controller_One_Rx.NVIC_IRQChannelSubPriority = NVIC_IRO_CHANNEL_CAN_RX1_SUB;
	CAN_Controller_One_Rx.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&CAN_Controller_One_Rx);
}

static void IRQ_TIM_System_COS_Init(){
    NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQ_CHANNEL_TIM_COS_FUNCTION;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_IRQ_CHANNEL_TIM_COS_PRE;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_IRQ_CHANNEL_TIM_COS_SUB;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void IRQ_Init(){
	//中断优先级分组,设置抢占1 ,响应3
	NVIC_PriorityGroupConfig(NVIC_IRQ_PRIORITY_GROUP);
	//CAN1控制器接收中断初始化
	IRQ_CAN_Controller_One_Rx0_Init();
	IRQ_CAN_Controller_One_Rx1_Init();
	//TIM2系统定时器中断初始化
	IRQ_TIM_System_COS_Init();
}

Port模块

本模块设计为初始化用到的端口

注意:里面端口的定义我是根据我MCU的型号定义的,自行定义的时候,请根据实际情况声明定义。

//----------------------------------------------Port.h
#ifndef PORT_H
#define PORT_H

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "Port_PBCfg.h"

#define CAN_PORT_INIT()         Can_Port_Init()
#define LED_PORT_INIT()         Led_Port_Init()
#define SPI_PORT_INIT()         Spi_Port_Init()
#define EEPROT_IIC_PORT_INIT()  EEPROM_I2c_Port_Init()

//led端口初始化
void Led_Port_Init();

//SPI端口初始化
void Spi_Port_Init();

//EEPRON端口初始化
void EEPROM_I2c_Port_Init();

//can端口初始化
void Can_Port_Init();

void Port_Init();

#endif

//----------------------------------------------Port_PBCfg.h
#ifndef PORT_PBCFG_H
#define PORT_PBCFG_H

//-------------LED PORT--------------
#define LED_PORT                GPIOB
#define LED_PORT_GPIO_CLK       RCC_APB2Periph_GPIOB
#define LED_PORT_FLICK_PIN      GPIO_Pin_5

//-------------SPI PORT--------------

//-------------IIC PORT--------------
#define EEPROM_IIC_PORT         GPIOB
#define EEPROM_IIC_GPIO_CLK     RCC_APB2Periph_GPIOB
#define EEPROM_IIC_SCL_PIN      GPIO_Pin_6
#define EEPROM_IIC_SDA_PIN      GPIO_Pin_7

//-------------CAN PORT--------------
#define CAN_ECAN_PORT           GPIOA
#define CAN_ECAN_GPIO_CLK       RCC_APB2Periph_GPIOA
#define CAN_ECAN_PORT_RX_PIN    GPIO_Pin_11
#define CAN_ECAN_PORT_TX_PIN    GPIO_Pin_12

#endif

//----------------------------------------------Port.c
#include "Port.h"

/*
    LED闪烁
    时钟是在APB2
    Port是GPIOB
    TX是GPIO_Pin_5
*/
static void Led_Port_Init(){
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(LED_PORT_GPIO_CLK , ENABLE);
    GPIO_InitStructure.GPIO_Pin = LED_PORT_FLICK_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(LED_PORT , &GPIO_InitStructure);
    GPIO_SetBits(LED_PORT , LED_PORT_FLICK_PIN);
}

/*
    SPI用到了端口复用
*/
static void Spi_Port_Init(){
    
}

static void EEPROM_I2c_Port_Init(){
    RCC_APB2PeriphClockCmd(EEPROM_IIC_GPIO_CLK , ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;//I/O口驱动电路的响应速度
    GPIO_InitStructure.GPIO_Pin = EEPROM_IIC_SCL_PIN | EEPROM_IIC_SDA_PIN; 
    GPIO_Init(EEPROM_IIC_PORT , &GPIO_InitStructure);
    //两个都拉高,这样可以处以空闲状态
    GPIO_SetBits(EEPROM_IIC_PORT , EEPROM_IIC_SCL_PIN | EEPROM_IIC_SDA_PIN);
}

/*
    时钟是在APB2
    Port是GPIOA
    TX是GPIO_Pin_12
    RX是GPIO_Pin_11
    
*/
static void Can_Port_Init(){
    RCC_APB2PeriphClockCmd(CAN_ECAN_GPIO_CLK , ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = CAN_ECAN_PORT_RX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(CAN_ECAN_PORT , &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = CAN_ECAN_PORT_TX_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(CAN_ECAN_PORT , &GPIO_InitStructure);
}

void Port_Init(){
    
    //LED端口初始化
    LED_PORT_INIT();
    
    //SPI端口初始化
    SPI_PORT_INIT();
    
    //EEPROM使用的I2c端口初始化
    EEPROT_IIC_PORT_INIT();
    
    //can端口初始化
    CAN_PORT_INIT();
}

TIM模块

本模块为定时模块,在本次实验中,我是利用STM32通用TIM2产生1ms的中断,来完成任务的切换。

//----------------------------------------------TIM.h
#ifndef TIM_H
#define TIM_H

#include "stm32f10x.h"
#include "BSPCOS.h"

#define OS_TIM          TIM2
#define OS_TIM_CLK      RCC_APB1Periph_TIM2
#define OS_TIM_IT_TYPE  TIM_IT_Update

void System_TIM_Init();

#endif

//----------------------------------------------TIM.c
#include "TIM.h"

void System_TIM_Init(){
    //启动时钟
    RCC_APB1PeriphClockCmd(OS_TIM_CLK , ENABLE);
    
    //初始化定时器 产生1ms秒的计数
    TIM_TimeBaseInitTypeDef TIM_InitStructure;
    TIM_InitStructure.TIM_Prescaler = 7199;                     /* 定时器预分频,这个预分频是要和计数周期一起计算使用 */
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;     /* 计数方式,向下计数 */
    TIM_InitStructure.TIM_Period = 9;                        	/* 计数周期 */
    TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;         /* 时钟分频,意思是TIM2本来是72MHZ的,需不需要分频 */
    TIM_TimeBaseInit(OS_TIM , &TIM_InitStructure);
	
	//设置允许中断
    TIM_ITConfig(OS_TIM , OS_TIM_IT_TYPE , ENABLE);
	//使能TIM
    TIM_Cmd(OS_TIM , ENABLE);   
}

void TIM2_IRQHandler(void)   //TIM2中断
{
    if (TIM_GetITStatus(OS_TIM, OS_TIM_IT_TYPE) != RESET){
        CosTimItChangeSystemTime();     /* 调用系统定时时间函数 */
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
    }
}

timer_task模块

本模块为定时任务的切换模块

//----------------------------------------------BSPCOS.h
#ifndef BSPCOS_H
#define BSPCOS_H

#include "stm32f10x.h"
#include "BSPCOSCfg.h"

void CosInit();

/*
    设置COS任务
*/
void SetCosTask(uint8_t priority , void(*fnct)(void*) , void *arg);


/*
    启动COS任务
*/
void CosStart(uint8_t priority , uint32_t tenths);

/*
    系统定时器中断调用的函数
*/
void CosTimItChangeSystemTime();

/*
    负责检查个任务是否启动,并执行相关函数
*/
void CosTask();

#endif

//----------------------------------------------BSPCOSCfg.h
#ifndef BSPCOSCFG_H
#define BSPCOSCFG_H

//设置任务的总数
#define COS_MAX_NUM     3

//设置任务的优先级
#define COS_PRIORITY_TIMER2MS           0
#define COS_PRIORITY_TIMER4MS           1
#define COS_PRIORITY_TIMER10MS          2

//任务的运行使能
#define COS_ENABLE                      1
#define COS_DIS_ENABLE                  0

//任务的准备使能
#define COS_STATE_ENABLE                1
#define COS_STATE_DIS_ENABLE            0

//系统最大的时间
#define COS_MAX_USEABLE 0xFFFFFFF0

typedef struct{
    uint8_t CosEn;              //任务使能标志
    uint8_t CosRdy;             //任务状态标志
    uint32_t CosCtr;            //计数器,也就是延迟执行的计数,是在系统时间的基础上操作比较的
    void (*CosFnct)(void*);    //执行的任务
    void *CosFnctArg;          //任务的参数
}t_Cos;


#endif

//----------------------------------------------BSPCOSDef.h
#ifndef BSPCOSDEF_H
#define BSPCOSDEF_H

#include "BSPCOS.h"
#include "SEGGER_RTT.h"

/*
    初始化系统的所有任务
*/
void InitCosAll();

/*
    驱动2ms的定时任务
*/
void Timer2ms(void* p);

/*
    驱动4ms的定时任务
*/
void Timer4ms(void* p);

/*
    驱动10ms的定时任务
*/
void Timer10ms(void*p);

#endif

//----------------------------------------------BSPTimeTask.h
#ifndef BSPTIMETASK_H
#define BSPTIMETASK_H

void Task2ms();

void Task1000msBy4ms();

#endif

//----------------------------------------------BSPCOS.c
#include "BSPCOS.h"

static t_Cos sCosTbl[COS_MAX_NUM];      
//这个是在中断中累加的,这个可以理解为系统时间,用这个时间去调控所有的任务
uint32_t sCosTimer = 0;

void CosInit(){
    uint8_t index = 0;
    t_Cos* pCos;
    sCosTimer = 0;
    pCos = sCosTbl;
    for(; index < COS_MAX_NUM ; ++index){
        pCos->CosEn = COS_DIS_ENABLE;
        pCos->CosCtr = 0xFFFFFFFF;
        pCos->CosRdy = COS_STATE_DIS_ENABLE;
        ++pCos;
    }
}
    
void SetCosTask(uint8_t priority , void(*fnct)(void*) , void *arg){
    t_Cos* pCos;
    if(priority < COS_MAX_NUM){
        pCos = (sCosTbl + priority);
        pCos->CosFnct = fnct;
        pCos->CosFnctArg = arg;
    }
}
        
void CosStart(uint8_t priority , uint32_t tenths){
    t_Cos* pCos;
    if(priority < COS_MAX_NUM){
        pCos = (sCosTbl + priority);
        pCos->CosEn = COS_ENABLE;       //在这里任务都使能了
        pCos->CosCtr = tenths + sCosTimer;
        if(tenths == 0){
            pCos->CosRdy = COS_STATE_ENABLE;
        }else{
            pCos->CosRdy = COS_STATE_DIS_ENABLE;
        }
    }
}

void CosTimItChangeSystemTime(){
    //定时器中断函数中,累加这个
    ++sCosTimer;
    t_Cos* pCos;
    //此处需要处理系统时间溢出的情况和延迟计数的溢出,
    if(sCosTimer > COS_MAX_USEABLE){
        for(uint8_t index = 0 ; index < COS_MAX_NUM ; ++index){
            pCos = (sCosTbl + index);
            if(pCos->CosCtr != 0xFFFFFFFF && pCos->CosCtr > COS_MAX_USEABLE){
                pCos->CosCtr -= COS_MAX_USEABLE;
            }
        }
        sCosTimer -= COS_MAX_USEABLE;
    }
    //此处判断任务是否执行
    for(uint8_t index = 0 ; index < COS_MAX_NUM ; ++index){
        pCos = (sCosTbl + index);
        if(COS_ENABLE == pCos->CosEn && pCos->CosCtr <= sCosTimer){
            pCos->CosRdy = COS_STATE_ENABLE;//任务如果是使能的情况下,并且任务的计数时间<=系统计数,那么任务状态开启
        }
    }
}

void CosTask(){
    t_Cos* pCos;
    void (*pfnct)(void*);       //执行的函数
    void* parg;                 //函数的参数
    for(uint8_t index = 0 ; index < COS_MAX_NUM ; ++index){
         pCos = (sCosTbl + index);
         if(pCos->CosEn == COS_ENABLE && pCos->CosRdy == COS_STATE_ENABLE){
            pfnct = pCos->CosFnct;
            parg = pCos->CosFnctArg;
            pCos->CosCtr = 0xFFFFFFFF;//这里把任务延时加到最大,这个数将在下一次任务启动中重新赋值
            pCos->CosRdy = COS_STATE_DIS_ENABLE;//该任务将关闭执行,等待中断中在此开启
            pCos->CosEn = COS_DIS_ENABLE;//关闭任务的使能,将在任务启动函数中,在此开启
            //判断函数是不是为空
            if(pfnct != (void (*)(void *))0){
                (*pfnct)(parg);//执行函数
            }
            //其实我觉得这个只是为了保险,或者有些任务他只执行一次
            if(pCos->CosCtr != 0xFFFFFFFF){
                 pCos->CosEn = COS_ENABLE;
            }
            return;//一次只执行一个任务
         }
    }
}

//----------------------------------------------BSPCOSDef.c
#include "BSPCOSDef.h"
#include "BSPTimeTask.h"

extern uint32_t sCosTimer;
extern void CAN_Test_1();

void InitCosAll(){
    //先初始化COS
    CosInit();
    //开始设置任务
    SetCosTask(COS_PRIORITY_TIMER2MS , Timer2ms , (void*)0);
    SetCosTask(COS_PRIORITY_TIMER4MS , Timer4ms , (void*)0);
    SetCosTask(COS_PRIORITY_TIMER10MS , Timer10ms , (void*)0);
    //开始启动任务
    CosStart(COS_PRIORITY_TIMER2MS, 0);//这个的函数将不会延迟,而是系统启动之后立马执行
    CosStart(COS_PRIORITY_TIMER4MS, 1);
    CosStart(COS_PRIORITY_TIMER10MS, 2);
}

/*
    测试的时候,都改成按秒定时
*/
void Timer2ms(void* p){
    CosStart(COS_PRIORITY_TIMER2MS, 2);
    //后面就开始添加自己的函数
    //SEGGER_RTT_printf(0,"time:%d task1 running...\n",sCosTimer);
    Task2ms();
}

void Timer4ms(void* p){
    CosStart(COS_PRIORITY_TIMER4MS, 4);
    //后面就开始添加自己的函数
    //SEGGER_RTT_printf(0,"time:%d task2 running...\n",sCosTimer);
    
}

void Timer10ms(void* p){
    CosStart(COS_PRIORITY_TIMER10MS, 10);
    //后面就开始添加自己的函数
    //SEGGER_RTT_printf(0,"time:%d task3 running...\n",sCosTimer);
	static uint32_t Global_Time_10_ms = 0;
	if(!(Global_Time_10_ms % 100)){
		Task1000msBy4ms();
	}
	if(Global_Time_10_ms == 100) Global_Time_10_ms = 0;
	++Global_Time_10_ms;
	
}

//----------------------------------------------BSPTimeTask.c
#include "BSPTimeTask.h"
#include "CAN.h"
#include "CanIf.h"

extern void CanIf_Test1_by_2_ms();

void Task2ms(){
	/* Can Main Function */
	Can_MainFunction();
	static uint8_t pduSet = 1;
	if(pduSet){
		CanIf_SetPduMode(Can_CanController_ECAN , CANIF_SET_ONLINE);
		pduSet = 0;
	}
	CanIf_Test1_by_2_ms();
}

void Task1000msBy4ms(){
	/* LED Flicker */
	GPIO_WriteBit(GPIOB , GPIO_Pin_5 , (BitAction)(SET - GPIO_ReadOutputDataBit(GPIOB , GPIO_Pin_5)));
    //CAN_Test_1();
}

main

主函数

//----------------------------------------------main.c
#include "stm32f10x.h"
#include "EcuM.h"
#include "BswM.h"
#include "BSPCOS.h"

int main(void){
    //delayInit();
    //ECU初始化
    EcuM_Init();
	//BSW初始化
	BswM_Init();
    //初始化系统的所有定时任务
    InitCosAll();
    while(1){
        CosTask();
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值