esp32-C3 CAN接口使用

功能概述

ESP32-C3具有1个CAN控制器支持以下特性:

  • 兼容ISO 11898-1协议(CAN2.0)
  • 支持标准帧(11bit ID)和扩展帧(29bit ID)格式
  • Bit速率从1Kbit/s-1Mbit/s
  • 工作模式:
    • 正常模式
    • 只听模式(不影响总线)
    • 无响应模式(传输期间无需ACK,可方便自检)
  • 64Byte大小的接收BUF
  • 支持接收单/双过滤
  • 支持错误处理

CAN协议关注点

数据帧或远程帧通过仲裁域抢占CAN总线,协议开始为11bit的ID号,其高位在前低位在后,0表示显性位,1表示隐性位,当多个设备同时发送消息时,ID中的显性位0会覆盖隐性位1,因此ID号越小的设备优先级约高,会优先抢占总线。
在这里插入图片描述
比如ID为3、2、1的设备优先级从高到底为:1(0001B)、2(0010B)、3(0011)。
SSR:一直为1(隐性)
RTR:0(显性)-数据帧 1(隐性)-远程帧
IDE:0(显性)-标准帧 1(隐性)-扩展帧
ACK:发送端输出1(隐性),接收端响应0(显性),发送端到响应0(显性),则发送表示成功。
参考文章:https://blog.csdn.net/qq_38880380/article/details/84573821 讲的更加详细。

接收过滤器

ESP32-c3接收过滤器如下图所示,配置包含1个验证代码寄存器和1个验证掩码寄存器,分别为32bit。
在这里插入图片描述
基本过滤原理是: 过滤出与验证代码相同的消息,但不关注验证掩码为1的消息bit位。
例如验证标准帧11位ID:
验证代码: 000 0001 1010
验证掩码: 000 0000 0011
最终过滤: 000 0000 10xx (ID最低2位掩码为1,不关注,只要ID其他位与验证代码相同即可接收)

单过滤器模式

单过滤器模式可过滤:

  • 标准帧的11位ID、RTR位、数据字节1和数据字节2
  • 或扩展帧的29位ID和RTR位
    在这里插入图片描述

双过滤器模式

双过滤器模式可过滤:

  • 标准帧的11位ID、RTR位、数据字节1(仅filter1)
  • 或扩展帧29位ID中的高16位
    在这里插入图片描述

关键函数说明

配置CONFIG_TWAI_ISR_IN_IRAM,并在安装TWAI驱动时设置标志TWAI_ALERT_AND_LOG ,可放置TWAI中断服务程序在内部RAM中。

配置和安装驱动

#include "driver/twai.h"

//安装CAN驱动
esp_err_t twai_driver_install(
		const twai_general_config_t *g_config, //基本配置
		const twai_timing_config_t *t_config, //时序配置
		const twai_filter_config_t *f_config)//过滤器配置
//启动CAN驱动
esp_err_t twai_start(void)
//停用CAN驱动
esp_err_t twai_stop(void)
//卸载CAN驱动
esp_err_t twai_driver_uninstall(void)

结构体说明:

//CAN接口基本配置
twai_general_config_t g_config = {
		.mode = TWAI_MODE_NORMAL , //TWAI_MODE_NORMAL / TWAI_MODE_NO_ACK / TWAI_MODE_LISTEN_ONLY
		.tx_io = 2, //IO号
		.rx_io = 3, //IO号
        .clkout_io = TWAI_IO_UNUSED, //io号,不用为-1
        .bus_off_io = TWAI_IO_UNUSED,//io号,不用为-1
        .tx_queue_len = 5, //发送队列长度,0-禁用发送队列
        .rx_queue_len = 5,//接收队列长度
        .alerts_enabled = TWAI_ALERT_NONE,  //警告标志 TWAI_ALERT_ALL 可开启所有警告
        .clkout_divider = 0,//1 to 14 , 0-不用
        .intr_flags = ESP_INTR_FLAG_LEVEL1}//中断优先级
        
//CAN接口时序配置官方提供了1K to 1Mbps的常用配置
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS(); //TWAI_TIMING_CONFIG_500KBITS()

//过滤器配置
twai_filter_config_t f_config = {
		.acceptance_code = 0, //验证代码
		.acceptance_mask = 0xFFFFFFFF, //验证掩码 0xFFFFFFFF表示全部接收
		.single_filter = true}//true:单过滤器模式 false:双过滤器模式

