1143|2

2885

帖子

4

TA的资源

五彩晶圆(中级)

楼主
 

【瑞萨RA6E2评估板】CAN FD功能和通讯兼容性测试 [复制链接]

CANFD通讯功能是比较高级的功能,RA6E2具有CAN FD通讯功能,而且瑞萨公司还提供了CAN FD的培训教材,本次测试除了使用开发板RA6E2以外还,还使用了米尔STM32MP135开发板,通过两块板的硬件进行连接,这里CAN FD的引脚不能直接连接,需要PHY TJA1043芯片,这个芯片将TTL信号转换为差分信号。

参考实验教程,首先建立项目CANFD_FSP_Project,

 

项目模板使用FPB_RA6E2,项目类型为Keil项目

增加按钮的IRQ模块,使用按钮来发送数据。

  我在项目中使用uart作为调试输出,所以再增加uart模块。引脚为P410和P411。

  增加uart之后就需要增加CAN FD设置了。初步的设置如下:

  首先不要急着设置CAN FD lite模块,应该设置PIN引脚,P402和P401引脚

  两个引脚都需要设置。然后设置增加CAN FD Lite

 

增加完成后发现出现错误。说明还有其它的设置。然后设置系统时钟。

  按照上面的图来设置。

按照上图设置,这时can fd模块的错误消失了。

项目代码如下:

#include "hal_data.h"
#include <stdio.h>

/* Macro definition */
#define CARRIAGE_ASCII            (13u)     /* Carriage return */
#define ZERO_ASCII                (48u)     /* ASCII value of zero */
#define NINE_ASCII                (57u)     /* ASCII value for nine */
#define DATA_LENGTH               (8u)      /* Expected Input Data length */
#define UART_ERROR_EVENTS         (UART_EVENT_BREAK_DETECT | UART_EVENT_ERR_OVERFLOW | UART_EVENT_ERR_FRAMING | \
                                    UART_EVENT_ERR_PARITY)    /* UART Error event bits mapped in registers */
#define RESET_VALUE               (0x00)

/* Flag for user callback */
static volatile uint8_t g_uart_event = RESET_VALUE;
static uint8_t g_temp_buffer[DATA_LENGTH] = {RESET_VALUE};
/* Counter to update g_temp_buffer index */
static volatile uint8_t g_counter_var = RESET_VALUE;
/* Flag to check whether data is received or not */
static volatile uint8_t g_data_received_flag = false;

void R_BSP_WarmStart(bsp_warm_start_event_t event);

extern bsp_leds_t g_bsp_leds;

static volatile bool g_sw_press;

can_info_t can_rx_info = 
{
	.error_code = 0,
	.error_count_receive = 0,
	.error_count_transmit = 0,
	.rx_fifo_status = 0,
	.rx_mb_status = 0,
	.status = 0,
};

const canfd_afl_entry_t p_canfd0_afl[] =
{
	{
		.id = 
    {
				.id           = 0x40,
			  .frame_type   = CAN_FRAME_TYPE_DATA,
        .id_mode      = CAN_ID_MODE_STANDARD,    			
		},
	  .mask = 
    {
		    .mask_id           = 0x7FE,
        .mask_frame_type   = 0,			
		    .mask_id_mode      = 1, 
		},
	  .destination = 
    {
				.minimum_dlc = CANFD_MINIMUM_DLC_0,
			  .rx_buffer   = CANFD_RX_MB_0,
		},
	}

};

/* Flags to be set in Callback function */
bool b_canfd_tx_complete  = false;
bool b_canfd_rx_complete  = false;
bool b_canfd_err_status = false;

/* CANDFD RX and TX variables */
can_frame_t g_can_tx_frame;
can_frame_t g_can_rx_frame;
can_frame_t g_can_rx_frame_fifo;

uint8_t tx_data[64];

/*******************************************************************************************************************//**
 * [url=home.php?mod=space&uid=159083]@brief[/url] Blinky example application
 *
 * Blinks all leds at a rate of 1 second using the software delay function provided by the BSP.
 *
 **********************************************************************************************************************/
