第二十三章 AT32F403A基于V2库 双can通讯

目录

概述

硬件

CAN

软件

初始化    

波特率计算

过滤器

初始化代码

发送数据函数

中断服务函数

测试

最后


概述

         本文主要是使用AT32F403A开发板,基于V2库实现双can通讯功能。

         串口工具使用的Atlink-ez自带的串口功能。

         工程建立、调试工具配置在前面章节有详细介绍。


硬件

        硬件方面使用的是参考官方AT32F437 SURF板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。

    如下图是开发板pcb图,以及硬件资源。(左边上角的就是atlink-ez,用usb线接到pc即可)


        如下为实物图:

 

        本章是双can的通信实验,can是总线型通信所以测试时是把CAN1和CAN2的H和H对接,L和L对接,相关原理图如下。由于板子的硬件设计上can1和iic1冲突,所以通过跳线帽来切。


CAN

         CAN 是 Controller Area Network 的缩写,是 ISO 国际标准化的串行通信协议。在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。

         AT32F403A有两组can,波特率最高可达 1M bit/s,总共有28个过滤器。can的使用不是和串口一样直接对接就可以使用的,而是和485类似,是需要有收发芯片的。


软件

初始化    

         本章使用AT32F403A的两个can口相互发送和接收数据,can1使用的IO是PB8/PB9,can2使用的是PB12/PB13。发送IO都设置为复用推挽输出,接收IO都设置为输入上拉模式。其中can1的PB8/PB9不是默认的IO,所以can1的IO需要重映射到PB8/PB9上面。

         can的使用最主要的就是波特率的计算、ID设置以及过滤器的使用。can简单来说就是在挂载总线下面的设备会对总线上面的帧ID进行对比,符合过滤器的设置,那么就收到fifo里面。

         can的基本参数结构体:

typedef struct

{

  can_mode_type mode_selection;          /*!< specifies the can mode.*/                  

  confirm_state ttc_enable;              /*!< time triggered communication mode enable */  

  confirm_state aebo_enable;             /*!< automatic exit bus-off enable */

  confirm_state aed_enable;              /*!< automatic exit doze mode enable */

  confirm_state prsf_enable;             /*!< prohibit retransmission when sending fails enable */  

  can_msg_discarding_rule_type mdrsel_selection; /*!< message discarding rule select when overflow */       

  can_msg_sending_rule_type mmssr_selection;     /*!< multiple message sending sequence rule */

} can_base_type;

         mode_selection:can工作模式

         ttc_enable:can 时间触发模式

         aebo_enable:自动退出离线功能

         aed_enable:自动退出睡眠功能

         prsf_enable:禁止自动重传

         mdrsel_selection:报文溢出丢弃规则

         mmssr_selection:报文发送优先级

波特率计算

         波特率的参数结构体:

typedef struct

{

  uint16_t baudrate_div;                  /*!< baudrate division,this parameter can be 0x001~0x400.*/                  

  can_rsaw_type rsaw_size;                /*!< resynchronization adjust width */  

  can_bts1_type bts1_size;                /*!< bit time segment 1 */

  can_bts2_type bts2_size;                /*!< bit time segment 2 */

} can_baudrate_type;

         baudrate_div:分频系数

         rsaw_size:can同步跳跃宽度

         bts1_size:can 位段 1 长度

         bts2_size:can 位段 2 长度

         波特率计算公式:boudrate = pclk/(baudrate_div *(1 + bts1_size + bts2_size))

         其中pclk是can1/2所在的总线的时钟,can1/2都是挂载在apb1总线下面的,apb1总线的最大频率是120M,一般常规下也是设置的120M。懂得pclk的之后,就按照公式去设定分频和位段参数就可以了。

         雅特力也已经发布can波特率计算工具,只要输入pclk的时钟以及需要的波特率,即可自动生成对应的参数,然后对应的设置到代码即可。can波特率计算工具

        工具使用如下图:

过滤器

         过滤器的参数结构体:

typedef struct

