【RA6M3 HMI Board评测挑战】-瑞萨RA6M3上的CAN实践

电子说

1.3w人已加入

描述

一.准备
基于RT-Thread Studio

1.1安装BSP包
GNU

注意GNU工具链版本
GNU

1.2 芯片资料
1.3FSP
1.4代码仓库

1.5创建工程
菜单栏
文件->新建->RT-Thread项目
设置如下
GNU

GNU

接上串口P205 P206
115200-8-N-1
GNU

二.CAN模块硬件部分介绍
GNU

TP5设置了一个测试点,可以测试Vref的VDD/2的电压,辅助确认芯片是否正常。

R76 R77构成了120欧终端电阻,C67起到滤波作用,这个电容不能大,否则影响高速时信号边沿,导致边沿变迟缓可能导致采样错误。

RS用于Slope-Control控制输入,默认接GND即High-Speed模式。

GNU

三.CAN模块介绍
参考《Renesas RA6M3 Group User’s Manual: Hardware》的《37. Controller Area Network (CAN) Module》

3.1特征
支持ISO11898-1 标准和扩展帧
支持最高1 Mbps
32个消息邮箱:每一个都可以独立配置为接收或发送;或者24个配置为接受或发送,剩余的8个配置为4级收发FIFO。
支持数据帧和远程帧接收,可配置只接收标准帧或者扩展帧或者混合帧,可配置单次接收模式,可配置溢出时数据是保存还是丢弃,每个邮箱可单独配置接收完成中断使能。
4个邮箱共用一个,一共8个接收过滤器,每个邮箱可单独使能过滤。
支持数据帧和远程帧发送,可配置只发送标准帧或者扩展帧或者混合帧,可配置单次发送模式,广播功能,优先级可由ID或者邮箱序号决定,支持发送中止且有中止完成标志,每个邮箱可单独配置接发送成中断使能。
从总线断开状态恢复的模式转换可选择为:1.符合ISO11898-1规范2.总线断开进入时自动进入CAN停止模式3.总线断开完成时自动进入CAN停止模式4.通过软件进入CAN停止模式5.通过软件转换到错误活动状态。
监控CAN总线错误,包括填充错误、格式错误、ACK错误、15位CRC错误、位错误和ACK分隔符错误。检测到错误状态的转换,包括错误警告、被动错误、总线关闭进入和总线关闭恢复。支持读取错误计数器。
使用16位计数器的时间戳功能,可选择1位、2位、4位和8位时间周期的参考时钟
支持五种中断源:接收完成、发送完成、接收FIFO、发送FIFO和错误中断。
停止CAN时钟以降低功耗。
三个软件支持单元:接收过滤器;邮箱搜索支持,包括接收邮箱搜索、发送邮箱搜索和邮件丢失搜索;通道搜索支持。
时钟源来自PCLKB 或 CANMCLK
可用于评估的三种测试模式:仅听模式;自检模式0(外部环回);自检模式1(内部环回)。
可以设置模块停止状态以降低功耗.

3.2框图
GNU

3.3操作模式
CAN模块的操作模式包括:CAN复位模式,CAN停止模式,CAN操作模式,CAN睡眠模式。状态切换如下图:
GNU

3.4时序设置
时序设置很重要
时钟源
CAN模块有一个CAN时钟发生器,可通过BCR寄存器中的CCLKS和BRP[9:0]位进行设置。图显示了CAN时钟发生器的框图
CCLKS选择时钟源来自与PCLKB还是EXTAL
BPR设置时钟分频最后得到fCANCLK
GNU

3.5时序设置
GNU

GNU

3.6中断
GNU

四.CAN驱动介绍
4.1添加CAN驱动
按如下设置并保存,也可以使用env设置
GNU

添加的代码位置如下
GNU

4.2使能硬件CAN
右键点击工程,打开env环境
GNU

GNU

GNU

GNU

GNU

4.3测试代码
CANboardSConscript下添加

if GetDepend(['RT_USING_CAN']):
src += Glob('ports/can_test.c')
刷新scons配置
GNU

添加的测试代码如下
GNU

该代码使用can0,创建接收线程接收can数据,接收到后打印信息,同时导出命令can_sample,执行一次命令发送一帧CAN数据。

五.回环测试
rt_device_open后添加一行,设置为回环模式
rt_device_control(can_dev,RT_CAN_CMD_SET_MODE,RT_CAN_MODE_LOOPBACK);

编译运行,help可以看到对应的命令can_sample
GNU

六.问题
can_sample can0
只能执行一次
GNU

static rt_device_t can_dev = NULL;

设置只有未初始化才初始化

if(can_dev == NULL)
{
    if (argc == 2)
    {
        rt_strncpy(can_name, argv[1], RT_NAME_MAX);
    }
    else
    {
        rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
    }
    can_dev = rt_device_find(can_name);
    if (!can_dev)
    {
        rt_kprintf("find %s failed!n", can_name);
        return RT_ERROR;
    }
    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
    res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
    RT_ASSERT(res == RT_EOK);
    rt_device_control(can_dev,RT_CAN_CMD_SET_MODE,RT_CAN_MODE_LOOPBACK);
    thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        rt_kprintf("create can_rx thread failed!n");
    }

}
这样就可以反复进行can_sample测试

GNU
七.CAN驱动分析
7.1测试代码
boardportscan_test.c
见前面的测试

7.2硬件抽象层
librariesHAL_Driversdrv_can.c drv_can.h
导出了初始化函数,启动时自动根据链接脚本放置的位置调用该函数
INIT_BOARD_EXPORT(rt_hw_can_init);

通过接口
result = rt_hw_can_register(&can_obj[i].can_dev, can_obj[i].config->name, can_obj[i].can_dev.ops, RT_NULL);
注册几个关键的数据结构
重点是如下结构体,即操作底层硬件的接口,驱动层即通过注册的该opt结构进行底层硬件操作

const struct rt_can_ops ra_can_ops =
{
.configure = ra_can_configure,
.control = ra_can_control,
.sendmsg = ra_can_sendmsg,
.recvmsg = ra_can_recvmsg
};
librariesHAL_Driversconfigra2l1can_config.h中的

#if defined(BSP_USING_CAN0)
#ifndef CAN0_CONFIG
#define CAN0_CONFIG
{
.name = "can0",
.num_of_mailboxs = CAN_NO_OF_MAILBOXES_g_can0,
.p_api_ctrl = &g_can0_ctrl,
.p_cfg = &g_can0_cfg,
}
#endif /* CAN0_CONFIG /
#endif /
BSP_USING_CAN0 */
则定义的芯片相关的操作数据结构和设备名字。

7.3组件层
rt-threadcomponentsdriverscancan.c

导出了命令
MSH_CMD_EXPORT_ALIAS(cmd_canstat, canstat, stat can device status);

rt_hw_can_register注册以下接口,即组件设备的驱动API

device- >init        = rt_can_init;
device- >open        = rt_can_open;
device- >close       = rt_can_close;
device- >read        = rt_can_read;
device- >write       = rt_can_write;

device->control = rt_can_control;
7.4设备层
更通用的设备层通过设备名找到设备句柄
rt_device_find

设备打开等操作时rt_device_open通过设备句柄调用组件层的API,

rt_can_open等,而组件层调用硬件抽象层的接口,硬件抽象层再调用IC的固件库实现硬件操作。

八.总结
得益于RT_Thread比较好的设备驱动框架,设备驱动的扩展非常方便,直接配置IC固件库,实现硬件抽象层即可,组件层和设备层驱动都是通用的。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分