CAN协议学习(二)MCAN控制器介绍
更多细节请参看MCAN2文档mcan2_ps.pdf。
一、MCAN2简介
MCAN2是Mentor公司开发的一个CAN2.0网络控制器的软核,初版2001年末版2006年。MCAN 2控制器实现了BOSCAN消息传输协议2.0a和2.0b。规范2.0a(相当于can 1.2)涵盖标准消息格式(11位标识符);规范2.0b涵盖标准和扩展消息格式(11位和29位标识符)。
二、总体架构
下图显示了MCAN2设计的主要功能块。

CPU对mcan 2的访问是通过独立的地址、输入数据和输出数据总线进行的。由主机设备将用于传输的消息放置到发送缓冲器中,以便由位处理器进行传输。设备接收到的消息首先由接收过滤器过滤,然后放入接收FIFO中。
CPU通过称为接收缓冲区的13字节窗口访问接收FIFO.结合接收FIFO使用接收缓冲区允许CPU在接收其他消息时处理一条消息。接收FIFO的总长度为64个字节,并以循环方式使用,使其能够同时容纳最多5个扩展的帧格式消息。
位定时逻辑块负责设备的波特率,并且是可编程的。所支持的波特率范围取决于主系统时钟XTAL1的频率,并且可以容易地跨越比BOSCH规范所选择的125kbud-1MBaud更宽的波特率范围。
CAN总线的接口由发送信号tx0、tx1和接收的rx 0提供。TX1通常与tx0相反,也可以编程为输出发送时钟,这对于测试非常有用。
三、发送、接收过程
要传输的数据以标准帧格式(SFF)或扩展帧格式(EFF)写入mcan 2的发送缓冲器(如下)。发送缓冲器包括CAN地址10h和1ch之间的13个字节,一个帧最多可以发送8个字节的数据。注意:在将数据写入缓冲区之前,需要检查传输缓冲区状态(状态寄存器,位2),以确保缓冲区“释放”(SR.2=‘1’)。当缓冲区被锁定时写入缓冲区的任何数据(SR.2=‘0’)都会丢失而没有任何指示。

发送缓冲器描述符字段的位布局如下所示.

FF代表frame format:0为标准帧,1为拓展帧。
RTR代表REMOTE TRANSMISSION REQUEST:1表示为远程帧。
DLC代表DATA LENGTH CODE:范围0-8,大于8的数被自动解释为8。
ID代表IDENTIFIER:标识符充当消息的名称,用于接收过滤,并确定总线访问优先级。标识符的二进制值越低,优先级就越高。在标准帧格式(SFF)中,标识符由11位(id.28至id.18)组成。在扩展帧格式(Eff)消息中,标识符由29位(id.28到id.0)组成。id.28是最高位,首先在总线上传输。
mcan 2接收的数据首先由接收滤波器过滤,然后传递给接收FIFO。接受过滤器只传递那些具有与接收过滤器寄存器中记录的消息相匹配的标识位的消息。
接收FIFO有64个字节深,允许最多5个完整扩展帧格式(EFF)消息的空间,并以循环方式使用。
放置在接收FIFO中的数据通过一个称为接收缓冲区的13字节窗口读取。该窗口位于can地址10h-1ch,即它占用与发送缓冲器相同的地址空间。与传输缓冲区一样,它足够宽,可以容纳一条包含最多8个字节数据的消息。

四、信号&寄存器描述
信号描述:


寄存器描述:

五、接收过滤
与过滤相关的寄存器:
10h-13h ACR0–3 Acceptance Code Registers 0-3
14h-17h AMR0–3 Acceptance Mask Registers 0-3
MCAN2的接收过滤模块首先将接收到的数据帧的ID部分与ACR即接收码寄存器比较,如果一致则接收,如果不一致则丢弃;AMR是接收掩码寄存器,如果某位设为‘1’,则将ACR对应的位设为‘不关心’。根据MOD.3为0或1来设置单过滤或双过滤模式,具体如下图。

六、时序图

七、测试程序(流程图&代码)


