(二)CAN通信协议代码-升级版

CAN代码-升级版

(1)can.c

#define CAN_BUS_ENABLE  1
#define CAN_BUS_DISABLE 0
#define CAN2_FILTER_S   14

typedef struct __can_gpio_pin_t{
    uint32_t  pin_bit;
    uint32_t gpio_rcc;
    GPIO_TypeDef *gpio_port;
}can_gpio_pin_t;

typedef struct __send_status_t{
    uint8_t mbox_s;
}send_status_t;

typedef struct _can_cfg_t{
    uint8_t can_dev_id;
    uint8_t pin_map;
    uint8_t fifo_no;
    uint8_t filter_start;
    can_gpio_pin_t r_pin;
    can_gpio_pin_t t_pin;    
    uint32_t can_rcc;
    CAN_TypeDef* can_ch;
    send_status_t txs;
    uint8_t irq;
    uint8_t it_flag;
    uint8_t res[2];
}can_cfg_t;

/*--- 设置常用CAN波特率 ---*/
typedef struct __can_tq_t {
    uint16_t can_baudrate;
    uint16_t can_prescaler;
    uint8_t can_syn_jump_width;
    uint8_t can_time_bit_seg1;
    uint8_t can_time_bit_seg2;
    uint8_t can_res;
}can_tq_t;