{

  confirm_state filter_activate_enable;  /*!< enable or disable the filter activate.*/

  can_filter_mode_type filter_mode;      /*!< config the filter mode mask or list.*/ 

  can_filter_fifo_type filter_fifo;      /*!< config the fifo which will be assigned to the filter. */

  uint8_t filter_number;                 /*!< config the filter number, parameter ranges from 0 to 13. */

  can_filter_bit_width_type filter_bit;  /*!< config the filter bit width 16bit or 32bit.*/ 

  uint16_t filter_id_high;               /*!< config the filter identification, for 32-bit configuration

                                              it's high 16 bits, for 16-bit configuration it's first. */ 

  uint16_t filter_id_low;                /*!< config the filter identification, for 32-bit configuration

                                              it's low 16 bits, for 16-bit configuration it's second. */ 

  uint16_t filter_mask_high;             /*!< config the filter mask or identification, according to the filtering mode,

                                              for 32-bit configuration it's high 16 bits, for 16-bit configuration it's first. */

  uint16_t filter_mask_low;              /*!< config the filter mask or identification, according to the filtering mode,

                                              for 32-bit configuration it's low 16 bits, for 16-bit configuration it's second. */

} can_filter_init_type;

         filter_activate_enable:过滤器使能

         filter_mode:过滤器工作模式

         filter_fifo:过滤器使用哪个FIFO

         filter_number:过滤器序号

         filter_bit:过滤器位宽,16/32bit

         filter_id_high:过滤器 ID 高位

         filter_id_low:过滤器 ID 低位

         filter_mask_high:过滤器掩码高位

         filter_mask_low:过滤器掩码低位

         AT32F403A的can一共有28个滤波器,每组can有14个,都是相互独立的,序号均为0-13。最主要的就是对ID和掩码的设定,不同的工作模式和不同的位宽就是不同的效果。首先我们的要明白can数据的ID分为两种,一种是标准ID,是11bit的长度,一种是扩展ID,是29bit的长度,所以当你使用16bit的位宽的时候,那只能用来过滤标准ID的帧。

         过滤器工作模式分为列表模式和掩码模式,在列表模式下,ID必须完全比配才能收到FIFO里面,此模式下,当位宽是32bit的时候,可以过滤两个ID,当位宽是16bit的时候可以过滤4个ID,也就是过滤器掩码用来做为ID。当在掩码模式下时,则掩码部分就起掩码的效果,需要ID与掩码相与起来值和输入帧的ID与掩码相与起来的值一样就可以通过过滤器,也就是掩码为1的位,输入帧的ID要保持和过滤器的ID一致,掩码为0的位,输入帧的ID是随意的,0或者1都可以,所以此模式下,当位宽是32bit的时候,可以过滤1类ID,当位宽是16bit的时候可以过滤2类ID。

         上面是过滤规则,下面是如何对过滤器的ID和掩码进行设置。

        在32bit位宽,掩码模式下时,ID寄存器的3-31位用来设定ID,掩码寄存器的3-31位用来设置掩码,并且ID寄存器和掩码寄存器都是使用两个16bit的组合的,所以都需要通过移位把对应ID设置进去。IDT是ID的类型,0为标准帧ID,1为扩展帧ID。当设置为过滤标准帧ID时,需要IDT为0,然后把11bit的ID左移5个位设置进过滤器的ID的高16位。掩码也一样的设置进掩码寄存器即可。当设置为过滤扩展帧ID时,需要IDT为1,然后把29bit的扩展ID先左移3个位然后再右移16个位,这样就取到了扩展ID的高16位,然后设置进过滤器的ID的高16位,最后29bit左移3位,再取低16位的,这16bit里面就包含了剩下的13个bit的扩展ID,并且已经左移了,然后设置进过滤器ID的低16bit。掩码也一样的设置进掩码寄存器即可。 

         在32bit位宽,列表模式下时,和掩码的设置也是类似的,只是把掩码部分看成一个ID寄存器来使用即可。

         在16bit位宽,掩码模式下时,ID的低16bit用来设置过滤ID,高16bit用来设置掩码;掩码的低16位用来设置另一个过滤ID,高16bit用来设置另一个掩码,IDT直接设置为0。在设置的时候记得移位。

         在16bit位宽,列表模式下时,可以过滤四个标准ID,也就是ID和掩码寄存器都用来做ID,移位设置进去即可。

         本章使用32bit列表模式分别过滤标准ID和扩展ID。

