本帖最后由 feihufuture 于 2021-8-10 19:39 编辑
#申请原创# @21小跑堂最近我们家的麒麟看见别人家孩子的酷车玩具,跑到爸爸跟前也要一辆。。。
好歹爸爸也是电子出身,这种电子玩具怎么能去买呢,而且买来的小车,要么傻瓜,要么功能不全,还不如DIY,还能跟麒麟一起做,让孩子享受一把电子开发的乐趣!
说干就干!
第一步:选择小车框架,+四个舵机,价格25元。
第二步,选择MCU。
家里找啊找,全是一些STM32的成品板子,太大,不适合。
最后在萝筐里找到了两个FPGA的核心板,很小,芯片型号XC6SLX25。
也好,虽然用的有点奢侈,每个核心板的价格100元,
但是,FPGA处理实时图像视频很好。
两个核心板,正好,一个放在小车上,另一个放在遥控器上。
第三步,选择音乐模块。
功能要足够全面,可以随意下载,选啊选,这个不错;
通过串口,FPGA可以跟模块任意操作。
引脚名称 | | | | | | | IO触发模式下为输入引脚IO0;UART控制模式下为TX引脚,连接控制端(MCU)的RX | | IO触发模式下为输入引脚IO1;UART控制模式下为RX引脚,连接控制端(MCU)的TX | | | | | | IO触发模式输入引脚IO4;One_Line一线串口控制模式数据接收引脚 | | | | | | | | 播放曲目时输出低电平(0V),播放结束输出高电平(3.3V) | | |
拨码开关模式配置
控制指令
第四步,选择远程通信模块;蓝牙可以,遥控器,手机都可兼容;
配置好,自动连接,即可透传,方便。
管脚序号 | 管脚名称 | 管脚说明 | 1 | UART_CTS | 悬空 | 2 | UART_TX | 串口数据输出 | 3 | UART_CTS | 悬空 | 4 | UART_RX | 串口数据输入 | 5 | P2_1 | 调试数据口 | 6 | P2_2 | 调试时钟口 | 7 | SCL | SCL | 8 | SDA | SDA | 9 | VCC | 3.3v | 10 | NC | NC | 11 | RESETB | 低电平复位, 至少5ms | 12 | GND | 地 | 13 | P1_1 | 蓝牙连接指示口( 未连接为低, 连接上为高) | 14 | P1_0 | NC | 15 | P0_7 | LED灯管脚(未连接闪烁, 连接常亮) | 16 | P0_6 | 断开连接引脚(200ms 低电脉冲断开) |
第五步,选择跟随模块。
用超声,比较简单一点。直接测距,精度高,安装方便。
最大接收距离 | >5M | 最小接收距离 | <3CM | 最大接收角度 | 180° (会随着距离增大角度变小) |
串口模式: 通信波特率为 115200, 接收模块 OUT 端直接使用串口输出距离,
输出频率是一秒发送 50 个数据包, 数据格式是 0XA5 加上两个字节的数据,
数据单位是毫米。 例如: 输出 0XA5 0X55 0X11, 0X5511 就是距离, 单位毫米。
引脚 | 定义 | VCC | 电源(DC 5V) | GND | 地 | OUT | 输出信号端 | NC | 悬空 |
第六步,选择舵机驱动L298N。
为了提高小车的马力,加上两个L298N,前轮+后轮。
第七步,选择电源。
第八步,其他附属内容。
导线若干;
开关若干;
电压转换芯片;
电平转换芯片;
电容;
胶枪;
电烙铁。
OK,先用上面的内容做个简单的,等麒麟满意了,咱再加上摄像头等其他功能,发挥FPGA的长处,总之,重在体验,让孩子感受乐趣!孩子是爸爸的好帮手!(透露一下,我们家麒麟五岁,认识常用类型的电阻电容和芯片,能焊接,能用列子夹住0402封装的电阻电容哟,最近在学习图形编程,相信麒麟未来比爸爸强!)
作为电子工程师的你们,为了你们的孩子,也行动起来把!
目前常用的主要是串口控制,附上代码!
module music_ctrl
(
input SysClk ,
input Rst ,
input Rx ,
output Tx ,
input MusicCtrlValid ,
input [7:0] MusicCtrlData
);
wire RxClk;
wire ByteRxDone;
wire [7:0] ByteRx;
reg ByteRxRdDone;
wire TxClk;
reg TxTriger;
wire ByteTxDone;
wire [7:0] ByteTx;
uart_top #
(
.sys_clk_freq ( 50000000 ),
.baud_rate ( 9600 )
)
uart_top
(
.Rs232SetRst ( Rst ),
.Rs232RxRst ( Rst ),
.Rs232TxRst ( Rst ),
//
.SysClk ( SysClk ),
//
.rx ( Rx ),
.tx ( Tx ),
//
.RxClk ( RxClk ),
.ByteRxDone ( ByteRxDone),
.ByteRx ( ByteRx),
.ByteRxRdDone ( ByteRxRdDone),
//
.TxClk ( TxClk),
.TxTriger ( TxTriger),
.ByteTxDone ( ByteTxDone),
.ByteTx ( ByteTx)
);
localparam TX_IDLE = 4'd0 ;
localparam SEND_1ST_BYTE = 4'd1 ;
localparam SEND_1ST_BYTE_WAIT = 4'd2 ;
localparam SEND_2ST_BYTE = 4'd3 ;
localparam SEND_2ST_BYTE_WAIT = 4'd4 ;
localparam SEND_3ST_BYTE = 4'd5 ;
localparam SEND_3ST_BYTE_WAIT = 4'd6 ;
localparam SEND_4ST_BYTE = 4'd7 ;
localparam SEND_4ST_BYTE_WAIT = 4'd8 ;
reg [3:0] SendSm;
reg [31:0] SendData;
//MusicCtrlData[7] : 1 music operation, button up
//MusicCtrlData[6] : falling edge, play current music; rising edge, stop current music;
//MusicCtrlData[5] : select music or vol, up is music.
//MusicCtrlData[4] : falling edge, next music;music vol+;
//MusicCtrlData[3] : falling edge, last music;music vol-;
reg MusicCtrlDatabit6D1;
reg MusicCtrlDatabit4D1;
reg MusicCtrlDatabit3D1;
always [url=home.php?mod=space&uid=72445]@[/url] ( posedge TxClk )
begin
MusicCtrlDatabit6D1 <= MusicCtrlData[6] ;
MusicCtrlDatabit4D1 <= MusicCtrlData[4];
MusicCtrlDatabit3D1 <= MusicCtrlData[3];
end
always @ ( posedge TxClk )
begin
if( Rst ) SendSm <= TX_IDLE;
else
case( SendSm )
TX_IDLE : if( MusicCtrlData[7] )
begin
if( MusicCtrlDatabit6D1 != MusicCtrlData[6] ) SendSm <= SEND_1ST_BYTE;
else if( ~MusicCtrlData[4] & MusicCtrlDatabit4D1 ) SendSm <= SEND_1ST_BYTE;
else if( ~MusicCtrlData[3] & MusicCtrlDatabit3D1 ) SendSm <= SEND_1ST_BYTE;
end
SEND_1ST_BYTE : SendSm <= SEND_1ST_BYTE_WAIT;
SEND_1ST_BYTE_WAIT : if( ByteTxDone ) SendSm <= SEND_2ST_BYTE;
SEND_2ST_BYTE : SendSm <= SEND_2ST_BYTE_WAIT;
SEND_2ST_BYTE_WAIT : if( ByteTxDone ) SendSm <= SEND_3ST_BYTE;
SEND_3ST_BYTE : SendSm <= SEND_3ST_BYTE_WAIT;
SEND_3ST_BYTE_WAIT : if( ByteTxDone ) SendSm <= SEND_4ST_BYTE;
SEND_4ST_BYTE : SendSm <= SEND_4ST_BYTE_WAIT;
SEND_4ST_BYTE_WAIT : if( ByteTxDone ) SendSm <= TX_IDLE;
default : ;
endcase
end
//localparam CHECK_PLAY_CMD = 32'haa0100ab;
localparam PLAY_CMD = 32'haa0200ac;
localparam STOP_CMD = 32'haa0400ae;
localparam LAST_CMD = 32'haa0500af;
localparam NEXT_CMD = 32'haa0600b0;
localparam VOLU_CMD = 32'haa1400be;
localparam VOLD_CMD = 32'haa1500bf;
//localparam CHECK_DISK_CMD = 32'haa0900b3;
//localparam CHECK_DISK_PLAY_CMD = 32'haa0a00b4;
//localparam CHECK_MUSIC_TOTAL_CMD = 32'haa0c00b6;
//localparam CHECK_MUSIC_CUR_CMD = 32'haa0d00b7;
assign ByteTx = SendData[31:24];
always @ ( posedge TxClk )
begin
case( SendSm )
TX_IDLE : begin TxTriger <= 1'b0; SendData <= 32'b0; end
SEND_1ST_BYTE : begin
TxTriger <= 1'b1;
if( MusicCtrlData[6] ) SendData <= STOP_CMD;
else if( ~MusicCtrlData[4] )
begin
if( MusicCtrlData[5] ) SendData <= LAST_CMD;
else SendData <= VOLU_CMD;
end
else if( ~MusicCtrlData[3] )
begin
if( MusicCtrlData[5] ) SendData <= NEXT_CMD;
else SendData <= VOLD_CMD;
end
else SendData <= PLAY_CMD;
end
SEND_2ST_BYTE : begin TxTriger <= 1'b1; SendData <= {SendData[23:0],8'b0}; end
SEND_3ST_BYTE : begin TxTriger <= 1'b1; SendData <= {SendData[23:0],8'b0}; end
SEND_4ST_BYTE : begin TxTriger <= 1'b1; SendData <= {SendData[23:0],8'b0}; end
default : TxTriger <= 1'b0;
endcase
end
endmodule
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
module uart_top #
(
parameter sys_clk_freq = 50000000,
parameter baud_rate = 115200
)
(
//system signal
input Rs232SetRst,
input Rs232RxRst,
input Rs232TxRst,
//
input SysClk ,
//
input rx,
output tx,
output RxClk,
output TxClk,
output ByteRxDone,
output [7:0] ByteRx,
input ByteRxRdDone,
input TxTriger,
output ByteTxDone,
input [7:0] ByteTx
);
/*
wire [7:0] ByteRx;
reg [4:0] cnt1;
wire TxTrigerAux;
always @ (posedge RxClk)
begin
if(Rs232RxRst) cnt1 <= 5'd0;
else if(cnt1 == 5'd25) cnt1 <= 5'd0;
else if(cnt1 != 5'd0) cnt1 <= cnt1 + 1;
else if(ByteRxDone) cnt1 <= cnt1 + 1;
end
assign TxTrigerAux = (cnt1 != 5'd0) ? 1'b1 :1'b0;
reg TxTrigerAuxD1,TxTrigerAuxD2,TxTrigerAuxD3;
reg [7:0] ByteRxD1,ByteRxD2;
always @ (posedge TxClk)
begin
TxTrigerAuxD1 <= TxTrigerAux;
TxTrigerAuxD2 <= TxTrigerAuxD1;
TxTrigerAuxD3 <= TxTrigerAuxD2;
ByteRxD1 <= ByteRx;
ByteRxD2 <= ByteRxD1;
end
wire TxTriger = ~TxTrigerAuxD3 & TxTrigerAuxD2;
wire [7:0] ByteTx = ByteRxD2;
reg TxTrigerD1, TxTrigerD2 , TxTrigerD3;
always @ (posedge RxClk)
begin
TxTrigerD1 <= TxTriger;
TxTrigerD2 <= TxTrigerD1;
TxTrigerD3 <= TxTrigerD2;
end
wire ByteRxRdDone = TxTrigerD3 & ~TxTrigerD2;
*/
//------------------------------------------------------------------------------------------------
uart_sets #
(
.sys_clk_freq ( sys_clk_freq ),
.baud_rate ( baud_rate )
)
uart_system_setting
(
.sys_clk ( SysClk ),
.rst ( Rs232SetRst ),
.rx_clk ( RxClk ),
.tx_clk ( TxClk )
);
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
uart_rx uart_rx_logic
(
.clk16x ( RxClk ),
.rst ( Rs232RxRst ),
.rx_data ( rx ),
.ByteRxDone ( ByteRxDone ),
.ByteRx ( ByteRx ),
.ByteRxRdDone ( ByteRxRdDone )
);
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
uart_tx uart_tx_logic
(
.clk1x ( TxClk ),
.rst ( Rs232TxRst ),
.mcu_data ( ByteTx ),
.TxTriger ( TxTriger ),
.tx_data ( tx ),
.ByteTxDone ( ByteTxDone )
);
//------------------------------------------------------------------------------------------------
endmodule
module uart_sets
#
(
parameter sys_clk_freq = 50000000,
parameter baud_rate = 115200
)
(
input sys_clk ,
input rst,
output rx_clk,
output tx_clk
);
//
//
reg [15:0] tx_clk_div = 0;
reg [15:0] rx_clk_div = 0;
reg tx_clk_r = 0;
reg rx_clk_r = 0;
wire [15:0] div_tx;
wire [15:0] div_rx;
//the frequecy of sending clock must be the same as baud_rate,
//"sys_clk_freq/baud_rate" is a divider,
//"2" means two jump to guarantee the frequecy of tx_clk,
//"16" is about the protocol of receiving clock in rs232.
assign div_tx = sys_clk_freq/(baud_rate*2);
assign div_rx = sys_clk_freq/(baud_rate*2*16);
assign tx_clk = tx_clk_r;
assign rx_clk = rx_clk_r;
//data sending clock
always @ ( posedge sys_clk )
begin
if( rst ) tx_clk_div <= 0;
else
begin
if(tx_clk_div < (div_tx - 1))
begin
tx_clk_div <= tx_clk_div + 1'b1;
tx_clk_r <= tx_clk_r;
end
else
begin
tx_clk_div <= 0;
tx_clk_r <= ~tx_clk_r;
end
end
end
//data receiving clock
always @ ( posedge sys_clk )
begin
if( rst ) rx_clk_div <= 0;
else
begin
if(rx_clk_div < (div_rx - 1))
begin
rx_clk_div <= rx_clk_div + 1'b1;
rx_clk_r <= rx_clk_r;
end
else
begin
rx_clk_div <= 0;
rx_clk_r <= ~rx_clk_r;
end
end
end
endmodule
`timescale 1ns / 1ps
/////////////////////////////////////////////
module uart_rx
(
input clk16x,
input rst,
input rx_data,
output ByteRxDone,
output [7:0] ByteRx,
input ByteRxRdDone
);
//
reg [3 : 0] rx_shift = 0;
reg frame_valid = 0;
reg [3 : 0] rx_cnt1 = 0;
reg sampling7 = 1;
reg sampling8 = 1;
reg sampling9 = 1;
reg [3 : 0] data_cnt = 0;
reg [7 : 0] rx_buf = 0;
//
wire res;
reg ByteRxDoneReg = 0;
reg [7:0] ByteRxReg;
//------------------------------------------------------------------------------------------------
//res shifter
always @ (posedge clk16x)
begin
if(rst) rx_shift <= 4'b0;
else if(frame_valid ) rx_shift <= 4'b0;
else rx_shift <= {rx_shift[2:0],rx_data};
end
//frame valid
always @ (posedge clk16x)
begin
if(rst) frame_valid <= 1'b0;
else if(rx_shift == 4'b1100) frame_valid <= 1'b1;
else if(data_cnt == 4'd9) frame_valid <= 1'b0;
end
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//---------------------------------------data sampling--------------------------------------------
//bit sampling counter
always @ (posedge clk16x)
begin
if(rst) rx_cnt1 <= 4'd0;
else if( frame_valid ) rx_cnt1 <= rx_cnt1 + 1'b1;
else rx_cnt1 <= 4'd0;
end
always @ (posedge clk16x)
begin
if(rst) begin
sampling7 <= 1;
sampling8 <= 1;
sampling9 <= 1;
end
else if(rx_cnt1 == 4'd6) sampling7 <= rx_data;
else if(rx_cnt1 == 4'd7) sampling8 <= rx_data;
else if(rx_cnt1 == 4'd8) sampling9 <= rx_data;
end
//caculate the sampling result
assign res = (sampling7&&sampling8)^(sampling8&&sampling9)
^(sampling7&&sampling9);
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//--------------------------------------data receive----------------------------------------------
always @ (posedge clk16x)
begin
if(rst) data_cnt <= 4'd0;
else if(frame_valid)
begin
if(&rx_cnt1) data_cnt <= data_cnt + 1'b1;
end
else data_cnt <= 4'd0;
end
//read interrupt
assign ByteRxDone = ByteRxDoneReg;
always @ (posedge clk16x)
begin
if(rst) ByteRxDoneReg <= 0;
else if( (data_cnt == 4'd8) && (rx_cnt1 == 4'd11) ) ByteRxDoneReg <= 1;
else ByteRxDoneReg <= 0;
end
//rx_buf
//when frame_valid is high, and data_cnt count as "0",
//it is the frame start bit "0"
assign ByteRx = ByteRxReg;
always @ (posedge clk16x)
begin
if(rst) rx_buf <= 8'd0;
else if( frame_valid )
begin
if( data_cnt != 4'b0 )
begin
if(rx_cnt1 == 4'd10) rx_buf <= {res, rx_buf[7:1]};
end
end
end
always @ (posedge clk16x)
begin
if(rst) ByteRxReg <= 8'd0;
else if(ByteRxRdDone) ByteRxReg <= 8'd0;
else if( frame_valid )
begin
if( data_cnt == 4'd8 )
begin
if(rx_cnt1 == 4'd11) ByteRxReg <= rx_buf;
end
end
end
//assign chipscope_bus = { 213'b0 ,res , rx_buf,rx_cnt1,data_cnt,frame_valid};
endmodule
`timescale 1ns / 1ps
//------------------------------------------------------------------------------------------------
module uart_tx(
input clk1x,
input rst,
input [7 : 0] mcu_data,
input TxTriger,
output tx_data,
output ByteTxDone
);
(*keep = "true"*)reg [7 : 0] tx_buf = 0;
reg [3 : 0] tx_cnt = 0;//transmit counter
reg data_valid = 0;//transmit data valid
reg tx_data_r = 1;
reg TxTrigerD1 = 0;
reg ByteTxDoneReg = 0;
//------------------------------------------------------------------------------------------------
always @ (posedge clk1x)
begin
if(rst) TxTrigerD1 <= 1'b0;
else TxTrigerD1 <= TxTriger;
end
//transmit data buf
always @ (posedge clk1x)
begin
if(rst) tx_buf <= 8'd0;
else if(TxTrigerD1 & ~TxTriger) tx_buf <= mcu_data;
end
always @ (posedge clk1x)
begin
if(rst) data_valid <= 1'b0;
else if(tx_cnt == 4'd8) data_valid <= 1'b0;
else if(TxTrigerD1 & ~TxTriger) data_valid <= 1'b1;
end
//transmit counter
always @ (posedge clk1x)
begin
if(rst) tx_cnt <= 4'd0;
else if( data_valid ) tx_cnt <= tx_cnt + 1'b1;
else tx_cnt <= 4'd0;
end
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
assign tx_data = tx_data_r;
always @ (posedge clk1x)
begin
if(rst) tx_data_r <= 1;
else
case(tx_cnt)
4'd1: tx_data_r <= 0;
4'd2: tx_data_r <= tx_buf[0];
4'd3: tx_data_r <= tx_buf[1];
4'd4: tx_data_r <= tx_buf[2];
4'd5: tx_data_r <= tx_buf[3];
4'd6: tx_data_r <= tx_buf[4];
4'd7: tx_data_r <= tx_buf[5];
4'd8: tx_data_r <= tx_buf[6];
4'd9: tx_data_r <= tx_buf[7];
default: tx_data_r <= 1;
endcase
end
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
assign ByteTxDone = ByteTxDoneReg;
always @ (posedge clk1x)
begin
if(rst) ByteTxDoneReg <= 0;
else if(tx_cnt == 4'd9) ByteTxDoneReg <= 0;
else if(tx_cnt == 4'd8) ByteTxDoneReg <= 1;
end
//------------------------------------------------------------------------------------------------
endmodule
|
|