当前位置:   article > 正文

基于FPGA的循迹小车,控制器:Xilinx-Ego1_fpga+循迹小车

fpga+循迹小车

记录FPGA(Xilinx-Ego1)学习调试时遇到的坑和Bug解决方法,以及Vivado开发FPGA的代码编写技巧,为之后复习留个底子。通篇文章均用单片机的开发思路去开发FPGA,只为帮助读者能快速上手,开发语言为最常用的Verilog。

关于如何使用Vivado创建一个工程见Ego1使用说明文档,很详细,详细见 依元素 官网:EGO1 (e-elements.com)

点击资源,然后注册邮箱,下载资料包,里面有很多例程:

源码或者现成的工程见 3c-EGo1配置实验vivado2017.2_v1.2 文件夹里的source与project文件夹

学习了基础操作后,教你怎么写代码,先对整个代码有个宏观认识:

         这是一个工程的文件夹,里面只有lab5_uart.srcs文件夹里的代码是自己写或者创建的,其余是你在仿真综合时,vivado自动生成的;代码分两大部分:约束文件(.xdc)和源文件(.v)

       讲解一下我对Vivado编写FPGA工程的认识:

        源文件(.v)文件编写逻辑为分层(top层和模块层)编写,将你需要用到的硬件的驱动代码设计成一个模块,模块即有输入和输出,比方说我要让一个数码管按一定的频率亮,那就需要定时器,就设计一个时钟作为输入,当然,你想复位的话,还可以设计一个按键(rst)作为输入,然后输出呢就是数码管的8个段(8段LED),设计好输入输出后就是你的逻辑编写,即你什么时候让数码管亮,比如我1s让数码管亮一次,1s后再灭一次,就写相应的逻辑,当然写逻辑就要用到相关的语法,语法就去菜鸟教程看verilog语言教程就行;然后是需要即需要定义一个top层,将你所有模块的输入和输出在这个模块进行例化(相当于单片机的引脚初始化)。top层是在你设计的功能模块在2个及以上时编写,这样你看起来也比较方便,系统所有的输入输出都在top层,也方便你查看。

        约束文件的作用相当于在使用单片机时对引脚进行定义,这里是将你源文件的top文件里设计的输入和输出约束到相关的引脚上,虽然像时钟,数码管这样的输入输出你看不见引脚,但你可以这样去理解,就是使用FPGA驱动硬件的逻辑就是:你设计输入和输出,然后将他们约束到相关硬件上或者引脚上,然后引脚再去接硬件。

        那么我这个工程呢就是关于Ego1的循迹小车,所有硬件驱动代码都由ego1写成他具备以下功能:

       基础功能:能用Ego1输出PWM波控制直流编码器电机和舵机转动,能用Ego1读取红外循迹模块的循迹反馈信号,能用Ego1的输入捕获采集编码器的信号实现电机转速测量,能用Ego1输出特定频率的方波驱动无缘蜂鸣器播放音乐,能用Ego1的数码管显示车速。

        终极功能:小车上电后能在赛道上一边播放车载音乐一边进行自动循迹。

系统硬件配置设计