初始化代码

IO:


/*
*can1 IO口初始化
*TX:PB9
*RX:PB8
*重映射IO口
*/

void can1_gpio_config(void)
{
	gpio_init_type gpio_init_struct;

	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);	//开启gpiob时钟
	crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);	//开启复用时钟(需要IO口重映射时使用)
	gpio_pin_remap_config(CAN1_GMUX_0010,TRUE);				//can1 io口重映射到PB8/9

	gpio_default_para_init(&gpio_init_struct);
	/* can tx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;		//推挽输出
	gpio_init_struct.gpio_mode = GPIO_MODE_MUX;					//复用	
	gpio_init_struct.gpio_pins = GPIO_PINS_9;						//PB9
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;					//无上下拉
	gpio_init(GPIOB, &gpio_init_struct);
	/* can rx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;					//输入模式
	gpio_init_struct.gpio_pins = GPIO_PINS_8;						//PB8
	gpio_init_struct.gpio_pull = GPIO_PULL_UP;					//上拉
	gpio_init(GPIOB, &gpio_init_struct);
}

/*
*can2 IO口初始化
*TX:PB13
*RX:PB12
*/

void can2_gpio_config(void)
{
	gpio_init_type gpio_init_struct;

	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

	gpio_default_para_init(&gpio_init_struct);
	/* can tx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;	//推挽输出
	gpio_init_struct.gpio_mode = GPIO_MODE_MUX;				//复用
	gpio_init_struct.gpio_pins = GPIO_PINS_13;				//PB13
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;				//无上下拉
	gpio_init(GPIOB, &gpio_init_struct);
	/* can rx pin */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;				//输入模式
	gpio_init_struct.gpio_pins = GPIO_PINS_12;				//PB8
	gpio_init_struct.gpio_pull = GPIO_PULL_UP;				//上拉
	gpio_init(GPIOB, &gpio_init_struct);
}

 Can


/**
  * can1 配置函数
  * 波特率1M
  * 
  */
void can1_configuration(void)
{
	can_base_type can_base_struct;
	can_baudrate_type can_baudrate_struct;
	can_filter_init_type can_filter_init_struct;

	crm_periph_clock_enable(CRM_CAN1_PERIPH_CLOCK, TRUE);		//开启can1时钟
	/* can base init */
	can_default_para_init(&can_base_struct);
	can_base_struct.mode_selection = CAN_MODE_COMMUNICATE;	//正常通讯模式
	can_base_struct.ttc_enable = FALSE;		//CAN 时间触发模式(时间戳):关闭
	can_base_struct.aebo_enable = TRUE;		//自动退出离线功能:开启
	can_base_struct.aed_enable = TRUE;		//自动退出睡眠功能:开启
	can_base_struct.prsf_enable = FALSE;		// 禁止自动重传:关闭
	can_base_struct.mdrsel_selection = CAN_DISCARDING_FIRST_RECEIVED;	//报文溢出丢弃规则丢弃之前收到的报文,保留新收到的报文
	can_base_struct.mmssr_selection = CAN_SENDING_BY_ID;	//报文发送优先级:根据 ID(ID 小的先发送) 
	can_base_init(CAN1, &can_base_struct);

	/* can baudrate, set baudrate = pclk/(baudrate_div *(1 + bts1_size + bts2_size)) */
	can_baudrate_struct.baudrate_div = 15;			//15分频
	can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ;		//CAN 同步跳跃宽度:1Tq 
	can_baudrate_struct.bts1_size = CAN_BTS1_6TQ;		//CAN 位段 1 长度:6Tq 
	can_baudrate_struct.bts2_size = CAN_BTS2_1TQ;		//CAN 位段 2 长度:1Tq
	can_baudrate_set(CAN1, &can_baudrate_struct);

	/* can filter init */
	can_filter_init_struct.filter_activate_enable = TRUE;				//开启过滤器
	can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_LIST;		//列表模式
	can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0;			//使用FOFI0
	can_filter_init_struct.filter_number = 0;							//0号滤波器
	can_filter_init_struct.filter_bit = CAN_FILTER_32BIT;				//32bit模式
	can_filter_init_struct.filter_id_high = (FILTER_EXT_ID1<<3)>>16&0xFFFF;			//设置过滤过展ID
	can_filter_init_struct.filter_id_low = ((FILTER_EXT_ID1 << 3) & 0xFFFF) | 0x04;
	can_filter_init_struct.filter_mask_high = (FILTER_STD_ID1<<5)&0xFFFF;			//设置过滤标准ID
	can_filter_init_struct.filter_mask_low = 0;
	can_filter_init(CAN1, &can_filter_init_struct);

	/* can interrupt config */
	nvic_irq_enable(CAN1_SE_IRQn, 0x00, 0x00);			//中断优先级配置及使能:CAN1 状态变化/错误中断
	nvic_irq_enable(USBFS_L_CAN1_RX0_IRQn, 0x00, 0x00);	//中断优先级配置及使能:CAN1 FIFO0 接收中断
	can_interrupt_enable(CAN1, CAN_RF0MIEN_INT, TRUE);	//can1 FIFO0 非空中断使能

	/* error interrupt enable */
	can_interrupt_enable(CAN1, CAN_ETRIEN_INT, TRUE);		//错误类型记录中断使能
	can_interrupt_enable(CAN1, CAN_EOIEN_INT, TRUE);		//can1 错误中断使能
}

