CAN协议学习(二)MCAN控制器介绍

更多细节请参看MCAN2文档mcan2_ps.pdf。

一、MCAN2简介

MCAN2Mentor公司开发的一个CAN2.0网络控制器的软核,初版2001年末版2006年。MCAN 2控制器实现了BOSCAN消息传输协议2.0a2.0b。规范2.0a(相当于can 1.2)涵盖标准消息格式(11位标识符);规范2.0b涵盖标准和扩展消息格式(11位和29位标识符)

二、总体架构

下图显示了MCAN2设计的主要功能块。

 

CPUmcan 2的访问是通过独立的地址、输入数据和输出数据总线进行的。由主机设备将用于传输的消息放置到发送缓冲器中,以便由位处理器进行传输。设备接收到的消息首先由接收过滤器过滤,然后放入接收FIFO中。

CPU通过称为接收缓冲区的13字节窗口访问接收FIFO.结合接收FIFO使用接收缓冲区允许CPU在接收其他消息时处理一条消息。接收FIFO的总长度为64个字节,并以循环方式使用,使其能够同时容纳最多5个扩展的帧格式消息。

位定时逻辑块负责设备的波特率,并且是可编程的。所支持的波特率范围取决于主系统时钟XTAL1的频率,并且可以容易地跨越比BOSCH规范所选择的125kbud-1MBaud更宽的波特率范围。

CAN总线的接口由发送信号tx0tx1和接收的rx 0提供。TX1通常与tx0相反,也可以编程为输出发送时钟,这对于测试非常有用。

三、发送、接收过程

要传输的数据以标准帧格式(SFF)或扩展帧格式(EFF)写入mcan 2的发送缓冲器(如下)。发送缓冲器包括CAN地址10h1ch之间的13个字节,一个帧最多可以发送8个字节的数据。注意:在将数据写入缓冲区之前,需要检查传输缓冲区状态(状态寄存器,位2),以确保缓冲区“释放”(SR.2=1)。当缓冲区被锁定时写入缓冲区的任何数据(SR.2=0)都会丢失而没有任何指示。

 

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

 

FF代表frame format0为标准帧,1为拓展帧。

RTR代表REMOTE TRANSMISSION REQUEST1表示为远程帧。

DLC代表DATA LENGTH CODE:范围0-8,大于8的数被自动解释为8

ID代表IDENTIFIER:标识符充当消息的名称,用于接收过滤,并确定总线访问优先级。标识符的二进制值越低,优先级就越高。在标准帧格式(SFF)中,标识符由11(id.28id.18)组成。在扩展帧格式(Eff)消息中,标识符由29(id.28id.0)组成。id.28是最高位,首先在总线上传输。

mcan 2接收的数据首先由接收滤波器过滤,然后传递给接收FIFO。接受过滤器只传递那些具有与接收过滤器寄存器中记录的消息相匹配的标识位的消息。

接收FIFO64个字节深,允许最多5个完整扩展帧格式(EFF)消息的空间,并以循环方式使用。

放置在接收FIFO中的数据通过一个称为接收缓冲区的13字节窗口读取。该窗口位于can地址10h-1ch,即它占用与发送缓冲器相同的地址空间。与传输缓冲区一样,它足够宽,可以容纳一条包含最多8个字节数据的消息。

四、信号&寄存器描述

信号描述:

 

寄存器描述:

 

五、接收过滤

与过滤相关的寄存器:

10h-13h ACR03 Acceptance Code Registers 0-3

14h-17h AMR03 Acceptance Mask Registers 0-3

MCAN2的接收过滤模块首先将接收到的数据帧的ID部分与ACR即接收码寄存器比较,如果一致则接收,如果不一致则丢弃;AMR是接收掩码寄存器,如果某位设为‘1’,则将ACR对应的位设为‘不关心’。根据MOD.3为0或1来设置单过滤或双过滤模式,具体如下图。