获取TWAI状态信息

//获取twai状态
esp_err_t twai_get_status_info(twai_status_info_t *status_info)
//返回值:ESP_OK: 成功;ESP_ERR_INVALID_ARG: 参数无效;ESP_ERR_INVALID_STATE:驱动未安装

//状态信息
twai_status_info_t status_info={
		.state=,//TWAI_STATE_STOPPED / TWAI_STATE_RUNNING / TWAI_STATE_BUS_OFF / TWAI_STATE_RECOVERING
		.msgs_to_tx=,//发送队列消息数       
		.msgs_to_rx=,//接收队列消息数    
		.tx_error_counter=, //发送错误计数
		.rx_error_counter=, //接收错误计数
		.tx_failed_count=,  //发送失败计数
		.rx_missed_count=,  //因接收队列满丢失的消息数
		.rx_overrun_count=, //因接收buf(64Byte)满而丢失的消息数
		.arb_lost_count=,   //仲裁失败计数
		.bus_error_count=};//总线错误计数

发送/接收消息

//发送消息到发送队列排队,如发送队列为空则立即发送,为满则等待ticks_to_wait时间
esp_err_t twai_transmit(
		const twai_message_t *message, //消息包
		TickType_t ticks_to_wait)//超时时间
/***********************************************
* 	返回值:
*	ESP_OK:发送成功
*	ESP_ERR_INVALID_ARG:参数无效
*	ESP_ERR_TIMEOUT:等待TX队列时超时
*	ESP_FAIL:TX队列已禁用,且当前正在传输另一条消息
*	ESP_ERR_INVALID_STATE:CAN驱动程序未运行或未安装
*	ESP_ERR_NOT_SUPPORTED:只听模式不支持发送
*************************************************/

//从接收队列接收1个消息,若队列为空,则阻塞
esp_err_t twai_receive(
		twai_message_t *message, //消息包
		TickType_t ticks_to_wait)//超时
/***********************************************
* 	返回值:
*	ESP_OK:接收成功
*	ESP_ERR_INVALID_ARG:参数无效
*	ESP_ERR_TIMEOUT:等待队列时超时
*	ESP_FAIL:TX队列已禁用,且当前正在传输另一条消息
*	ESP_ERR_INVALID_STATE:CAN驱动程序未运行或未安装
*	ESP_ERR_NOT_SUPPORTED:只听模式不支持发送
*************************************************/


//发送/接收消息帧结构
twai_message_t send_message1 = {
		.extd = 1,//0-标准帧; 1-扩展帧
		.rtr = 0,//0-数据帧; 1-远程帧
		.ss = 1, //0-错误重发; 1-单次发送(仲裁或丢失时消息不会被重发),对接收消息无效
		.self = 0,//0-不接收自己发送的消息,1-接收自己发送的消息,对接收消息无效
		.dlc_non_comp = 0,// 0-数据长度不大于8(ISO 11898-1); 1-数据长度大于8(非标);
		.identifier = ID0, //11/29位ID
		.data_length_code = 0, //DLC数据长度4bit位宽
		.data = {0, 0 , 0 , 0 ,0 ,0 ,0 ,0}};//发送数据,对远程帧无效

使用示例

CAN控制器自回环测试

硬件需将2-3脚回环或连接CAN接口转换芯片,程序运行10s,分别发送标准帧、远程帧、扩展帧,并接收打印帧内容。
需注意自回环测试需要配置:twai_general_config_t->mode = TWAI_MODE_NO_ACK;twai_message_t ->self = 1;

#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/twai.h"

#define EXAMPLE_TAG "TWAI Self Test"
#define SENDMSG 0
#define RECEIVEMSG 1
/* --------------------------- Tasks and Functions -------------------------- */

void printf_msg(int flag, twai_message_t *msg) // flag:0-send 1-receive
{
    int j;
    if (flag)
        printf("Receive: ");
    else
        printf("Send   : ");
    if (msg->extd)
        printf("Extended ");
    else
        printf("Standard ");
    if (msg->rtr)
        printf("Remote Frame, ");
    else
        printf("Data  Frame,  ");
    printf("ID: %d    ", msg->identifier);
    if (msg->rtr == 0)
    {
        for (j = 0; j < msg->data_length_code; j++)
        {
            printf("D%d: %d\t", j, msg->data[j]);
        }
        printf("\n");
    }
    else
        printf("\n");
}