/**
  * can2 配置函数
  * 波特率1M
  * 
  */

void can2_configuration(void)
{
	can_base_type can_base_struct;
	can_baudrate_type can_baudrate_struct;
	can_filter_init_type can_filter_init_struct;

	crm_periph_clock_enable(CRM_CAN2_PERIPH_CLOCK, TRUE);		//开启can2时钟
	/* can base init */
	can_default_para_init(&can_base_struct);
	can_base_struct.mode_selection = CAN_MODE_COMMUNICATE;	//正常通讯模式
	can_base_struct.ttc_enable = FALSE;		//CAN 时间触发模式(时间戳):关闭
	can_base_struct.aebo_enable = TRUE;		//自动退出离线功能:开启
	can_base_struct.aed_enable = TRUE;		//自动退出睡眠功能:开启
	can_base_struct.prsf_enable = FALSE;	// 禁止自动重传:关闭
	can_base_struct.mdrsel_selection = CAN_DISCARDING_FIRST_RECEIVED;	//报文溢出丢弃规则丢弃之前收到的报文,保留新收到的报文
	can_base_struct.mmssr_selection = CAN_SENDING_BY_ID;	//报文发送优先级:根据 ID(ID 小的先发送) 
	can_base_init(CAN2, &can_base_struct);

	/* can baudrate, set baudrate = pclk/(baudrate_div *(1 + bts1_size + bts2_size)) */
	can_baudrate_struct.baudrate_div = 15;				//15分频
	can_baudrate_struct.rsaw_size = CAN_RSAW_1TQ;		//can 同步跳跃宽度:1Tq 
	can_baudrate_struct.bts1_size = CAN_BTS1_6TQ;		//can 位段 1 长度:6Tq 
	can_baudrate_struct.bts2_size = CAN_BTS2_1TQ;		//can 位段 2 长度:1Tq
	can_baudrate_set(CAN2, &can_baudrate_struct);

	/* can filter init */
	can_filter_init_struct.filter_activate_enable = TRUE;				//开启过滤器
	can_filter_init_struct.filter_mode = CAN_FILTER_MODE_ID_LIST;		//列表模式
	can_filter_init_struct.filter_fifo = CAN_FILTER_FIFO0;			    //使用FOFI0
	can_filter_init_struct.filter_number = 0;							//0号滤波器
	can_filter_init_struct.filter_bit = CAN_FILTER_32BIT;				//32bit模式
	can_filter_init_struct.filter_id_high = (FILTER_EXT_ID2<<3)>>16&0xFFFF;			//设置过滤展ID
	can_filter_init_struct.filter_id_low = ((FILTER_EXT_ID2 << 3) & 0xFFFF) | 0x04;	//扩展帧,第3bit要设置为1.
	can_filter_init_struct.filter_mask_high = (FILTER_STD_ID2<<5)&0xFFFF;			//设置过滤标准ID
	can_filter_init_struct.filter_mask_low = 0;
	can_filter_init(CAN2, &can_filter_init_struct);

	/* can interrupt config */
	nvic_irq_enable(CAN2_SE_IRQn, 0x00, 0x00);			//中断优先级配置及使能:can2 状态变化/错误中断
	nvic_irq_enable(CAN2_RX0_IRQn, 0x00, 0x00);			//中断优先级配置及使能:can2 FIFO0 接收中断
	can_interrupt_enable(CAN2, CAN_RF0MIEN_INT, TRUE);	//can2 FIFO0 非空中断使能

	/* error interrupt enable */
	can_interrupt_enable(CAN2, CAN_ETRIEN_INT, TRUE);		//错误类型记录中断使能
	can_interrupt_enable(CAN2, CAN_EOIEN_INT, TRUE);		//can2 错误中断使能
}