六、时序图

 

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

  1 //test CAN 2019.03.22 by zhou
  2 
  3     assign  F_can_rx[0]=(F_can_tx[3]==1'b1)?F_can_tx[0]:((F_can_tx[0]==1'b1)?F_can_tx[3]:1'bZ);        //star
  4     assign  F_can_rx[3]=(F_can_tx[0]==1'b1)?F_can_tx[3]:((F_can_tx[3]==1'b1)?F_can_tx[0]:1'bZ);        //earth
  5 
  6     assign  F_can_rx[1]=(F_can_tx[2]==1'b1)?F_can_tx[1]:((F_can_tx[1]==1'b1)?F_can_tx[2]:1'bZ);        //star
  7     assign  F_can_rx[2]=(F_can_tx[1]==1'b1)?F_can_tx[2]:((F_can_tx[2]==1'b1)?F_can_tx[1]:1'bZ);        //earth
  8     
  9 
 10 
 11 task CPU_READ_NPT;        //just read data, no display
 12     input [17:2] addr;
 13     output [15:0] rddata;
 14 
 15        begin
 16         #120ns
 17     @(posedge S_cpu_clk) 
 18     F_nrd = 1'b1;
 19     F_nwr = 1'b1;
 20     F_ncs = 1'b1;
 21     F_addr =addr;
 22     @(posedge S_cpu_clk) 
 23     F_nrd = 1'b0;
 24     F_nwr = 1'b1;
 25     F_ncs = 1'b0;
 26     F_addr =addr;
 27     @(posedge S_cpu_clk) 
 28     wait (F_nrdy==0);
 29     rddata = F_data_o;
 30     //$display("the addr %h read result is %h",addr, rddata);
 31     @(posedge S_cpu_clk) 
 32     F_nrd = 1'b1;
 33     F_nwr = 1'b1;
 34     F_ncs = 1'b1;
 35     F_addr =0;
 36        end
 37 endtask
 38 
 39 
 40 task CAN_TEST_ALL;
 41     begin
 42     CAN_TEST(16'h0700,16'h1201,16'h0500,16'h1100,8'h03);
 43     //CAN_TEST(16'h0701,16'h1200,16'h0600,16'h1000,8'h12);
 44     end
 45 endtask
 46 
 47 
 48 task CAN_TEST;
 49     input [15:0] reset_reg_star;
 50     input [15:0] reset_reg_earth;
 51     input [15:0] base_reg_star;
 52     input [15:0] base_reg_earth;
 53     input [7:0] connect;
 54 
 55     int i_cnt;
 56     logic [15:0] can_rdata;
 57 
 58     begin
 59     $display("=============CAN %h TEST START=============",connect);
 60 
 61     CPU_WRITE(reset_reg_star,16'h0000);//CAN1A RST begin
 62     #170ns;
 63     CPU_WRITE(reset_reg_star,16'h0001);//CAN1A RST end
 64     CPU_WRITE(reset_reg_earth,16'h0000);//CAN2B RST begin
 65     #170ns;
 66     CPU_WRITE(reset_reg_earth,16'h0001);//CAN2B RST end
 67 
 68 
 69     //////////////////can init 1A&2B begin////////////////
 70     CPU_WRITE(base_reg_star,8'h09);    //CAN1A INIT [star]
 71     CPU_READ_NPT(base_reg_star,can_rdata);
 72     if(can_rdata != 8'h09)
 73     begin 
 74         $display("the addr base_reg_star read result is %h,wrong!(should be 8'h09)",can_rdata);
 75         $stop;
 76     end
 77     CPU_WRITE(base_reg_star+8'h1F,8'h08);
 78 
 79     CPU_WRITE(base_reg_star+8'h10,8'h00);
 80     CPU_WRITE(base_reg_star+8'h11,8'h00);
 81     CPU_WRITE(base_reg_star+8'h12,8'h00);
 82     CPU_WRITE(base_reg_star+8'h13,8'h00);
 83     CPU_WRITE(base_reg_star+8'h14,8'hFF);      // ////CARE ID:MUST 00                                                   
 84     CPU_WRITE(base_reg_star+8'h15,8'hFF);
 85     CPU_WRITE(base_reg_star+8'h16,8'hFF);
 86     CPU_WRITE(base_reg_star+8'h17,8'hFF);
 87 
 88     CPU_WRITE(base_reg_star+8'h04,8'h03);
 89     CPU_WRITE(base_reg_star+8'h06,8'h00);
 90     CPU_WRITE(base_reg_star+8'h07,8'h16);    
 91     CPU_WRITE(base_reg_star+8'h08,8'h00);
 92     CPU_WRITE(base_reg_star+8'h1E,8'h00);
 93     CPU_WRITE(base_reg_star+8'h00,8'h08);
 94 
 95     CPU_WRITE(base_reg_earth+8'h00,8'h09);    //CAN2B INIT [earth]
 96     CPU_READ_NPT(base_reg_earth+8'h00,can_rdata);
 97     if(can_rdata != 8'h09)
 98     begin 
 99         $display("the addr base_reg_earth+8'h00 read result is %h,wrong!(should be 8'h09)",can_rdata);
100         $stop;
101     end
102     CPU_WRITE(base_reg_earth+8'h1F,8'h08);
103 
104     CPU_WRITE(base_reg_earth+8'h10,8'h12);         // //// ID:MUST 122X
105     CPU_WRITE(base_reg_earth+8'h11,8'h24);        
106     CPU_WRITE(base_reg_earth+8'h12,8'h00);
107     CPU_WRITE(base_reg_earth+8'h13,8'h00);
108     CPU_WRITE(base_reg_earth+8'h14,8'h00);                                                
109     CPU_WRITE(base_reg_earth+8'h15,8'h00);
110     CPU_WRITE(base_reg_earth+8'h16,8'hFF);
111     CPU_WRITE(base_reg_earth+8'h17,8'hFF);
112 
113     CPU_WRITE(base_reg_earth+8'h04,8'h01);
114     CPU_WRITE(base_reg_earth+8'h06,8'h00);
115     CPU_WRITE(base_reg_earth+8'h07,8'h16);    
116     CPU_WRITE(base_reg_earth+8'h08,8'h02);
117     CPU_WRITE(base_reg_earth+8'h1E,8'h00);
118     CPU_WRITE(base_reg_earth+8'h00,8'h08);
119     //////////////////can init end///////////////////////////
120 
121 
122     CPU_WRITE(base_reg_star+8'h01,8'h0C);    //CLR RX FIFO
123 
124     CPU_READ(base_reg_star+8'h02,can_rdata);    //SR[2]=?0
125     while(can_rdata[2] == 0)
126     begin
127         #1us;
128         CPU_READ_NPT(base_reg_star+8'h02,can_rdata);
129     end
130     
131     
132         CPU_WRITE(base_reg_star+8'h10,8'h08);    //Transmit Frame Information:standard,8 data
133     CPU_WRITE(base_reg_star+8'h11,8'h56);    //identifier:ff0
134     CPU_WRITE(base_reg_star+8'h12,8'h60);    
135     for(i_cnt=3;i_cnt<11;i_cnt++)
136     begin
137         CPU_WRITE(base_reg_star+8'h10+i_cnt,i_cnt);//write data to transmit buffer,发送一帧标准帧数据
138     end
139     
140 
141     CPU_WRITE(base_reg_star+8'h01,8'h01);    //trans enable
142     
143     CPU_READ(base_reg_star+8'h03,can_rdata);
144     CPU_READ(base_reg_star+8'h02,can_rdata);
145     while(can_rdata[2] == 0)
146     begin    
147         #1us;
148         CPU_READ_NPT(base_reg_star+8'h02,can_rdata);
149         
150     end
151     CPU_READ(base_reg_star+8'h03,can_rdata);
152     CPU_READ(base_reg_star+8'h02,can_rdata);
153     
154     #2ms;
155     CPU_READ(base_reg_earth+8'h10,can_rdata);
156     CPU_READ(base_reg_earth+8'h11,can_rdata);
157     CPU_READ(base_reg_earth+8'h12,can_rdata);
158     CPU_READ(base_reg_earth+8'h13,can_rdata);
159     CPU_READ(base_reg_earth+8'h14,can_rdata);
160     CPU_READ(base_reg_earth+8'h15,can_rdata);
161     CPU_READ(base_reg_earth+8'h16,can_rdata);
162     CPU_READ(base_reg_earth+8'h17,can_rdata);
163     CPU_READ(base_reg_earth+8'h18,can_rdata);
164     CPU_READ(base_reg_earth+8'h19,can_rdata);
165     //CPU_READ(base_reg_star+8'h03,can_rdata);
166     //CPU_READ(base_reg_star+8'h02,can_rdata);
167     CPU_READ(base_reg_earth+8'h1a,can_rdata);
168 
169     
170     ///////////////////////////////////second sending///////////////////////////////
171     $display("####################################");
172     CPU_WRITE(base_reg_star+8'h01,8'h0C);
173     CPU_WRITE(base_reg_earth+8'h01,8'h0C);
174 
175     CPU_READ(base_reg_star+8'h02,can_rdata);    //SR[2]=?0
176     while(can_rdata[2] == 0)
177     begin
178         #1us;
179         CPU_READ_NPT(base_reg_star+8'h02,can_rdata);
180     end
181     CPU_READ(base_reg_star+8'h02,can_rdata);
182 
183     CPU_WRITE(base_reg_star+8'h10,8'h08);    //Transmit Frame Information:standard,8 data
184     CPU_WRITE(base_reg_star+8'h11,8'h00);    //identifier:00
185     CPU_WRITE(base_reg_star+8'h12,8'h00);    
186     for(i_cnt=3;i_cnt<11;i_cnt++)
187     begin
188         CPU_WRITE(base_reg_star+8'h10+i_cnt,i_cnt);//write data to transmit buffer,发送一帧标准帧数据
189     end        
190 
191 
192     CPU_WRITE(base_reg_star+8'h01,8'h01);    //trans enable
193     CPU_READ(base_reg_star+8'h02,can_rdata);    //SR[2]=?0
194     #2ms
195     CPU_READ(base_reg_earth+8'h10,can_rdata);
196     CPU_READ(base_reg_earth+8'h11,can_rdata);
197     CPU_READ(base_reg_earth+8'h12,can_rdata);
198     CPU_READ(base_reg_earth+8'h13,can_rdata);
199     CPU_READ(base_reg_earth+8'h14,can_rdata);
200     CPU_READ(base_reg_earth+8'h15,can_rdata);
201     CPU_READ(base_reg_earth+8'h16,can_rdata);
202     CPU_READ(base_reg_earth+8'h17,can_rdata);
203     CPU_READ(base_reg_earth+8'h18,can_rdata);
204     CPU_READ(base_reg_earth+8'h19,can_rdata);
205     //CPU_READ(base_reg_star+8'h03,can_rdata);
206     //CPU_READ(base_reg_star+8'h02,can_rdata);
207     CPU_READ(base_reg_earth+8'h1a,can_rdata);
208     
209     $display("CAN %h TEST Success!
",connect);
210     end
211 
212 endtask
MCAN2测试代码
原文地址:https://www.cnblogs.com/zhouliyan/p/10612813.html