static void twai_transmit_task(void *arg)
{
    int i;
    twai_message_t s1 = {
        .extd = 0,                         // 0-标准帧; 1-扩展帧
        .rtr = 0,                          // 0-数据帧; 1-远程帧
        .ss = 1,                           // 0-错误重发; 1-单次发送(仲裁或丢失时消息不会被重发),对接收消息无效
        .self = 1,                         // 0-不接收自己发送的消息,1-接收自己发送的消息,对接收消息无效
        .dlc_non_comp = 0,                 // 0-数据长度不大于8(ISO 11898-1); 1-数据长度大于8(非标);
        .identifier = 60,                  // 11/29位ID
        .data_length_code = 4,             // DLC数据长度4bit位宽
        .data = {0, 0, 0, 0, 0, 0, 0, 0}}; //发送数据,对远程帧无效
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 3; i++) //发送3个标准数据帧
    {
        s1.data[0] = i;
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    s1.rtr = 1;
    s1.data_length_code = 6;
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 1; i++) //发送1个标准远程帧
    {
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    s1.extd = 1;
    s1.rtr = 0;
    s1.data_length_code = 5;
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 3; i++) //发送3个扩展数据帧
    {
        s1.data[0] = i;
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    s1.rtr = 1;
    s1.data_length_code = 3;
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 1; i++) //发送1个扩展远程帧
    {
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    vTaskDelete(NULL);
}

static void twai_receive_task(void *arg)
{
    twai_message_t r1;
    for (int i = 0; i < 8; i++) //发送1个扩展远程帧
    {
        ESP_ERROR_CHECK(twai_receive(&r1, portMAX_DELAY));
        printf_msg(RECEIVEMSG, &r1);
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    // CAN接口基本配置
    twai_general_config_t g_config = {
        .mode = TWAI_MODE_NO_ACK,            // TWAI_MODE_NORMAL / TWAI_MODE_NO_ACK / TWAI_MODE_LISTEN_ONLY
        .tx_io = 2,                          // IO号
        .rx_io = 3,                          // IO号
        .clkout_io = TWAI_IO_UNUSED,         // io号,不用为-1
        .bus_off_io = TWAI_IO_UNUSED,        // io号,不用为-1
        .tx_queue_len = 5,                   //发送队列长度,0-禁用发送队列
        .rx_queue_len = 5,                   //接收队列长度
        .alerts_enabled = TWAI_ALERT_NONE,   //警告标志 TWAI_ALERT_ALL 可开启所有警告
        .clkout_divider = 0,                 // 1 to 14 , 0-不用
        .intr_flags = ESP_INTR_FLAG_LEVEL1}; //中断优先级

    // CAN接口时序配置官方提供了1K to 1Mbps的常用配置
    twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS(); // TWAI_TIMING_CONFIG_500KBITS()

    //过滤器配置
    twai_filter_config_t f_config = {
        .acceptance_code = 0,          //验证代码
        .acceptance_mask = 0xFFFFFFFF, //验证掩码 0xFFFFFFFF表示全部接收
        .single_filter = true};        // true:单过滤器模式 false:双过滤器模式

    ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
    ESP_LOGI(EXAMPLE_TAG, "Driver installed");
    ESP_ERROR_CHECK(twai_start());
    ESP_LOGI(EXAMPLE_TAG, "Driver started");

    xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, 8, NULL, tskNO_AFFINITY);
    xTaskCreatePinnedToCore(twai_transmit_task, "TWAI_tx", 4096, NULL, 9, NULL, tskNO_AFFINITY);

    vTaskDelay(pdMS_TO_TICKS(10000)); //运行10s

    twai_status_info_t status_info;
    twai_get_status_info(&status_info);
    while (status_info.msgs_to_tx != 0)
    {
        ESP_ERROR_CHECK(twai_get_status_info(&status_info));
    }
    ESP_ERROR_CHECK(twai_stop()); // Stop the TWAI Driver
    ESP_LOGI(EXAMPLE_TAG, "Driver stopped");
    ESP_ERROR_CHECK(twai_driver_uninstall());
    ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled");
}

效果:

I (278) TWAI Self Test: Driver installed
I (278) TWAI Self Test: Driver started
Send : Standard Data Frame, ID: 60 D0: 0 D1: 0 D2: 0 D3: 0
Send : Standard Data Frame, ID: 60 D0: 1 D1: 0 D2: 0 D3: 0
Send : Standard Data Frame, ID: 60 D0: 2 D1: 0 D2: 0 D3: 0
Receive: Standard Data Frame, ID: 60 D0: 0 D1: 0 D2: 0 D3: 0
Receive: Standard Data Frame, ID: 60 D0: 1 D1: 0 D2: 0 D3: 0
Receive: Standard Data Frame, ID: 60 D0: 2 D1: 0 D2: 0 D3: 0
Send : Standard Remote Frame, ID: 60
Receive: Standard Remote Frame, ID: 60
Send : Extended Data Frame, ID: 60 D0: 0 D1: 0 D2: 0 D3: 0 D4: 0
Send : Extended Data Frame, ID: 60 D0: 1 D1: 0 D2: 0 D3: 0 D4: 0
Send : Extended Data Frame, ID: 60 D0: 2 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Data Frame, ID: 60 D0: 0 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Data Frame, ID: 60 D0: 1 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Data Frame, ID: 60 D0: 2 D1: 0 D2: 0 D3: 0 D4: 0
Send : Extended Remote Frame, ID: 60
Receive: Extended Remote Frame, ID: 60
I (10278) TWAI Self Test: Driver stopped
I (10278) TWAI Self Test: Driver uninstalled

CAN收发带过滤测试

收发测试至少有2个CAN终端,本次测试采用ESP32-C3作为master,ESP32作为slave,master分别发送ID号为0x55b和0x55e的消息包,slave设置过滤器,只接收ID为0x55e的扩展帧,并将数据做处理后以0xcc的ID发送到主机。
需要注意的是,正常收发数据需配置: twai_general_config_t->.mode = TWAI_MODE_NORMAL; 和 twai_message_t->self = 0; 另外使用过滤器注意移位。

主机代码:

#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/twai.h"

#define EXAMPLE_TAG "TWAI master"
#define SENDMSG 0
#define RECEIVEMSG 1
/* --------------------------- Tasks and Functions -------------------------- */

void printf_msg(int flag, twai_message_t *msg) // flag:0-send 1-receive
{
    int j;
    if (flag)
        printf("Receive: ");
    else
        printf("Send   : ");
    if (msg->extd)
        printf("Extended ");
    else
        printf("Standard ");
    if (msg->rtr)
        printf("Remote Frame, ");
    else
        printf("Data  Frame,  ");
    printf("ID: 0x%x    ", msg->identifier);
    if (msg->rtr == 0)
    {
        for (j = 0; j < msg->data_length_code; j++)
        {
            printf("D%d: %d\t", j, msg->data[j]);
        }
        printf("\n");
    }
    else
        printf("\n");
}

static void twai_transmit_task(void *arg)
{
    int i;
    twai_message_t s1 = {
        .extd = 0,                         // 0-标准帧; 1-扩展帧
        .rtr = 0,                          // 0-数据帧; 1-远程帧
        .ss = 1,                           // 0-错误重发; 1-单次发送(仲裁或丢失时消息不会被重发),对接收消息无效
        .self = 0,                         // 0-不接收自己发送的消息,1-接收自己发送的消息,对接收消息无效
        .dlc_non_comp = 0,                 // 0-数据长度不大于8(ISO 11898-1); 1-数据长度大于8(非标);
        .identifier = 0x55b,                  // 11/29位ID
        .data_length_code = 4,             // DLC数据长度4bit位宽
        .data = {0, 0, 0, 0, 0, 0, 0, 0}}; //发送数据,对远程帧无效
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 3; i++) //发送3个标准数据帧
    {
        s1.data[0] = i;
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    s1.rtr = 1;
    s1.data_length_code = 6;
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 1; i++) //发送1个标准远程帧
    {
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    s1.extd = 1;
    s1.rtr = 0;
    s1.identifier = 0x55e;
    s1.data_length_code = 5;
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 3; i++) //发送3个扩展数据帧
    {
        s1.data[0] = i;
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    s1.rtr = 1;
    s1.data_length_code = 3;
    vTaskDelay(pdMS_TO_TICKS(1000));
    for (i = 0; i < 1; i++) //发送1个扩展远程帧
    {
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
        printf_msg(SENDMSG, &s1);
    }

    vTaskDelete(NULL);
}