void hal_entry (void)
{
#if BSP_TZ_SECURE_BUILD

    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif

	  fsp_err_t  err = FSP_SUCCESS;
	  size_t buff_len;
	  uint32_t local_timeout = (DATA_LENGTH * UINT16_MAX);
  	unsigned char send_buff[32]="RA Keil Exit\r";
	
    /* Define the units to be used with the software delay function */
    const bsp_delay_units_t bsp_delay_units = BSP_DELAY_UNITS_MILLISECONDS;

    /* Set the blink frequency (must be <= bsp_delay_units */
    const uint32_t freq_in_hz = 2;

    /* Calculate the delay in terms of bsp_delay_units */
    const uint32_t delay = bsp_delay_units / freq_in_hz;

    /* LED type structure */
    bsp_leds_t leds = g_bsp_leds;

    /* If this board has no LEDs then trap here */
    if (0 == leds.led_count)
    {
        while (1)
        {
            ;                          // There are no LEDs on this board
        }
    }

    /* Holds level to set for pins */
    bsp_io_level_t pin_level = BSP_IO_LEVEL_LOW;
		
		err = R_ICU_ExternalIrqOpen(&g_external_irq_ctrl,&g_external_irq_cfg);
		if(FSP_SUCCESS != err) __BKPT();
		
		err = R_ICU_ExternalIrqEnable(&g_external_irq_ctrl);
		if(FSP_SUCCESS != err) __BKPT();
		err = R_SCI_UART_Open(&g_uart0_ctrl, &g_uart0_cfg);
    if(FSP_SUCCESS != err) __BKPT();
		
		buff_len = strlen((char *)send_buff);
		
		err = R_SCI_UART_Write(&g_uart0_ctrl, send_buff, buff_len);
		if(FSP_SUCCESS != err) __BKPT();

    while (1)
    {
        /* Enable access to the PFS registers. If using r_ioport module then register protection is automatically
         * handled. This code uses BSP IO functions to show how it is used.
         */
        R_BSP_PinAccessEnable();

        /* Update all board LEDs */
        for (uint32_t i = 0; i < leds.led_count; i++)
        {
            /* Get pin to toggle */
            uint32_t pin = leds.p_leds[i];

            /* Write to this pin */
            R_BSP_PinWrite((bsp_io_port_pin_t) pin, pin_level);
        }

				err = R_CANFD_InfoGet(&g_canfd0_ctrl,&can_rx_info);
				if(FSP_SUCCESS != err) __BKPT();
				
				if((can_rx_info.rx_mb_status & (1 << 0) ) ==(1 << 0))
				{
						err = R_CANFD_Read(&g_canfd0_ctrl,0,&g_can_rx_frame);
				    if(err != FSP_SUCCESS) __BKPT();
				}
				
				if(g_sw_press)
        {
							err = R_SCI_UART_Write(&g_uart0_ctrl, send_buff, buff_len);
							if(FSP_SUCCESS != err) __BKPT();
		
							while ((UART_EVENT_TX_COMPLETE != g_uart_event) && (--local_timeout))
							{
									/* Check if any error event occurred */
									if (UART_ERROR_EVENTS == g_uart_event)
									{
											break;
									}
							}
							
							err = FSP_SUCCESS;
							for(uint16_t i = 0; i< DATA_LENGTH;i++)
              {
									tx_data[i] = (uint8_t) (i + 1);
							}
							memcpy((uint8_t *)&g_can_tx_frame.data[0],(uint8_t *)&tx_data[0],DATA_LENGTH);
							g_can_tx_frame.id                  = 0x40;
							g_can_tx_frame.id_mode             = CAN_ID_MODE_STANDARD;
              g_can_tx_frame.type                = CAN_FRAME_TYPE_DATA;
              g_can_tx_frame.data_length_code    = 8;
							g_can_tx_frame.options             = 0;
							
							/* Write some data to the transmit frame */
							err = R_CANFD_Write(&g_canfd0_ctrl,0,&g_can_tx_frame);
							
							/* Handle error*/
							if(FSP_SUCCESS != err) __BKPT();
							
							g_sw_press = false;	
				}
				
        /* Protect PFS registers */
        R_BSP_PinAccessDisable();

        /* Toggle level for next write */
        if (BSP_IO_LEVEL_LOW == pin_level)
        {
            pin_level = BSP_IO_LEVEL_HIGH;
        }
        else
        {
            pin_level = BSP_IO_LEVEL_LOW;
        }

        /* Delay */
        R_BSP_SoftwareDelay(delay, bsp_delay_units);
    }
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart (bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        IOPORT_CFG_OPEN(&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
    }
}

void user_irq_callback(external_irq_callback_args_t * p_args)
{

		if(p_args->channel == 9)
    {
			g_sw_press = true;
		}
}

void user_uart_callback(uart_callback_args_t * p_args)
{

/* Logged the event in global variable */
    g_uart_event = (uint8_t)p_args->event;

    /* Reset g_temp_buffer index if it exceeds than buffer size */
    if(DATA_LENGTH == g_counter_var)
    {
        g_counter_var = RESET_VALUE;
    }

    if(UART_EVENT_RX_CHAR == p_args->event)
    {
        switch (p_args->data)
        {
            /* If Enter is pressed by user, set flag to process the data */
            case CARRIAGE_ASCII:
            {
                g_counter_var = RESET_VALUE;
                g_data_received_flag  = true;
                break;
            }
            /* Read all data provided by user until enter button is pressed */
            default:
            {
                g_temp_buffer[g_counter_var++] = (uint8_t ) p_args->data;
                break;
            }
        }
    }
}

/* Callback function */
void canfd0_callback(can_callback_args_t *p_args)
{
    /* TODO: add your own code here */
    switch(p_args->event)
    {
			case CAN_EVENT_TX_COMPLETE:
			{
				  b_canfd_tx_complete = true;
				  break;
			}
		  case CAN_EVENT_RX_COMPLETE:
			{
			    b_canfd_rx_complete = true;
				  break;
			}	
			case CAN_EVENT_ERR_WARNING:
			case CAN_EVENT_ERR_PASSIVE:
			case CAN_EVENT_ERR_BUS_OFF:         	
			case CAN_EVENT_BUS_RECOVERY:        	
			case CAN_EVENT_MAILBOX_MESSAGE_LOST:
			case CAN_EVENT_ERR_BUS_LOCK:        	
			case CAN_EVENT_ERR_CHANNEL:         	
			case CAN_EVENT_TX_ABORTED:          	
			case CAN_EVENT_ERR_GLOBAL:          	
			case CAN_EVENT_FIFO_MESSAGE_LOST:   	
      case CAN_EVENT_TX_FIFO_EMPTY:
      {
			    b_canfd_err_status = true;
				  break;
			}				
		}
}

这里需要重点关照的内容如下:

const canfd_afl_entry_t p_canfd0_afl[] =
{
	{
		.id = 
    {
				.id           = 0x40,
			  .frame_type   = CAN_FRAME_TYPE_DATA,
        .id_mode      = CAN_ID_MODE_STANDARD,    			
		},
	  .mask = 
    {
		    .mask_id           = 0x7FE,
        .mask_frame_type   = 0,			
		    .mask_id_mode      = 1, 
		},
	  .destination = 
    {
				.minimum_dlc = CANFD_MINIMUM_DLC_0,
			  .rx_buffer   = CANFD_RX_MB_0,
		},
	}

};

canfd_afl_entry_t 结构中的ID设置为0x40,十进制为64。这个为CAN中的包过滤地址,最开始我就是没有理解该地址,使得通讯只能引起中断,结果数据无法接收。

 

这个结构是用来设置AFLT(地址过滤表)的,这里只是用了一个地址,(需要注意:芯片可以支持多个地址的。)发送数据代码如下,

	if(g_sw_press)
	{
			err = R_SCI_UART_Write(&g_uart0_ctrl, send_buff, buff_len);
			if(FSP_SUCCESS != err) __BKPT();

			while ((UART_EVENT_TX_COMPLETE != g_uart_event) && (--local_timeout))
			{
					/* Check if any error event occurred */
					if (UART_ERROR_EVENTS == g_uart_event)
					{
							break;
					}
			}
			
			err = FSP_SUCCESS;
			for(uint16_t i = 0; i< DATA_LENGTH;i++)
			{
					tx_data[i] = (uint8_t) (i + 1);
			}
			memcpy((uint8_t *)&g_can_tx_frame.data[0],(uint8_t *)&tx_data[0],DATA_LENGTH);
			g_can_tx_frame.id                  = 0x64;
			g_can_tx_frame.id_mode             = CAN_ID_MODE_STANDARD;
			g_can_tx_frame.type                = CAN_FRAME_TYPE_DATA;
			g_can_tx_frame.data_length_code    = 8;
			g_can_tx_frame.options             = 0;
			
			/* Write some data to the transmit frame */
			err = R_CANFD_Write(&g_canfd0_ctrl,0,&g_can_tx_frame);
			
			/* Handle error*/
			if(FSP_SUCCESS != err) __BKPT();
			
			g_sw_press = false;	
	}

这里我没有按照实验教材中将代码放到IRQ按钮中断里,而是放到了主循环里。这一点需要注意,还有就是地址,我的为100,十六进制0x64,因为我的STM32MP135开发板为100地址。因为没有发现如何修改这个地址。所以只能为100了。

 

程序写完后开始运行。

启动linux开发板,使用如下代码初始化。

  参考STM32MP135的测试连接 STM32MP135测试

cansend can0 64#11.22.33.44

发出命令后发现RA6E2开发板的中断有了反应

说数据接收成功。

 

 

最新回复

CAN FD的实验要求的测试环境还是挺高级的。   详情 回复 发表于 2023-11-14 09:14
点赞 关注

回复
举报

6842

帖子

11

TA的资源

版主

沙发
 

米尔的封装了收发芯片,用起来比较方便。大佬米尔的粉丝呀!

 
 

回复

116

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

CAN FD的实验要求的测试环境还是挺高级的。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表