(根据实验的需要,论述平台的系统硬件配置,包括硬件选择、硬件配套、网络连接和参数配置等

(1)控制器:Xilinx-Ego1(FPGA)

(2)执行元件:舵机

(3)执行元件:编码器电机

(4)执行元件:无源蜂鸣器

(5)测量元件:循迹模块(5路红外传感器)

(6)电机驱动:tb6612fng

(7)功率放大单元:L298N

(8)稳压模块:

其中舵机和电机模块的代码展示如下:(因为都是PWM,所以写在一起了)

时钟主频:clk约束到了P17,具体是50MHz还是100MHz我忘了

  1. `timescale 1ns / 1ps
  2. module pwm_cont(
  3. clk,
  4. sw7,
  5. rst_n,
  6. da_in,
  7. pwm_out,
  8. pwm_outz,
  9. hw_in,
  10. djfz1,
  11. djfz2,
  12. djfy1,
  13. djfy2,
  14. pwm_outy
  15. );
  16. input clk;
  17. input rst_n;
  18. input sw7;
  19. input [6:0] da_in;
  20. output reg djfz1;
  21. output reg djfz2;
  22. output reg djfy1;
  23. output reg djfy2;
  24. output reg pwm_out;
  25. output reg pwm_outz;
  26. output reg pwm_outy;
  27. input [4:0] hw_in;
  28. parameter s=1000_000,//20ms-----min:s4(左偏) max:s7(右偏) 中间:s1
  29. s7=190_000,//4ms----右满
  30. //s6=190_000,//3.5ms----270
  31. s5=185_000,//3ms----225
  32. s0=175_000,//2.5ms----右
  33. s1=150_000,//2ms---中间
  34. s2=125_000,//1.5ms----90
  35. s3=95_000,//1ms-----45 100_000
  36. s4=80_000;//0.5ms---0 左满
  37. reg [31:0] cnt_r;
  38. reg [31:0] cnt;
  39. reg [31:0] cnt_r1;
  40. reg [31:0] cnt1;
  41. reg biaoqian;
  42. reg wr_reg,wr_up,wr_down;
  43. always@(posedge clk or posedge rst_n) begin
  44. if(rst_n)
  45. begin
  46. wr_reg <= 1'b0;
  47. wr_up <= 1'b0;
  48. wr_down <= 1'b0;
  49. cnt_r1 <= s1;
  50. end
  51. else
  52. begin
  53. wr_reg <= sw7;
  54. wr_up <= sw7&(~wr_reg);//sw1上升沿检测,选择循迹模式
  55. wr_down <= ~sw7&wr_reg;
  56. if(wr_up)
  57. biaoqian=1;
  58. if(wr_down)
  59. biaoqian=0;
  60. if(biaoqian==1)
  61. begin
  62. djfz1=0;
  63. djfz2=1;
  64. djfy1=0;
  65. djfy2=1;
  66. case(hw_in)
  67. 5'b00000:
  68. begin
  69. //cnt_r1 <= s1;//中间
  70. biaoqian<=0;
  71. end
  72. //5'b11111: cnt_r1 <= s1;//中间
  73. 5'b11000: cnt_r1 <= s7;//右转s7
  74. 5'b11110: cnt_r1 <= s7;//右转s7满
  75. 5'b11100: cnt_r1 <= s5;//左转
  76. 5'b11101: cnt_r1 <= s0;//左转
  77. 5'b11001: cnt_r1 <= s1;//中间
  78. 5'b11011: cnt_r1 <= s1;//中间
  79. 5'b10011: cnt_r1 <= s1;//中间
  80. 5'b10111: cnt_r1 <= s2;//右转
  81. 5'b00111: cnt_r1 <= s3;//右转
  82. 5'b01111: cnt_r1 <= s4;//左转s4满
  83. 5'b00011: cnt_r1 <= s4;//右转
  84. endcase
  85. end
  86. if(!biaoqian)
  87. begin
  88. djfz1=0;
  89. djfz2=0;
  90. djfy1=0;
  91. djfy2=0;
  92. end
  93. end
  94. end
  95. //速度选择
  96. always@(posedge clk or posedge rst_n)begin
  97. if(rst_n)
  98. begin
  99. cnt_r <= 31'd0;
  100. end
  101. else
  102. begin
  103. // case(da_in)//速度选择
  104. // 7'b0000001: cnt_r <= s/20;//90
  105. // //8'b00000011: cnt_r <= s4;//0
  106. // 7'b0000010: cnt_r <= s/15;//45
  107. // 7'b0000100: cnt_r <= s/10;//90
  108. // 7'b0001000: cnt_r <= s/8;//135
  109. // 7'b0010000: cnt_r <= s/4;//180
  110. // 7'b0100000: cnt_r <= s/2;//225
  111. // 7'b1000000: cnt_r <= s;//满速
  112. case(hw_in)
  113. 5'b11000: cnt_r <= s/8;//右转s7
  114. 5'b11110: cnt_r <= s/7;//右转s7满
  115. 5'b11100: cnt_r <= s/7;//左转
  116. 5'b11101: cnt_r <= s/7;//左转
  117. 5'b11001: cnt_r <= s/5;//中间
  118. 5'b11011: cnt_r <= s/5;//中间
  119. 5'b11111: cnt_r <= s/5;//中间
  120. 5'b10011: cnt_r <= s/5;//中间
  121. 5'b10111: cnt_r <= s/7;//右转
  122. 5'b00111: cnt_r <= s/7;//右转
  123. 5'b01111: cnt_r <= s/7;//左转s4
  124. 5'b00011: cnt_r <= s/7;//右转
  125. 5'b00000: cnt_r <= 0;//停止
  126. default: cnt_r <= s/8;//停止
  127. endcase
  128. end
  129. end
  130. always@(posedge clk or negedge rst_n)begin
  131. if(rst_n)
  132. begin
  133. cnt <= 31'd0;
  134. cnt1 <= 31'd0;
  135. end
  136. else if(cnt >= s)
  137. begin
  138. cnt <= 31'd0;
  139. cnt1 <= 31'd0;
  140. end
  141. else
  142. begin
  143. cnt <= cnt + 1'b1;
  144. cnt1 <= cnt1 + 1'b1;
  145. end
  146. end
  147. always@(posedge clk or negedge rst_n)begin
  148. if(rst_n)
  149. begin
  150. pwm_outz <= 1'b0;
  151. pwm_outy <= 1'b0;
  152. end
  153. else if(cnt <= cnt_r)
  154. begin
  155. pwm_outz <= 1'b1;
  156. pwm_outy <= 1'b1;
  157. if(wr_down)
  158. begin
  159. pwm_outz <= 1'b0;
  160. pwm_outy <= 1'b0;
  161. end
  162. end
  163. else
  164. begin
  165. pwm_outz <= 1'b0;
  166. pwm_outy <= 1'b0;
  167. end
  168. end
  169. always@(posedge clk or negedge rst_n)begin
  170. if(rst_n)
  171. begin
  172. //pwm_out<= s1;//中间
  173. pwm_out <= 1'b0;
  174. end
  175. else if(cnt1 <= cnt_r1)
  176. begin
  177. pwm_out <= 1'b1;
  178. end
  179. else
  180. begin
  181. pwm_out <= 1'b0;
  182. end
  183. end
  184. endmodule

代码写好了之后需要生成bit流,当然这还不够,我们需要让小车不连接电脑去跑这就需要将代码固化到Ego1里面,下面是代码固化的方法:(13条消息) vivado纯verilog代码固化程序_Kiss丶小坏-CSDN博客

简单步骤:当然你直接生成bit流之后

选择Tools——>Generate Memory Configuration File,也可以打开hardware之后右键找到。

注:这一步是产生mcs文件进行程序加载,同时也会产生prm文件(也可以不需要,例如直接在生成bit文件时,勾选bin文件,最后一步时直接加载bin文件)。详情看文档去。

在这里插入图片描述

配置:

在这里插入图片描述 如果报错就将Interface改成报错要求的值

之后是Add Configuration Memory Device。三种方法:

方法1.

在这里插入图片描述

方法2.

在这里插入图片描述

方法3.

在这里插入图片描述

接下来,出现如下界面,选择flash芯片。

在这里插入图片描述

如果报错就选择n25q64-3.3v-spi-xi_x2_x4

最后一步,在选择芯片之后会出现如下界面,也就是加载Flash,固化程序。在这里插入图片描述 

整个工程见如下链接:

Xilinx-Ego1(FPGA)寻迹小车-硬件开发文档类资源-CSDN文库

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/893161
推荐阅读
相关标签
  

闽ICP备14008679号