赞
踩
通过串口调试助手,使用串口发送电脑指令到fpga开发板,来控制led灯的工作状态。
通过三个模块来实现 串口控制led闪烁:
1.uart的数据接收模块:将用户数据通过串口调试助手发到fpga
2.串口命令模块:将uart接受模块的数据通过该模块,通过一个自定义协议来发送led灯所需的控制信号
3.led工作状态的控制模块:闪烁时间和闪烁状态由用户指定(Time,Ctrl[on/off])
自定义协议如下:
类似于起始位和停止位的判定,通过数据的移位和比较,最后实现中间命令模块的编写,从而实现串口控制led灯(uart_rx模块和led_ctrl_time模块见前面所写)
PS:代码中Time的发送,是先发的高位再发的低位。
- `timescale 1ns / 1ps
-
- module uart_cmd(
- clk ,
- rst ,
- rx_data ,
- rx_done ,
- Time ,
- ctrl
- );
- input clk ;
- input rst ;
- input[7:0] rx_data ;
- input rx_done ;
- output[31:0] Time ;
- output[7:0] ctrl ;
-
- reg[7:0] data_str[7:0];
- reg[31:0] r_Time ;
- reg[7:0] r_ctrl ;
- assign Time =r_Time ;
- assign ctrl =r_ctrl ;
-
- always@(posedge clk ,negedge rst)begin
- if(!rst)begin
- data_str[0] <= 0;
- data_str[1] <= 0;
- data_str[2] <= 0;
- data_str[3] <= 0;
- data_str[4] <= 0;
- data_str[5] <= 0;
- data_str[6] <= 0;
- data_str[7] <= 0;
- end
- else if(rx_done)begin
- data_str[0] <= rx_data;
- data_str[1] <= data_str[0];
- data_str[2] <= data_str[1];
- data_str[3] <= data_str[2];
- data_str[4] <= data_str[3];
- data_str[5] <= data_str[4];
- data_str[6] <= data_str[5];
- data_str[7] <= data_str[6];
- end
- else begin
- data_str[0] <= data_str[0];
- data_str[1] <= data_str[1];
- data_str[2] <= data_str[2];
- data_str[3] <= data_str[3];
- data_str[4] <= data_str[4];
- data_str[5] <= data_str[5];
- data_str[6] <= data_str[6];
- data_str[7] <= data_str[7];
- end
- end
-
- always@(posedge clk ,negedge rst)begin
- if(!rst)begin
- r_Time <= 32'd0;
- r_ctrl <= 8'd0;
- end
- else if((data_str[0] == 8'hf0) && (data_str[6]==8'h05) && (data_str[7]==8'h55))begin
- r_Time <= {data_str[5],data_str[4],data_str[3],data_str[2]};
- r_ctrl <= data_str[1];
- end
- else begin
- r_Time <= 32'd0;
- r_ctrl <= 8'd0;
- end
- end
- endmodule
- `timescale 1ns / 1ps
-
- module uart_ctrl_led(
- clk ,
- rst ,
- uart_rx ,
- led
- );
- input clk ;
- input rst ;
- input uart_rx;
- output led ;
-
- wire[7:0] data ;
- wire rx_done;
- wire[31:0] Time ;
- wire[7:0] ctrl ;
-
- uart_rx_byte uart_rx_byte_u0(
- .clk ( clk ),
- .rst ( rst ),
- .baud_set ( 7 ),
- .uart_rx ( uart_rx),
- .data ( data ),
- .rx_done (rx_done )
- );
-
- uart_cmd uart_cmd_u0(
- .clk ( clk ),
- .rst ( rst ),
- .rx_data ( data ),
- .rx_done ( rx_done),
- .Time ( Time ),
- .ctrl ( ctrl )
- );
-
- led_ctrl_time led_ctrl_time_u0(
- .clk ( clk ),
- .rst ( rst ),
- .Ctrl ( ctrl ),
- .Time ( Time ),
- .led ( led )
- );
- endmodule
- `timescale 1ns / 1ps
-
-
- module uart_ctrl_led_tb();
- reg clk ;
- reg rst ;
- reg uart_rx ;
- wire led ;
-
-
- uart_ctrl_led uart_ctrl_led_1(
- .clk ( clk ),
- .rst ( rst ),
- .uart_rx ( uart_rx ),
- .led ( led )
- );
-
- initial clk = 0;
- always #10 clk = ~clk;
-
- initial begin
- rst = 0;
- #201;
- rst = 1;
- #200;
- uart_tx_byte(8'h55);
- #90000; //@(posedge rx_done);
- #5000;
- uart_tx_byte(8'h05);
- #90000;
- #5000;
- uart_tx_byte(8'h12);
- #90000;
- #5000;
- uart_tx_byte(8'h34);
- #90000;
- #5000;
- uart_tx_byte(8'h56);
- #90000;
- #5000;
- uart_tx_byte(8'h78);
- #90000;
- #5000;
- uart_tx_byte(8'h9a);
- #90000;
- #5000;
- uart_tx_byte(8'hf0);
- #90000;
- #5000;
- $stop;
- end
- task uart_tx_byte;
- input [7:0]tx_data;
- begin
- uart_rx = 1;
- #20;
- uart_rx = 0;
- #8680;
- uart_rx = tx_data[0];
- #8680;
- uart_rx = tx_data[1];
- #8680;
- uart_rx = tx_data[2];
- #8680;
- uart_rx = tx_data[3];
- #8680;
- uart_rx = tx_data[4];
- #8680;
- uart_rx = tx_data[5];
- #8680;
- uart_rx = tx_data[6];
- #8680;
- uart_rx = tx_data[7];
- #8680;
- uart_rx = 1;
- #8680;
- end
- endtask
- endmodule
在此基础上,生成了bit流,上班运行:
实现0.5s传输一个数据,即Time = 25,000,000 对应的16进制数为01 7D 78 40 这样边设置完成了TIme[31:0]的设置,再将Ctrl ==AA(1010_1010)来控制led灯一亮一灭。
即串口发送 55 05 01 7D 78 40 A0 f0 ,这样便完成了串口控制led闪烁。
但是!!实际工程上板之后发现等了好久led灯才开始闪烁,在闪烁之后,再将ctrl== 1111_0000,使得led闪烁变慢,最后rst复位,都能够直接实现。
通过小梅哥的视频讲解得知:
所以在led闪烁的控制中,我们将计数器的清零条件由== 变为 >= ,这样就解决了这样的问题。!!!赞
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。