static void twai_receive_task(void *arg)
{
    twai_message_t r1;
    for (int i = 0; i < 8; i++) //发送1个扩展远程帧
    {
        ESP_ERROR_CHECK(twai_receive(&r1, portMAX_DELAY));
        printf_msg(RECEIVEMSG, &r1);
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    // CAN接口基本配置
    twai_general_config_t g_config = {
        .mode = TWAI_MODE_NORMAL,            // TWAI_MODE_NORMAL / TWAI_MODE_NO_ACK / TWAI_MODE_LISTEN_ONLY
        .tx_io = 2,                          // IO号
        .rx_io = 3,                          // IO号
        .clkout_io = TWAI_IO_UNUSED,         // io号,不用为-1
        .bus_off_io = TWAI_IO_UNUSED,        // io号,不用为-1
        .tx_queue_len = 5,                   //发送队列长度,0-禁用发送队列
        .rx_queue_len = 5,                   //接收队列长度
        .alerts_enabled = TWAI_ALERT_NONE,   //警告标志 TWAI_ALERT_ALL 可开启所有警告
        .clkout_divider = 0,                 // 1 to 14 , 0-不用
        .intr_flags = ESP_INTR_FLAG_LEVEL1}; //中断优先级

    // CAN接口时序配置官方提供了1K to 1Mbps的常用配置
    twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS(); // TWAI_TIMING_CONFIG_500KBITS()

    //过滤器配置
    twai_filter_config_t f_config = {
        .acceptance_code = 0,          //验证代码
        .acceptance_mask = 0xFFFFFFFF, //验证掩码 0xFFFFFFFF表示全部接收
        .single_filter = true};        // true:单过滤器模式 false:双过滤器模式

    ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
    ESP_LOGI(EXAMPLE_TAG, "Driver installed");
    ESP_ERROR_CHECK(twai_start());
    ESP_LOGI(EXAMPLE_TAG, "Driver started");

    xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, 8, NULL, tskNO_AFFINITY);
    xTaskCreatePinnedToCore(twai_transmit_task, "TWAI_tx", 4096, NULL, 9, NULL, tskNO_AFFINITY);

    vTaskDelay(pdMS_TO_TICKS(10000)); //运行10s

    twai_status_info_t status_info;
    twai_get_status_info(&status_info);
    while (status_info.msgs_to_tx != 0)
    {
        ESP_ERROR_CHECK(twai_get_status_info(&status_info));
    }
    ESP_ERROR_CHECK(twai_stop()); // Stop the TWAI Driver
    ESP_LOGI(EXAMPLE_TAG, "Driver stopped");
    ESP_ERROR_CHECK(twai_driver_uninstall());
    ESP_LOGI(EXAMPLE_TAG, "Driver uninstalled");
}

从机代码:

#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "driver/twai.h"

#define EXAMPLE_TAG "TWAI slave"
#define SENDMSG 0
#define RECEIVEMSG 1
/* --------------------------- Tasks and Functions -------------------------- */

void printf_msg(int flag, twai_message_t *msg) // flag:0-send 1-receive
{
    int j;
    if (flag)
        printf("Receive: ");
    else
        printf("Send   : ");
    if (msg->extd)
        printf("Extended ");
    else
        printf("Standard ");
    if (msg->rtr)
        printf("Remote Frame, ");
    else
        printf("Data  Frame,  ");
    printf("ID: 0x%x    ", msg->identifier);
    if (msg->rtr == 0)
    {
        for (j = 0; j < msg->data_length_code; j++)
        {
            printf("D%d: %d\t", j, msg->data[j]);
        }
        printf("\n");
    }
    else
        printf("\n");
}

static void twai_receive_task(void *arg)
{
    int j;
    twai_message_t s1 = {
        .extd = 0,                         // 0-标准帧; 1-扩展帧
        .rtr = 0,                          // 0-数据帧; 1-远程帧
        .ss = 1,                           // 0-错误重发; 1-单次发送(仲裁或丢失时消息不会被重发),对接收消息无效
        .self = 0,                         // 0-不接收自己发送的消息,1-接收自己发送的消息,对接收消息无效
        .dlc_non_comp = 0,                 // 0-数据长度不大于8(ISO 11898-1); 1-数据长度大于8(非标);
        .identifier = 0xcc,                 // 11/29位ID
        .data_length_code = 4,             // DLC数据长度4bit位宽
        .data = {0, 0, 0, 0, 0, 0, 0, 0}}; //发送数据,对远程帧无效
    twai_message_t r1;
    for (int i = 0; i < 8; i++)
    {
        ESP_ERROR_CHECK(twai_receive(&r1, portMAX_DELAY));
        printf_msg(RECEIVEMSG, &r1);
        s1.extd = r1.extd;
        s1.rtr = r1.rtr;
        s1.data_length_code = r1.data_length_code;
        if (r1.rtr == 0)
        {
            for (j = 0; j < r1.data_length_code; j++)
                s1.data[j] = 255 - r1.data[j]; // 255减去原始数据回传
        }
        ESP_ERROR_CHECK(twai_transmit(&s1, portMAX_DELAY));
    }
    vTaskDelete(NULL);
}