//test CAN 2019.03.22 by zhou
assign F_can_rx[]=(F_can_tx[]=='b1)?F_can_tx[0]:((F_can_tx[0]==1'b1)?F_can_tx[]:'bZ); //star
assign F_can_rx[]=(F_can_tx[]=='b1)?F_can_tx[3]:((F_can_tx[3]==1'b1)?F_can_tx[]:'bZ); //earth
assign F_can_rx[]=(F_can_tx[]=='b1)?F_can_tx[1]:((F_can_tx[1]==1'b1)?F_can_tx[]:'bZ); //star
assign F_can_rx[]=(F_can_tx[]=='b1)?F_can_tx[2]:((F_can_tx[2]==1'b1)?F_can_tx[]:'bZ); //earth
task CPU_READ_NPT; //just read data, no display
input [:] addr;
output [:] rddata;
begin
#120ns
@(posedge S_cpu_clk)
F_nrd = 'b1;
F_nwr = 'b1;
F_ncs = 'b1;
F_addr =addr;
@(posedge S_cpu_clk)
F_nrd = 'b0;
F_nwr = 'b1;
F_ncs = 'b0;
F_addr =addr;
@(posedge S_cpu_clk)
wait (F_nrdy==);
rddata = F_data_o;
//$display("the addr %h read result is %h",addr, rddata);
@(posedge S_cpu_clk)
F_nrd = 'b1;
F_nwr = 'b1;
F_ncs = 'b1;
F_addr =;
end
endtask
task CAN_TEST_ALL;
begin
CAN_TEST('h0700,16'h1201,'h0500,16'h1100,'h03);
//CAN_TEST(16'h0701,16'h1200,16'h0600,16'h1000,8'h12);
end
endtask
task CAN_TEST;
input [:] reset_reg_star;
input [:] reset_reg_earth;
input [:] base_reg_star;
input [:] base_reg_earth;
input [:] connect;
int i_cnt;
logic [:] can_rdata;
begin
$display("=============CAN %h TEST START=============",connect);
CPU_WRITE(reset_reg_star,'h0000);//CAN1A RST begin
#170ns;
CPU_WRITE(reset_reg_star,'h0001);//CAN1A RST end
CPU_WRITE(reset_reg_earth,'h0000);//CAN2B RST begin
#170ns;
CPU_WRITE(reset_reg_earth,'h0001);//CAN2B RST end
//////////////////can init 1A&2B begin////////////////
CPU_WRITE(base_reg_star,'h09); //CAN1A INIT [star]
CPU_READ_NPT(base_reg_star,can_rdata);
if(can_rdata != 'h09)
begin
$display("the addr base_reg_star read result is %h,wrong!(should be 8'h09)",can_rdata);
$stop;
end
CPU_WRITE(base_reg_star+'h1F,8'h08);
CPU_WRITE(base_reg_star+'h10,8'h00);
CPU_WRITE(base_reg_star+'h11,8'h00);
CPU_WRITE(base_reg_star+'h12,8'h00);
CPU_WRITE(base_reg_star+'h13,8'h00);
CPU_WRITE(base_reg_star+'h14,8'hFF); // ////CARE ID:MUST 00
CPU_WRITE(base_reg_star+'h15,8'hFF);
CPU_WRITE(base_reg_star+'h16,8'hFF);
CPU_WRITE(base_reg_star+'h17,8'hFF);
CPU_WRITE(base_reg_star+'h04,8'h03);
CPU_WRITE(base_reg_star+'h06,8'h00);
CPU_WRITE(base_reg_star+'h07,8'h16);
CPU_WRITE(base_reg_star+'h08,8'h00);
CPU_WRITE(base_reg_star+'h1E,8'h00);
CPU_WRITE(base_reg_star+'h00,8'h08);
CPU_WRITE(base_reg_earth+'h00,8'h09); //CAN2B INIT [earth]
CPU_READ_NPT(base_reg_earth+'h00,can_rdata);
if(can_rdata != 'h09)
begin
$display("the addr base_reg_earth+8'h00 read result is %h,wrong!(should be 8'h09)",can_rdata);
$stop;
end
CPU_WRITE(base_reg_earth+'h1F,8'h08);
CPU_WRITE(base_reg_earth+'h10,8'h12); // //// ID:MUST 122X
CPU_WRITE(base_reg_earth+'h11,8'h24);
CPU_WRITE(base_reg_earth+'h12,8'h00);
CPU_WRITE(base_reg_earth+'h13,8'h00);
CPU_WRITE(base_reg_earth+'h14,8'h00);
CPU_WRITE(base_reg_earth+'h15,8'h00);
CPU_WRITE(base_reg_earth+'h16,8'hFF);
CPU_WRITE(base_reg_earth+'h17,8'hFF);
CPU_WRITE(base_reg_earth+'h04,8'h01);
CPU_WRITE(base_reg_earth+'h06,8'h00);
CPU_WRITE(base_reg_earth+'h07,8'h16);
CPU_WRITE(base_reg_earth+'h08,8'h02);
CPU_WRITE(base_reg_earth+'h1E,8'h00);
CPU_WRITE(base_reg_earth+'h00,8'h08);
//////////////////can init end///////////////////////////
CPU_WRITE(base_reg_star+'h01,8'h0C); //CLR RX FIFO
CPU_READ(base_reg_star+'h02,can_rdata); //SR[2]=?0
while(can_rdata[] == )
begin
#1us;
CPU_READ_NPT(base_reg_star+'h02,can_rdata);
end
CPU_WRITE(base_reg_star+'h10,8'h08); //Transmit Frame Information:standard,8 data
CPU_WRITE(base_reg_star+'h11,8'h56); //identifier:ff0
CPU_WRITE(base_reg_star+'h12,8'h60);
for(i_cnt=;i_cnt<;i_cnt++)
begin
CPU_WRITE(base_reg_star+'h10+i_cnt,i_cnt);//write data to transmit buffer,发送一帧标准帧数据
end
CPU_WRITE(base_reg_star+'h01,8'h01); //trans enable
CPU_READ(base_reg_star+'h03,can_rdata);
CPU_READ(base_reg_star+'h02,can_rdata);
while(can_rdata[] == )
begin
#1us;
CPU_READ_NPT(base_reg_star+'h02,can_rdata);
end
CPU_READ(base_reg_star+'h03,can_rdata);
CPU_READ(base_reg_star+'h02,can_rdata);
#2ms;
CPU_READ(base_reg_earth+'h10,can_rdata);
CPU_READ(base_reg_earth+'h11,can_rdata);
CPU_READ(base_reg_earth+'h12,can_rdata);
CPU_READ(base_reg_earth+'h13,can_rdata);
CPU_READ(base_reg_earth+'h14,can_rdata);
CPU_READ(base_reg_earth+'h15,can_rdata);
CPU_READ(base_reg_earth+'h16,can_rdata);
CPU_READ(base_reg_earth+'h17,can_rdata);
CPU_READ(base_reg_earth+'h18,can_rdata);
CPU_READ(base_reg_earth+'h19,can_rdata);
//CPU_READ(base_reg_star+8'h03,can_rdata);
//CPU_READ(base_reg_star+8'h02,can_rdata);
CPU_READ(base_reg_earth+'h1a,can_rdata);
///////////////////////////////////second sending///////////////////////////////
$display("####################################");
CPU_WRITE(base_reg_star+'h01,8'h0C);
CPU_WRITE(base_reg_earth+'h01,8'h0C);
CPU_READ(base_reg_star+'h02,can_rdata); //SR[2]=?0
while(can_rdata[] == )
begin
#1us;
CPU_READ_NPT(base_reg_star+'h02,can_rdata);
end
CPU_READ(base_reg_star+'h02,can_rdata);
CPU_WRITE(base_reg_star+'h10,8'h08); //Transmit Frame Information:standard,8 data
CPU_WRITE(base_reg_star+'h11,8'h00); //identifier:00
CPU_WRITE(base_reg_star+'h12,8'h00);
for(i_cnt=;i_cnt<;i_cnt++)
begin
CPU_WRITE(base_reg_star+'h10+i_cnt,i_cnt);//write data to transmit buffer,发送一帧标准帧数据
end
CPU_WRITE(base_reg_star+'h01,8'h01); //trans enable
CPU_READ(base_reg_star+'h02,can_rdata); //SR[2]=?0
#2ms
CPU_READ(base_reg_earth+'h10,can_rdata);
CPU_READ(base_reg_earth+'h11,can_rdata);
CPU_READ(base_reg_earth+'h12,can_rdata);
CPU_READ(base_reg_earth+'h13,can_rdata);
CPU_READ(base_reg_earth+'h14,can_rdata);
CPU_READ(base_reg_earth+'h15,can_rdata);
CPU_READ(base_reg_earth+'h16,can_rdata);
CPU_READ(base_reg_earth+'h17,can_rdata);
CPU_READ(base_reg_earth+'h18,can_rdata);
CPU_READ(base_reg_earth+'h19,can_rdata);
//CPU_READ(base_reg_star+8'h03,can_rdata);
//CPU_READ(base_reg_star+8'h02,can_rdata);
CPU_READ(base_reg_earth+'h1a,can_rdata);
$display("CAN %h TEST Success!\n",connect);
end
endtask
MCAN2测试代码
CAN协议学习(二)MCAN控制器介绍的更多相关文章
- WebService学习--(二)webservice相关介绍
一.WebService是什么? 1. 基于Web的服务:服务器端整出一些资源让客户端应用访问(获取数据) 2. 一个跨语言.跨平台的规范(抽象) 3. 多个跨平台.跨语言的应用间通信整合的方案(实际 ...
- TCP/IP协议学习(二) LWIP用户自定义配置文件解析
LWIP协议支持用户配置,可以通过用户裁剪实现最优化配置,LWIP默认包含opts.h作为系统默认配置,不过通过添加lwipopts.h文件并包含在opts.h头文件之前就可以对lwip进行用户裁剪, ...
- Asp.Net MVC学习总结(二)——控制器与动作(Controller And Action)
一.理解控制器 1.1.什么是控制器 控制器是包含必要的处理请求的.NET类,控制器的角色封装了应用程序逻辑,控制器主要是负责处理请求,实行对模型的操作,选择视图呈现给用户. 简单理解:实现了ICon ...
- HTTP协议学习笔记(二)
HTTP协议学习笔记(二) 1.HTTP报文 HTTP报文:用于HTTP协议交互的信息.请求报文:请求端(客户端)的HTTP报文叫做请求报文.响应报文:响应端(服务端)的HTTP报文叫做响应报文. H ...
- 8086汇编语言学习(二) 8086汇编开发环境搭建和Debug模式介绍
1. 8086汇编开发环境搭建 在上篇博客中简单的介绍了8086汇编语言.工欲善其事,必先利其器,在8086汇编语言正式开始学习之前,先介绍一下如何搭建8086汇编的开发环境. 汇编语言设计之初是用于 ...
- TCP/IP协议学习之实例ping命令学习笔记
TCP/IP协议学习之实例ping命令学习笔记(一) 一. 目的为了让网络协议学习更有效果,在真实网络上进行ping命令前相关知识的学习,暂时不管DNS,在内网中,进行2台主机间的ping命令的整个详 ...
- python学习第二讲,pythonIDE介绍以及配置使用
目录 python学习第二讲,pythonIDE介绍以及配置使用 一丶集成开发环境IDE简介,以及配置 1.简介 2.PyCharm 介绍 3.pycharm 的安装 二丶IDE 开发Python,以 ...
- SpringMVC入门学习(二)
SpringMVC入门学习(二) ssm框架 springMVC 在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...
- 苹果ANCS协议学习【转】
苹果ANCS协议学习 转自:http://www.cnblogs.com/alexcai/p/4321514.html 综述 苹果通知中心(Apple Notification Center Serv ...
随机推荐
- How to not display “Commit point reached - logical record count” counts
You can use the keyword silent, which is available in the options clause. You can set the followin ...
- Oracle 查询每天执行慢的SQL
本文转载自http://blog.itpub.net/28602568/viewspace-1364844/ 前言: 工作中的您是否有 想对每天慢的sql进行查询.汇总或者行优化等情况,如下SQL希 ...
- POJ2955 Brackets(区间DP)
给一个括号序列,求有几个括号是匹配的. dp[i][j]表示序列[i,j]的匹配数 dp[i][j]=dp[i+1][j-1]+2(括号i和括号j匹配) dp[i][j]=max(dp[i][k]+d ...
- 3.1常用类(java学习笔记)包装类及日期类
一.包装类 java是一门面向对象的语言,秉承一切皆对象的思想. 可java中有一些基本数据类型并不是对象,有时可能需要将它们变为对象. 这时就需要用到我们的包装类了. 基本数据类型 包装类 int ...
- 每天一个liunx命令4之 ps -ef ,ps -aux ,ps aux
1ps aux和ps –aux 请注意"ps -aux"不同于"ps aux".POSIX和UNIX的标准要求"ps -aux"打印用户名为 ...
- 一次快速改写 SQL Server 高效查询的范例
原文:一次快速改写 SQL Server 高效查询的范例 最近線上系統突然出現匯出資料超過 10 筆時,查詢逾時的狀況,在仔細查找之後. 發現了問題原因,透過應用端與數據端兩邊同時調整,將查詢的效率提 ...
- 【转】C++调用Matlab的.m文件
原文地址 Matlab是一个强大的数学计算/仿真工 具,其内置了很多实用的现成的函数,而且我们经常也自己定义很多m函数.但在很多情况下,我们不得不使用VC编程.那么,如何在VC中利用matla ...
- Springboot默认加载application.yml原理以及扩展
Springboot默认加载application.yml原理以及扩展 SpringApplication.run(...)默认会加载classpath下的application.yml或applic ...
- jquery的attr和prop区别之实例
对于HTML元素本身就带有的固有属性,在处理时,使用prop方法. 对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法. html文件 <tr> <th>& ...
- tensorflow TensorArray 代码例子
import tensorflow as tf import numpy as np B=3 D=4 T=5 tf.reset_default_graph() xs=tf.placeholder(sh ...