发送数据函数


/**
  *  can1发送数据函数
  *  标准ID
  *  
  */
void can1_transmit_data_sid(void)
{
	uint8_t transmit_mailbox;
	can_tx_message_type tx_message_struct;
	tx_message_struct.standard_id = FILTER_STD_ID2;		//ID值
	tx_message_struct.extended_id = 01;
	tx_message_struct.id_type = CAN_ID_STANDARD;		//标准ID类型
	tx_message_struct.frame_type = CAN_TFT_DATA;		//数据帧
	tx_message_struct.dlc = 8;
	tx_message_struct.data[0] = 0x10;		//数据
	tx_message_struct.data[1] = 0x11;
	tx_message_struct.data[2] = 0x12;
	tx_message_struct.data[3] = 0x13;
	tx_message_struct.data[4] = 0x14;
	tx_message_struct.data[5] = 0x15;
	tx_message_struct.data[6] = 0x16;
	tx_message_struct.data[7] = 0x17;
	transmit_mailbox = can_message_transmit(CAN1, &tx_message_struct);
	while(can_transmit_status_get(CAN1, (can_tx_mailbox_num_type)transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL);
	
}

/**
  *  can1发送数据函数
  *  扩展ID
  *  
  */
void can1_transmit_data_eid(void)
{
	uint8_t transmit_mailbox;
	can_tx_message_type tx_message_struct;
	tx_message_struct.standard_id = 02;
	tx_message_struct.extended_id = 0x18F5F200;		//ID值
	tx_message_struct.id_type = CAN_ID_EXTENDED;		//扩展ID
	tx_message_struct.frame_type = CAN_TFT_DATA;		//数据帧
	tx_message_struct.dlc = 8;							//数据长度
	tx_message_struct.data[0] = 0x18;		//数据
	tx_message_struct.data[1] = 0x19;
	tx_message_struct.data[2] = 0x1A;
	tx_message_struct.data[3] = 0x1B;
	tx_message_struct.data[4] = 0x1C;
	tx_message_struct.data[5] = 0x1D;
	tx_message_struct.data[6] = 0x1E;
	tx_message_struct.data[7] = 0x1F;
	transmit_mailbox = can_message_transmit(CAN1, &tx_message_struct);
	while(can_transmit_status_get(CAN1, (can_tx_mailbox_num_type)transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL);
	
}

/**
  *  can1发送数据函数
  *  标准ID
  *  
  */

void can2_transmit_data_sid(void)
{
	uint8_t transmit_mailbox;
	can_tx_message_type tx_message_struct;
	tx_message_struct.standard_id = FILTER_STD_ID1;		//ID值
	tx_message_struct.extended_id = 03;
	tx_message_struct.id_type = CAN_ID_STANDARD;		//标准ID
	tx_message_struct.frame_type = CAN_TFT_DATA;		//数据帧
	tx_message_struct.dlc = 8;							//数据长度
	tx_message_struct.data[0] = 0x20;		//数据
	tx_message_struct.data[1] = 0x21;
	tx_message_struct.data[2] = 0x22;
	tx_message_struct.data[3] = 0x23;
	tx_message_struct.data[4] = 0x24;
	tx_message_struct.data[5] = 0x25;
	tx_message_struct.data[6] = 0x26;
	tx_message_struct.data[7] = 0x27;
	transmit_mailbox = can_message_transmit(CAN2, &tx_message_struct);
	while(can_transmit_status_get(CAN2, (can_tx_mailbox_num_type)transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL);
}

/**
  *  can2发送数据函数
  *  扩展ID
  *  
  */
void can2_transmit_data_eid(void)
{
	uint8_t transmit_mailbox;
	can_tx_message_type tx_message_struct;
	tx_message_struct.standard_id = 04;		
	tx_message_struct.extended_id = FILTER_EXT_ID1;		//ID值
	tx_message_struct.id_type = CAN_ID_EXTENDED;		//扩展ID
	tx_message_struct.frame_type = CAN_TFT_DATA;		//数据帧
	tx_message_struct.dlc = 8;							//数据长度
	tx_message_struct.data[0] = 0x28;		//数据
	tx_message_struct.data[1] = 0x29;
	tx_message_struct.data[2] = 0x2A;
	tx_message_struct.data[3] = 0x2B;
	tx_message_struct.data[4] = 0x2C;
	tx_message_struct.data[5] = 0x2D;
	tx_message_struct.data[6] = 0x2E;
	tx_message_struct.data[7] = 0x2F;
	transmit_mailbox = can_message_transmit(CAN2, &tx_message_struct);
	while(can_transmit_status_get(CAN2, (can_tx_mailbox_num_type)transmit_mailbox) != CAN_TX_STATUS_SUCCESSFUL);
}

中断服务函数

/**
  *  @brief  can1 interrupt function rx0
  *  @param  none
  *  @retval none
  */
void USBFS_L_CAN1_RX0_IRQHandler (void)
{
	u8 i=0;
	can_rx_message_type rx_message_struct;
	if(can_flag_get(CAN1,CAN_RF0MN_FLAG) != RESET)
	{
		can_message_receive(CAN1, CAN_RX_FIFO0, &rx_message_struct);
		printf("can1 rx data \r\n");
		printf("rx_message_struct.standard_id:%02x \r\n",rx_message_struct.standard_id);
		printf("rx_message_struct.extended_id:%02x \r\n",rx_message_struct.extended_id);
		if(rx_message_struct.standard_id == FILTER_STD_ID1||rx_message_struct.extended_id==FILTER_EXT_ID1)
		{
			printf("rx data:\r\n");
			for(i=0;i<8;i++)
			{
				 printf("%02x ",rx_message_struct.data[i]);
			}
			 printf("\r\n");
		}	
	}
}

 void CAN2_RX0_IRQHandler (void)
{
	u8 i=0;
	can_rx_message_type rx_message_struct;
	if(can_flag_get(CAN2,CAN_RF0MN_FLAG) != RESET)
	{
		can_message_receive(CAN2, CAN_RX_FIFO0, &rx_message_struct);
		printf("can2 rx data\r\n");
		printf("rx_message_struct.standard_id:%02x \r\n",rx_message_struct.standard_id);
		printf("rx_message_struct.extended_id:%02x \r\n",rx_message_struct.extended_id);
		if(rx_message_struct.standard_id == FILTER_STD_ID2||rx_message_struct.extended_id==FILTER_EXT_ID2)
		{
			printf("rx data:\r\n");
			for(i=0;i<8;i++)
			 {
				 printf("%02x ",rx_message_struct.data[i]);
			 }
			 printf("\r\n");
		}
	}
}


测试

         测试代码

         通过发送不同ID的数据帧,接收中断中都添加对应的log,会把收到FIFO中的帧的ID以及数据打印出来。

         测试结果

         设的ID 都通过了,数据也都是对上了。


最后

         有问题的可以加QQ群技术交流,同时相关代码上传到QQ群中。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值