void app_main(void)
{
    // CAN接口基本配置
    twai_general_config_t g_config = {
        .mode = TWAI_MODE_NORMAL,            // TWAI_MODE_NORMAL / TWAI_MODE_NO_ACK / TWAI_MODE_LISTEN_ONLY
        .tx_io = 21,                          // IO号
        .rx_io = 22,                          // IO号
        .clkout_io = TWAI_IO_UNUSED,         // io号,不用为-1
        .bus_off_io = TWAI_IO_UNUSED,        // io号,不用为-1
        .tx_queue_len = 5,                   //发送队列长度,0-禁用发送队列
        .rx_queue_len = 5,                   //接收队列长度
        .alerts_enabled = TWAI_ALERT_NONE,   //警告标志 TWAI_ALERT_ALL 可开启所有警告
        .clkout_divider = 0,                 // 1 to 14 , 0-不用
        .intr_flags = ESP_INTR_FLAG_LEVEL1}; //中断优先级

    // CAN接口时序配置官方提供了1K to 1Mbps的常用配置
    twai_timing_config_t t_config = TWAI_TIMING_CONFIG_1MBITS(); // TWAI_TIMING_CONFIG_500KBITS()

    //过滤器配置
    twai_filter_config_t f_config = {
        .acceptance_code = 0x55e << 3, //验证代码
        .acceptance_mask = 0x00000007, //验证掩码 0xFFFFFFFF表示全部接收 7:不关注低3bit
        .single_filter = true};        // true:单过滤器模式 false:双过滤器模式

    ESP_ERROR_CHECK(twai_driver_install(&g_config, &t_config, &f_config));
    ESP_LOGI(EXAMPLE_TAG, "Driver installed");
    ESP_ERROR_CHECK(twai_start());
    ESP_LOGI(EXAMPLE_TAG, "Driver started");

    xTaskCreatePinnedToCore(twai_receive_task, "TWAI_rx", 4096, NULL, 8, NULL, tskNO_AFFINITY);
}

效果:
主机打印:

I (277) TWAI master: Driver installed
I (277) TWAI master: Driver started
Send : Standard Data Frame, ID: 0x55b D0: 0 D1: 0 D2: 0 D3: 0
Send : Standard Data Frame, ID: 0x55b D0: 1 D1: 0 D2: 0 D3: 0
Send : Standard Data Frame, ID: 0x55b D0: 2 D1: 0 D2: 0 D3: 0
Send : Standard Remote Frame, ID: 0x55b
Send : Extended Data Frame, ID: 0x55e D0: 0 D1: 0 D2: 0 D3: 0 D4: 0
Send : Extended Data Frame, ID: 0x55e D0: 1 D1: 0 D2: 0 D3: 0 D4: 0
Send : Extended Data Frame, ID: 0x55e D0: 2 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Data Frame, ID: 0xcc D0: 255 D1: 255 D2: 255 D3: 255 D4: 255
Receive: Extended Data Frame, ID: 0xcc D0: 254 D1: 255 D2: 255 D3: 255 D4: 255
Receive: Extended Data Frame, ID: 0xcc D0: 253 D1: 255 D2: 255 D3: 255 D4: 255
Send : Extended Remote Frame, ID: 0x55e
Receive: Extended Remote Frame, ID: 0xcc
I (10277) TWAI master: Driver stopped
I (10277) TWAI master: Driver uninstalled

从机打印:

I (308) TWAI slave: Driver installed
I (308) TWAI slave: Driver started
Receive: Extended Data Frame, ID: 0x55e D0: 0 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Data Frame, ID: 0x55e D0: 1 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Data Frame, ID: 0x55e D0: 2 D1: 0 D2: 0 D3: 0 D4: 0
Receive: Extended Remote Frame, ID: 0x55e

可见从机只响应了ID为0x55e的扩展帧。

  • 11
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值