static can_tq_t can_baud_array[] = {
    { 5, 400, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 10, 200, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 20, 100, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 40, 50, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 50, 40, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 80, 25, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 100, 20, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 125, 16, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 200, 10, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 250, 36, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
    { 400, 5, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 500, 4, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 666, 3, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_8tq },
    { 800, 11, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
    { 1000, 9, CAN_SJW_2tq, CAN_BS1_2tq, CAN_BS2_1tq },
    { 0 },
};

static can_cfg_t can_cfg[CAN_DEV_CNT]={
    [CAN_DEV1] = {
        .can_dev_id = CAN_DEV1,
        .fifo_no = CAN_Filter_FIFO0,
        .t_pin = { GPIO_Pin_12, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_TX PA12
        .r_pin = { GPIO_Pin_11, RCC_APB2Periph_GPIOA, GPIOA }, // CAN1_RX PA11
        .pin_map = 0,
        .can_rcc = RCC_APB1Periph_CAN1,
        .can_ch = CAN1,
        .filter_start = 0,//0~13
        .irq = CAN1_RX0_IRQn,
        .it_flag = CAN_IT_FMP0,
    },
    [CAN_DEV2] = {
        .can_dev_id = CAN_DEV2,
        .fifo_no = CAN_Filter_FIFO1,
        .t_pin = { GPIO_Pin_13, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_TX PB13
        .r_pin = { GPIO_Pin_12, RCC_APB2Periph_GPIOB, GPIOB }, // CAN2_RX PB12
        .pin_map = 0,
        .can_rcc = RCC_APB1Periph_CAN2,
        .can_ch = CAN2,
        .filter_start = CAN2_FILTER_S,//14~27
        .irq = CAN2_RX1_IRQn,
        .it_flag = CAN_IT_FMP1,
    }
};

static can_tq_t *__get_tp(int br)
{
    int i = 0;
    while(can_baud_array[i].can_baudrate != 0){
        if(can_baud_array[i].can_baudrate == br){
            return &can_baud_array[i];
        }
        i++;
    }
    return NULL;
}

static void __can_enable(int can_dev, u32 val)
{
    if(can_dev == CAN_DEV1){
        if(val == CAN_BUS_ENABLE){
            _debug(SYS_INFO, "CAN_1 bus enable\n");
            pp_ctrl_set(PIN_CAN1_STB,0);/*0 enable*/
        }else{
            pp_ctrl_set(PIN_CAN1_STB,1);/*1 disable*/
        }
    }else if(can_dev == CAN_DEV2){
        if(val == CAN_BUS_ENABLE){
            _debug(SYS_INFO, "CAN_2 bus enable\n");
            pp_ctrl_set(PIN_CAN2_STB,0);/*0 enable*/
        }else{
            pp_ctrl_set(PIN_CAN2_STB,1);/*1 disable*/
        }
    }
}

int can_dev_init(int can_dev, int can_mode, int brp)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    CAN_InitTypeDef CAN_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    can_cfg_t* pparam = &can_cfg[can_dev];

    _debug(SYS_INFO, "CAN%d Init start\n", pparam->can_dev_id + 1);

    CAN_DeInit(pparam->can_ch);

    /* 使能GPIO、CANx外设复用功能时钟使能 */
    RCC_APB1PeriphClockCmd(pparam->can_rcc, ENABLE);
    RCC_APB2PeriphClockCmd(pparam->r_pin.gpio_rcc | pparam->t_pin.gpio_rcc, ENABLE);
    // RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);

    /* GPIO 复用功能初始化:Rx */
    GPIO_InitStructure.GPIO_Pin = pparam->r_pin.pin_bit;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(pparam->r_pin.gpio_port, &GPIO_InitStructure);

    /* GPIO 复用功能初始化:Tx */
    GPIO_InitStructure.GPIO_Pin = pparam->t_pin.pin_bit;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
    GPIO_Init(pparam->t_pin.gpio_port, &GPIO_InitStructure);
    
    /* CAN 初始化 */
    u8 ret_can;
    can_tq_t* pcan_baud = __get_tp(brp);
    if (pcan_baud == NULL) {
        _debug(SYS_INFO, "Setting BaudRate param is unqualified %d\n",brp);
        return -1;
    }
    CAN_InitStructure.CAN_Prescaler = pcan_baud->can_prescaler;
    CAN_InitStructure.CAN_SJW = pcan_baud->can_syn_jump_width;
    CAN_InitStructure.CAN_BS1 = pcan_baud->can_time_bit_seg1;
    CAN_InitStructure.CAN_BS2 = pcan_baud->can_time_bit_seg2;
    _debug(SYS_INFO, "BaudRate = %dKHZ, can_prescaler = %d, CAN_SJW_%dtq, CAN_BS1_%dtq, CAN_BS2_%dtq \n",
        pcan_baud->can_baudrate,
        pcan_baud->can_prescaler,
        pcan_baud->can_syn_jump_width + 1,
        pcan_baud->can_time_bit_seg1 + 1,
        pcan_baud->can_time_bit_seg2 + 1);

    CAN_InitStructure.CAN_Mode = can_mode;
    CAN_InitStructure.CAN_TTCM = DISABLE; //can_time_trigger_communication;
    CAN_InitStructure.CAN_ABOM = DISABLE; //can_auto_bus_off;
    CAN_InitStructure.CAN_AWUM = DISABLE; //can_auto_wakeup;
    CAN_InitStructure.CAN_NART = ENABLE;  //can_no_auto_retransmit;(开启不自动重发)
    CAN_InitStructure.CAN_RFLM = DISABLE; //can_recv_fifo_lock;
    CAN_InitStructure.CAN_TXFP = DISABLE; //can_transmit_fifo_priority;
    ret_can = CAN_Init(pparam->can_ch, &CAN_InitStructure);
    if (ret_can == 0) {
        _debug(SYS_INFO, "CAN%d Initialize is failed \n", pparam->can_dev_id + 1);
        return -1; 
    }
#if 1
    /* 接收中断参数配置 */
    CAN_ITConfig(pparam->can_ch, pparam->it_flag, ENABLE); //FIFO0消息挂号中断允许
    NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //接收IRQ通道使能
    NVIC_Init(&NVIC_InitStructure); //初始化接收中断配置
#endif
   _debug(SYS_INFO, "CAN%d Init end\n", pparam->can_dev_id + 1);
    return 0;
}

int p_can_open(int can_dev,int bps)
{
  int ret = can_dev_init(can_dev,CAN_Mode_Normal,bps);
  if(ret == 0){
    __can_enable(can_dev,CAN_BUS_ENABLE);
  }
  return ret;
}

void p_can_close(int can_dev)
{
    NVIC_InitTypeDef NVIC_InitStructure = {0};
    can_cfg_t* pparam = &can_cfg[can_dev];
    __can_enable(can_dev,CAN_BUS_DISABLE);
    CAN_ITConfig(pparam->can_ch, pparam->it_flag, DISABLE);
    NVIC_InitStructure.NVIC_IRQChannel = pparam->irq;
    NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; 
    NVIC_Init(&NVIC_InitStructure);
    CAN_DeInit(pparam->can_ch);
}

int p_can_read(int can_dev, can_msg_t* msg)
{
    can_cfg_t* pparam = &can_cfg[can_dev];
    CanRxMsg RxMessage;

    /* 判别是哪个接收邮箱有数据挂起 */
    if (CAN_MessagePending(pparam->can_ch, CAN_FIFO0)) {
        CAN_Receive(pparam->can_ch, CAN_FIFO0, &RxMessage);
    } else if (CAN_MessagePending(pparam->can_ch, CAN_FIFO1)) {
        CAN_Receive(pparam->can_ch, CAN_FIFO1, &RxMessage);
    } else {
        _error("read error can msg");
        return 0;
    }

    if(CAN_Id_Standard == RxMessage.IDE){
        msg->id_type = CAN_ID_ST;
        msg->id = RxMessage.StdId;
        _debug(SYS_INFO, "CAN%d FIFO0 receive msg Std_id = 0x%x ...\n", pparam->can_dev_id + 1, RxMessage.StdId);
    }else{
        msg->id_type = CAN_ID_EX;
        msg->id = RxMessage.ExtId;
        _debug(SYS_INFO, "CAN%d FIFO1 receive msg EXT_id = 0x%x ...\n", pparam->can_dev_id + 1, RxMessage.ExtId);
    }

    if(CAN_RTR_Data == RxMessage.RTR){
        msg->id_frame = CAN_FR_DATA;
    }else{
        msg->id_frame = CAN_FR_REMOTE;
    }
    msg->len = RxMessage.DLC;
    memcpy(msg->data,RxMessage.Data, RxMessage.DLC);
    return RxMessage.DLC;
}

int p_can_send(int can_dev, can_msg_t* msg)
{
    can_cfg_t* pparam = &can_cfg[can_dev];
    CanTxMsg TxMsg = {0};
    if(msg->id_type == CAN_ID_ST){
        TxMsg.IDE = CAN_Id_Standard;
        TxMsg.StdId = msg->id;
    }else{
        TxMsg.IDE = CAN_Id_Extended;
        TxMsg.ExtId = msg->id;
    }
    if(msg->id_frame == CAN_FR_DATA){
       TxMsg.RTR =  CAN_RTR_Data;
    }else{
       TxMsg.RTR =  CAN_RTR_Remote; 
    }
    TxMsg.DLC = msg->len;

    memcpy(TxMsg.Data,msg->data,TxMsg.DLC);

    pparam->txs.mbox_s = CAN_TxStatus_NoMailBox;
    uint8_t tx_mbox = CAN_Transmit(pparam->can_ch, &TxMsg);
    if (tx_mbox == CAN_TxStatus_NoMailBox) {
        _debug(SYS_INFO, "CAN Transmit Status is No MailBox\n");
        return -1;
    }
    pparam->txs.mbox_s = tx_mbox;
    return 0;
}

int p_can_send_ok(int can_dev)
{
    can_cfg_t* pparam = &can_cfg[can_dev];
    if(pparam->txs.mbox_s == CAN_TxStatus_NoMailBox){
        return -1;
    }

    if(CAN_TransmitStatus(pparam->can_ch, pparam->txs.mbox_s) == CAN_TxStatus_Failed){
        return 0;
    }

    return 1;
}

#define CAN_ID_STD_STD	CAN_ID_ST
#define CAN_ID_EXT_EXT	CAN_ID_EX
#define CAN_ID_STD_EXT	2
#define CAN_ID_EXT_STD	3


static int __genc_ids(int format,uint32_t *ids,uint32_t *pout)
{
    switch (format) {
    case CAN_ID_STD_STD:
        pout[0] = (ids[0] << 21) | CAN_Id_Standard;
        pout[1] = (ids[1] << 21) | CAN_Id_Standard;
        break;
    case CAN_ID_STD_EXT:
        pout[0] = (ids[0]  << 21) | CAN_Id_Standard;
        pout[1] = (ids[1] << 3) | CAN_Id_Extended;
        break;
    case CAN_ID_EXT_STD:
        pout[0] = (ids[0]  << 3) | CAN_Id_Extended;
        pout[1] = (ids[1] << 21) | CAN_Id_Standard;
        break;
    case CAN_ID_EXT_EXT:
        pout[0] = (ids[0]  << 3) | CAN_Id_Extended;
        pout[1] = (ids[1] << 3) | CAN_Id_Extended;
        break;
    default: {
        return -1;
        } 
    }
    return 0;
}
static int __p_can_set_filter_list(int filter_id, int fifo_no, int format, uint32_t id1, uint32_t id2)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure = { 0 };
    uint32_t in_ids[2] = {id1,id2};
    uint32_t out_ids[2] = {0};

    if(__genc_ids(format,in_ids,out_ids)){
        _debug(SYS_INFO, "CAN geting id is failed \n");
        return -1;
    }
    _debug(SYS_INFO, "filter_Id = 0x%x 0x%x, filter_number = %d, CAN_Filter_FIFO = %d\n",\
                         out_ids[0], out_ids[1], filter_id, fifo_no);
    CAN_FilterInitStructure.CAN_FilterNumber = filter_id;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = (out_ids[0] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterIdLow = out_ids[0] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (out_ids[1] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = out_ids[1] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = fifo_no;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
    return 0;
}

static int __p_can_set_filter_mask(int filter_id, int fifo_no, int format, uint32_t id, uint32_t mask)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure = { 0 };
    uint32_t in_ids[2] = {id,mask};
    uint32_t out_ids[2] = {0};

    if(__genc_ids(format,in_ids,out_ids)){
        _debug(SYS_INFO, "CAN geting id is successed ...\n");
        return -1;
    }
    _debug(SYS_INFO, "------ filter_Id = 0x%x 0x%x, filter_number = %d, CAN_Filter_FIFO = %d ----------\n",\
                         out_ids[0], out_ids[1], filter_id, fifo_no);
    CAN_FilterInitStructure.CAN_FilterNumber = filter_id;
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterIdHigh = (out_ids[0] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterIdLow = out_ids[0] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (out_ids[1] >> 16) & 0xffff;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = out_ids[1] & 0xffff;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = fifo_no; // CAN_Filter_FIFO0
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);
    return 0;
}

/*
@filter_mode FILTER_LIST  FILTER_MASK
@format  CAN_ID_ST CAN_ID_EX
*/
int p_can_set_filter(int can_dev, int filter_mode, int format, uint32_t* ids, int id_cnt)
{
    int i;
    can_cfg_t* pparam = &can_cfg[can_dev];
    uint32_t r_ids[28] = {0};
    CAN_SlaveStartBank(CAN2_FILTER_S);
    
    if (id_cnt & 1) { //奇数
        for(i = 0; i < id_cnt; i++){
            r_ids[i] = ids[i];
        }
        if(filter_mode == FILTER_LIST){
            r_ids[i] = r_ids[i-1];
        }else{
            r_ids[i] = 0xffffffff;
        }
        id_cnt++;
    }else{
        for(i = 0; i < id_cnt; i++){
            r_ids[i] = ids[i];
        }
    }

    if (filter_mode == FILTER_LIST) {
        for (i = 0; i < id_cnt / 2; i++) {
            __p_can_set_filter_list(pparam->filter_start + i, pparam->fifo_no, format, r_ids[2*i], r_ids[2*i + 1]);
        }
    } else {
        for (i = 0; i < id_cnt / 2; i++) {
            __p_can_set_filter_mask(pparam->filter_start + i, pparam->fifo_no, format, r_ids[2*i], r_ids[2*i + 1]);
        }
    }

    return 0;
}

(2)can.h

#ifndef __p_can_h__
#define __p_can_h__
#if 0
  .word CAN2_TX_IRQHandler
  .word CAN2_RX0_IRQHandler
  .word CAN2_RX1_IRQHandler
  .word CAN2_SCE_IRQHandler
#define CAN_Id_Standard ((uint32_t)0x00000000) /*!< Standard Id */
#define CAN_Id_Extended ((uint32_t)0x00000004) /*!< Extended Id */
#endif

typedef enum {
    CAN_DEV1,
    CAN_DEV2,
    CAN_DEV_CNT
} CAN_DEV_E;


#define CAN_ID_ST 0 //标准帧
#define CAN_ID_EX 1 //扩展帧

#define CAN_FR_DATA 0
#define CAN_FR_REMOTE 1

#define FILTER_LIST 0
#define FILTER_MASK 1

typedef struct _can_msg_t {
    uint8_t id_type; //0:标准帧 1:扩展帧
    uint8_t id_frame; //0:数据帧 1:远程帧
    uint8_t len;
    uint8_t res;
    uint32_t id;
    uint8_t data[8];
} can_msg_t;

int can_dev_init(int can_dev, int can_mode, int brp);
int p_can_open(int can_dev,int bps);
void p_can_close(int can_dev);
int p_can_read(int can_dev,can_msg_t *msg);
int p_can_send(int can_dev,can_msg_t *msg);
/*
@filter_mode FILTER_LIST  FILTER_MASK
@format  CAN_ID_ST CAN_ID_EX
*/
int p_can_set_filter(int can_dev, int filter_mode, int format, uint32_t* ids, int id_cnt);

void p_can_task_start(int can_dev);
void p_can_task_stop(int can_dev);
void p_can_task(void);
#endif


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OBD-II通信协议是指汽车诊断系统中使用的一种标准协议,用于通过汽车的OBD-II接口进行诊断和通信。OBD-II是On-Board Diagnostics第代的缩写,是一种由汽车制造商和环境保护机构共同制定的通信标准。 OBD-II协议规定了汽车控制模块和诊断设备之间的通信方式和数据格式。它定义了一系列的诊断命令和响应,用于读取和清除汽车的故障码、获取实时数据和执行特定的控制功能。 OBD-II协议中主要包含以下几个重要部分: 1. 物理层接口:定义了OBD-II接口的物理连接方式和电气特性,常见的有16针的OBD-II插座。 2. 数据链路层:定义了OBD-II通信的基本规则和数据传输方式,采用串行通信协议,常见的有基于CAN总线的ISO 15765-4协议。 3. 网络层:定义了OBD-II的网络地址和诊断设备的识别方式,使得诊断工具能够准确地与汽车的控制模块进行通信。 4. 应用层:定义了一系列诊断命令和响应格式,包括读取故障码、清除故障码、请求实时数据和执行控制命令等。 OBD-II通信协议的中文版是针对中国市场的特定要求而发布的,主要与欧美标准相兼容。中文版协议在数据格式和语言方面进行了适配,使得国内诊断设备和汽车制造商能够更好地进行通信和故障诊断。 总的来说,OBD-II通信协议是一种标准化的汽车诊断通信协议,通过定义通信方式、数据格式和诊断命令,实现了诊断设备与汽车控制模块之间的有效通信和数据交换。中文版协议是对原有协议的适配,以满足中国市场的需求。 ### 回答2: OBD-II通信协议是一种用于汽车诊断的通信协议,其全称为"On-Board Diagnostics-II",即车载诊断系统第代。它是由国际标准化组织(ISO)制定的一套标准,旨在提供一个统一的汽车诊断接口。 OBD-II通信协议定义了汽车发动机及其相关系统的诊断接口和协议规范,使得车辆制造商和第三方诊断工具能够通过该接口收集和分析车辆的故障码、传感器数据和其他相关信息。该协议规定了诊断接口的物理连接方式、通信速率、命令结构以及数据格式等。 根据OBD-II通信协议的规定,诊断接口通常位于汽车驾驶室内的驾驶员侧脚下方,可通过一个标准的16针连接器与诊断工具相连。通信协议支持多种通信协议和通信速率,包括基于串行通信的ISO 9141-2、ISO 14230-KWP2000、ISO 15765-CAN等。 通过OBD-II通信协议,诊断工具可以发送特定的命令来获取车辆的故障码、实时传感器数据、状态信息等。这有助于识别并解决车辆的故障,提高驾驶安全性和燃油经济性。另外,该协议还支持诊断工具与车辆之间的双向通信,使得用户能够对某些系统参数进行编程和配置。 OBD-II通信协议在全球范围内得到广泛应用,几乎所有新款的汽车都支持该协议。该协议的出现对汽车诊断和维修领域产生了重大影响,为诊断技术的发展提供了基础。同时,它也为诊断设备的研发和市场提供了统一的接口和规范,促进了该行业的发展。 ### 回答3: OBD-II通信协议,即On-Board Diagnostics II,是指汽车诊断系统所采用的一种标准化的通信协议。它主要用于车辆的故障检测和诊断,能够通过与车辆内部的电子控制单元(ECU)进行通信,获取车辆诸多数据和故障代码。 OBD-II通信协议是由美国汽车工程师协会(SAE)制定的国际标准,于1996年开始开始在美国车辆中广泛应用。该协议规定了统一的通信参数、数据格式和诊断模式,使得不同车型和品牌的车辆之间能够进行有效的通信和诊断。 OBD-II通信协议采用了标准的16针OBD-II接口,通过该接口可以连接至诊断工具或诊断设备,实现与车辆的通信。协议规定了通信的物理层和应用层。在物理层,协议采用了电气特性、接口和通信速率的统一标准,以确保通信正常进行。在应用层,协议规定了读取和解读诸多数据和故障代码的方法,如车速、发动机转速、冷却液温度、氧传感器状况等。 OBD-II通信协议的中文版是将该协议的相关规定、参数和方法翻译成中文。这使得非英语国家的技术人员、维修人员和车主能够更好地了解和应用该协议,提高诊断和维修的效率。同时,该中文版也方便了相关研究和教育机构的教学和科研工作。 总之,OBD-II通信协议是一种用于汽车诊断和故障检测的标准化通信协议,通过与车辆内部的电子控制单元进行通信,获取车辆的数据和故障代码。它的中文版翻译使得更多人能够理解和应用该协议,促进了汽车维修和故障诊断技术的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值