要想让软件能够如期运行,首先需要做好硬件的连线。所以,本系统的第一步是进行FPGA电路设计。
硬件原理
想要做好电路设计,首先要了解用到的硬件的工作原理。
首先是rtl8188无线网卡。这张无线网卡通过USB接口与PC或开发板等设备连接。成功驱动后可以有多种工作方式,如开放无线热点,或者连接其他无线热点等。
其次是舵机。舵机,是指在自动驾驶仪中操纵飞机舵面(操纵面)转动的一种执行部件。
本次设计使用到的舵机如下图所示:
可以看到,这个舵机上有三根线,分别为红线、橙线、黑线。其中,
红线为直流供电线,需要提供5V直流电来作为舵机的工作电压;
黑线是地线;
橙线为控制线,控制线用于传输角度控制信号。这个角度是由控制信号脉冲的持续时间决定的,这叫做脉冲编码调制(PCM)。舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围,总间隔为2ms。脉冲的宽度将决定马达转动的距离。例如:1.5毫秒的脉冲,电机将转向90度的位置(通常称为中立位置,对于180°舵机来说,就是90°位置)。如果脉冲宽度小于1.5毫秒,那么电机轴向朝向0度方向。如果脉冲宽度大于1.5毫秒,轴向就朝向180度方向。
本系统中,由于Zybo开发板上的PMOD端口的最高电压输出是3.3V,所以舵机的直流供电需要通过其他方式来提供。
设计目标
在本系统中,需要通过Zybo开发板上的嵌入式Linux系统来接收socket信息并且控制舵机。而Zybo板虽然集成了FPGA和双核Cortex™-A9处理器,却没有帮我们连接ARM核和实验板上的外部设备。
所以,根据之前了解到的工作原理,我们首先需要自己在FPGA中设计一个PWM波输出设备,之后建立USB接口以及控制舵机的PWM波输出设备与ARM核的连接,这样才能让运行在ARM上的嵌入式Linux系统能够找到这两个设备并且加以控制。
设计过程
了解到要做什么之后,就可以开始设计了,先从复杂一点的PWM波模块设计开始吧。
PWM波模块设计及连接
本次设计中,PWM波使用计数器计数的方式来生成。首先设置一个模N计数器,当计数器的值小于值m(m<N)时,输出电平1;反之则输出电平0。
在之前的硬件原理中已经介绍到,舵机的控制一般需要一个20ms左右的时基脉冲,也就是说频率是50Hz。Zybo开发板给外设提供的时钟频率是100MHz,这两个频率相差过大。为了减小计数器的模,先对这个100MHz的时钟做一次分频。分频器Verilog代码如下:
module clk_div(
input clk_100m,
output reg clk_1m
);
reg [5:0] cnt = 0;
initial begin
clk_1m = 0;
end
always@(posedge clk_100m) begin
if(cnt == 49) begin
cnt <= 0;
clk_1m <= ~clk_1m;
end
else cnt <= cnt + 1;
end
endmodule
原理比较简单,让100MHz的时钟信号作为输入,输出信号每过50个时钟周期就翻转一次,这样就使得输出信号是1MHz的时钟信号。
有了1MHz的信号作为时钟信号之后,计算可得:
1MHz / 50Hz = 20000
所以,PWM波的计数器的模应该为20000。这样的话就可以进行PWM输出模块的设计了。Verilog代码如下
module servo(
input clk_1m,
input [11:0] pwm_duty,
output pwm_out
);
reg [14:0]cnt = 0;
always @( posedge clk_1m )
begin
if(cnt == 19999)
cnt <= 0;
else
cnt <= cnt + 1;
end
assign pwm_out = (cnt < pwm_duty) ? 1'b1 : 1'b0
endmodule
首先,PWM波生成模块的输入为刚刚生成的1MHz时钟信号clk_1m以及ARM核通过实验板上的AXI总线传递过来的数据pwm_duty。设计模20000计数器,当计数器的值小于12位输入信号pwm_duty时,输出电平1,否则输出电平0。这时,输出pwm_out就是20ms的时基脉冲。
到这里未知,我们就在FPGA内设计出了一个PWM波输出模块。但由于我们需要将这个模块与ARM核连接,所以我们需要将这个模块与Zybo实验板上的AXI总线做连接。
好在Vivado自带生成与AXI总线连接的IP核的功能。用Vivado的自定义IP核功能把上述分频器以及PWM波生成模块包装成与AXI总线连接的IP核。这样,就可以使ARM核向该模块传递数据pwm_duty,从而修改PWM波的占空比了。封装好后的IP核如下图:
左侧的三个输入端口是AXI总线的相关端口,而右侧的输出端口就是PWM波的输出端口。将这个输出端口通过约束文件连接到Zybo板上的某一个PMOD端口,就可以在该PMOD端口处输出PMW波了。
USB端口的连接
由于vivado中自带了IP核——Zynq7 Processing System。该IP核可以管理开发板上的ARM处理器和其他标准输入输出接口的连接,比如USB接口、网线接口以及板上的AXI、SPI总线等。所以,只需要在这个IP核内勾选USB接口的相关选项,就完成了USB端口和ARM核的连接了,整体来讲是比较简单的。
Zynq7 Processing System核的设置界面如下图所示,可以看到这里已经做好了USB接口的连接。
做好USB接口连接的该IP核,外观上会多出一个输出端口USBIND_0,如下图所示:
最终成果
经过上面的设计,可以得到本系统的硬件电路。之后嵌入式系统启动需要的硬件比特流文件和设备树文件,就基于这个硬件电路通过vivado的自带工具生成。
至于如何在嵌入式系统中操作这两块硬件,需要的就是对应这两块硬件的Linux驱动了。在下一节,会详细地介绍这两块硬件的Linux驱动的设计和编译的过程。
附录
博主的Vivado工程(vivado版本为18.2。此外,因为这个工程还用来做别的设计,所以并不止有PWM模块,这个工程中不是所有模块都是用来进行本系统的设计的,请各位使用的时候注意一下)
提取码:zagm
下章预告
有了基本的硬件连接,现在需要的是让嵌入式系统能够找到这些硬件。而驱动文件,就是用来让操作系统找到具体硬件必不可少的文件。下章将会重点介绍rtl8188和舵机的驱动文件的生成过程。