FPGA实现CAN通信

FPGA实现CAN通信
1、CAN协议物理层和协议层
2、传输的波特率
3、FPGA实现思路
4、FPGA实现代码

1、CAN物理层和协议层
CAN与串口类似,都是异步通信,利用两根差分线来进行信号的传输。
在多节点进行数据传输时主要分为遵循ISO11898标准的高速短距离闭环形式和遵循ISO11519标准的低速远距离开环网络。这两种形式主要是在硬件设计时根据实际应用情况加入120欧姆或者2.2千欧姆电阻。
在CAN通信时信号逻辑和平时常用的电平表示不太一样,根据标准电平表示形式如下图:

FPGA实现CAN通信
CAN报文类型有5种,分别是数据帧、遥控帧、错误帧、过载帧、帧间隔。而我们常用的是数据帧,数据帧分为标准数据帧和扩展数据帧两种。数据帧结构如下图:
FPGA实现CAN通信
3、FPGA实现思路
在进行FPGA实现时主要是实现一个完备的状态转移状态机。在设计状态机时需要对最复杂的包格式进行设计。通过对控制段进行判断来跳转到不同类型帧格式的状态,根据数据长度来完成对数据的接收和发送。由于FPGA实现完备的CAN收发驱动并不是所有项目所必须的,因此根据不同项目来进行特定包数据的收发。
通过上面描述对CAN数据格式有了一个基本上认识,下面是通过示波器抓取CAN标准数据帧波形,示波器正连接CANH端,示波器负极连接CANL端。波特率是10Kbps,有效数据长度8字节。
FPGA实现CAN通信
4、FPGA实现代码

在实现波特率可调的数据收发控制时需要注意的是每个波特数据的采样点。CAN数据采样时序如下图所示,一般采样点都是在数据稳当的中间点位置,因此在设计FPGA中CAN模块的时钟频率应当是数据波特率的20倍。

FPGA实现CAN通信

数据的收发需要根据实际的项目情况进行组包控制,这里就不进行细致描述了。
CAN实现数据的收发两个过程中对应FPGA来说由于接收相对复杂,就以接收模块进行描述。
数据的接收过程就按照一般的状态机进行设计就行,需要注意的是不同类型帧的跳转是在控制段进行了,因此在控制段会发生状态的跳转。CAN接收状态的状态机实现如下图:

FPGA实现CAN通信

这个状态机的实现并不复杂,主要是对帧类型进行判断。然后根据数据长度把数据解析出来。下面是实现CAN数据接收代码:

`timescale 1ns / 1ps//// Company: // Engineer: // // Create Date:    // Design Name: // Module Name:    can_rx // Project Name: // Target Devices: // Tool versions: // Description: //// Dependencies: //// Revision: // Revision 0.01 - File Created// Additional Comments: ////module can_rx(input   	wire		 can_clk	    				,input   	wire		 rst_n       				,				input		wire						can_rx						,		output		reg							can_ack_out_low				,output		reg							can_id_out_en				,output		reg			[10:0]			can_id_out					,output		reg							can_data_out_en				,output		reg			[63:0]			can_data_out				    );				reg					[8:0]			state							;reg									can_rx_t						;reg									error_state						;reg					[9:0]			error_data						;reg					[4:0]			one_bit_cont					;reg					[10:0]			can_id							;reg					[6:0]			bit_cont						;reg									id_en_flag						;reg									contral_flag					;reg									data_en_flag					;reg									cic_en_flag						;reg									can_rx_en_flag					;reg									can_rx_unen_flag				;reg					[4:0]			can_continuity_data				;reg									can_continuity_data_flag		;reg					[4:0]			can_id_data_cont				;reg					[3:0]			can_contral_data_cont			;reg					[6:0]			can_data_data_cont				;reg					[4:0]			can_cic_data_cont				;always @(posedge can_clk or negedge rst_n )beginif(rst_n==1'b0) begincan_rx_t	 'b0							;end else  begincan_rx_t	 can_rx						;end	end parameter			state_idle		 = 9'b000000000			;			//状态机初始化parameter			state_start		 = 9'b000000001			;			//监测到开始标志parameter			state_sof		 = 9'b000000010			;           //开始帧头第一位SOFparameter			state_id		 = 9'b000000100			;           //包IDparameter			state_control	 = 9'b000001000			;           //标准帧控制段parameter			state_data		 = 9'b000010000			;           //数据段parameter			state_crc		 = 9'b000100000			;           //CRC段parameter			state_ack		 = 9'b001000000			;           //ACK段parameter			state_eof		 = 9'b010000000			;           //帧结束段parameter			state_end		 = 9'b100000000			;           //状态机结束状态parameter			bit_flag_no		 = 5'b10011				;		always @(posedge can_clk or negedge rst_n )beginif(rst_n==1'b0) beginstate						 'b0							;one_bit_cont				 'b0							;bit_cont					 'b0							;id_en_flag					 'b0							;contral_flag				 'b0							;data_en_flag  'b0							;cic_en_flag					 'b0							;can_rx_en_flag               'b0							;can_ack_out_low				 'b1							;end   else case(state) 		state_idle:		begin if ((can_rx_t==1'b1)&&(can_rx==1'b0))	begin							state						 state_sof					;							one_bit_cont				 'b0							;							can_rx_en_flag               'b1							;					end else begin							state						 state_idle					;							one_bit_cont				 'b0							;							bit_cont					 'b0							;							id_en_flag					 'b0							;							contral_flag  'b0							;							data_en_flag				 'b0							;							cic_en_flag	  'b0							;							can_rx_en_flag               'b0							;							can_ack_out_low				 'b1							;					end 					end 		state_sof:		begin if ((one_bit_cont==bit_flag_no)&&(can_rx==1'b0))	begin							state						 state_id						;							id_en_flag					 'b1							;							one_bit_cont				 'b0							;					end else if ((one_bit_contbit_flag_no)&&(can_rx==1'b0)) begin							state						 state_sof					;							one_bit_cont				 one_bit_cont + 1'b1			;					end 					end 		state_id:		begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_id_data_cont))	begin							state						 state_control				;							id_en_flag					 'b0							;							contral_flag				 'b1							;							one_bit_cont				 'b0							;							bit_cont					 'b0							;					end else if ((one_bit_cont==bit_flag_no)&&(bit_contcan_id_data_cont)) begin							state						 state_id						;							one_bit_cont				 'b0							;							bit_cont					 bit_cont + 1'b1				;					end else if (one_bit_contbit_flag_no) begin							state						 state_id						;							one_bit_cont				 one_bit_cont + 1'b1			;					end else begin							state						 state_idle					;					end 					end 		state_control:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_contral_data_cont))	begin							state						 state_data					;							contral_flag				 'b0							;							one_bit_cont				 'b0							;							bit_cont					 'b0							;							data_en_flag  'b1							;					end else if ((one_bit_cont==bit_flag_no)&&(bit_contcan_contral_data_cont)) begin							state						 state_control				;							one_bit_cont				 'b0							;							bit_cont					 bit_cont + 1'b1				;					end else if (one_bit_contbit_flag_no) begin							state						 state_control				;							one_bit_cont				 one_bit_cont + 1'b1			;					end else begin							state						 state_idle					;					end 					end 		state_data:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_data_data_cont))	begin							state						 state_crc					;							one_bit_cont				 'b0							;							bit_cont					 'b0							;							data_en_flag  'b0							;							cic_en_flag					 'b1							;					end else if ((one_bit_cont==bit_flag_no)&&(bit_contcan_data_data_cont)) begin							state						 state_data					;							one_bit_cont				 'b0							;							bit_cont					 bit_cont + 1'b1				;					end else if (one_bit_contbit_flag_no) begin							state						 state_data					;							one_bit_cont				 one_bit_cont + 1'b1			;					end else begin							state						 state_idle					;					end 					end 		state_crc:	begin 来源:撕裂的牛仔裤
                                                        

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年3月18日
下一篇 2021年3月18日

相关推荐