在之前的文章中具体控制代码已经全部进行了分析与解释,顶层模块进行模块的输入输出的定义、内部变量的定义、模块的实例化与蓝牙信号的判断。
代码如下:
module top_modlue(
input clk,//系统时钟
input reset,//复位按键
input rx,//蓝牙接收
input wire [3:0] signal,//红外信号
input wire Echo,//超声波接收
input [3:0] track,//寻迹
input [1:0] Light,//寻光
input [1:0] openmv_in,//色块信息
output wire Trig,//超声波触发
output [3:0] led,//led输出
output wire motor_A_PWM,//电机
output wire motor_A_IN1,
output wire motor_A_IN2,
output wire motor_B_PWM,
output wire motor_B_IN1,
output wire motor_B_IN2,
output wire motor_C_PWM,
output wire motor_C_IN1,
output wire motor_C_IN2,
output wire motor_D_PWM,
output wire motor_D_IN1,
output wire motor_D_IN2,
output [7:0] led1//数码管输出
);
/******************************模块使用的变量**************************************/
wire [7:0] datarece;//蓝牙接收的信息
reg [7:0] data;//蓝牙信号
wire [15:0] distance;//超声波测得距离
reg [15:0] distance_reg;//超声波测得距离
reg [3:0] mode;//模式选择(避障 寻迹 遥控)
reg [3:0] ledout;//led输出
reg [7:0] pwm;//pwm输出值
reg Mode_Control;//遥控模式标志符
reg [3:0] signal_reg;//红外信号
reg [1:0] light_reg;
parameter SEG_NUM0 = 8'b0011_1111, //数码管显示0
SEG_NUM1 = 8'b0000_0110, //数码管显示1
SEG_NUM2 = 8'b0101_1011, //数码管显示2
SEG_NUM3 = 8'b0100_1111, //数码管显示3
SEG_NUM4 = 8'b0110_0110, //数码管显示4
SEG_NUM5 = 8'b0110_1101, //数码管显示5
SEG_NUM6 = 8'b0111_1101, //数码管显示6
SEG_NUM7 = 8'b0000_0111, //数码管显示7
SEG_NUM8 = 8'b0111_1111, //数码管显示8
SEG_NUM9 = 8'b0110_1111; //数码管显示9
reg [7:0] led1_reg;
assign led1=led1_reg;
assign led=ledout;//led连线
localparam DISTANCE_THRESHOLD = 200; //超声波避障阈值
/********************************调用模块****************************************/
//蓝牙模块
uar_control bluetooth(
.clk(clk),//输入 时钟
.reset(reset),//输入 复位
.rx(rx),//输入 信息
.LED(datarece)//输出 信息
);
//超声波测距
juli_detect u0(
.clk(clk),//输入 时钟
.reset(reset),//输入 复位
.Echo(Echo),//输入 触发
.Trig(Trig),
.distance(distance)//输出 距离
);
//电机控制
Four_Wheel_Control (
.clk(clk), // 输入 时钟
.reset(reset), // 输入 复位
.mode(mode), // 输入 模式(0-停止,2-前进,1-后退,4-右转,3-左转)
.pwm(pwm), // 输入 PWM值(0-255范围)
.motor_A_PWM(motor_A_PWM), // 电机A的PWM控制信号输出
.motor_A_IN1(motor_A_IN1), // 电机A的IN1控制信号输出
.motor_A_IN2(motor_A_IN2), // 电机A的IN2控制信号输出
.motor_B_PWM(motor_B_PWM), // 电机B的PWM控制信号输出
.motor_B_IN1(motor_B_IN1), // 电机B的IN1控制信号输出
.motor_B_IN2(motor_B_IN2), // 电机B的IN2控制信号输出
.motor_C_PWM(motor_C_PWM), // 电机C的PWM控制信号输出
.motor_C_IN1(motor_C_IN1), // 电机C的IN1控制信号输出
.motor_C_IN2(motor_C_IN2), // 电机C的IN2控制信号输出
.motor_D_PWM(motor_D_PWM), // 电机D的PWM控制信号输出
.motor_D_IN1(motor_D_IN1), // 电机D的IN1控制信号输出
.motor_D_IN2(motor_D_IN2) // 电机D的IN2控制信号输出
);
/************************核心控制代码*********************************/
//赋值模块
always @(posedge clk) begin
begin
data<=datarece;//reg赋值
distance_reg<=distance;//reg赋值
light_reg<=Light;
pwm<=128;//默认pwm最大值
if(mode==0)pwm<=0;//接收停止指令时pwm赋0
end
end
//控制模块
always@(posedge clk)begin
//根据data的值来选择不同的模式
//避障模式
if(data==8'b11111110) begin
ledout<=4'b0001;//亮一个LED
Mode_Control<=0;//遥控模式标志符清零
if (distance_reg <= DISTANCE_THRESHOLD) begin//如果距离小于阈值
mode<=1;//
end else begin//如果距离大于阈值
mode<=0;//
end
end
//寻迹模式
else if(data==8'b11111000) begin
ledout<=4'b0011;//亮两个LED
Mode_Control<=0;//遥控模式标志符清零
if((track[1]==1'b0)&&(track[2]==1'b0))//未寻到黑线,俩轮直接前进
mode<=2;//直行T16
else if((track[1]==1'b0)&&(track[2]==1'b1))//左传感寻到黑线,右传感未寻到,右轮动
mode<=4;//右转
else if((track[1]==1'b1)&&(track[2]==1'b0))//右传感寻到黑线,右传感未寻到,左轮动
mode<=3;//左转
else mode<=0;//两个黑线,不符要求,停止运行
end
//遥控模式
else if(data==8'b11100000) begin
case(openmv_in)
2'b00: led1_reg<=SEG_NUM3;
2'b01: led1_reg<=SEG_NUM1;//red
2'b10: led1_reg<=SEG_NUM2;//green
2'b11: led1_reg<=SEG_NUM0;//blue
endcase
ledout<=4'b0111;//亮三个LED
mode<=0;//默认状态停止
Mode_Control<=1;//遥控模式标志符置高
end
//寻光模式
else if(data==8'b10000000) begin
ledout<=4'b1111;//亮四个LED
Mode_Control<=0;//遥控模式标志符置高
if((Light[1]==1'b1)&&(Light[0]==1'b1))//同时感应光线
mode<=2;//直行
else if((Light[1]==1'b1)&&(Light[0]==1'b0))//左边感应到光线,右边没有感应到光线
mode<=3;//左转
else if((Light[1]==1'b0)&&(Light[0]==1'b1))//右边感应到光线,左边没有感应到光线
mode<=4;//右转
else mode<=0;//都没有感应到光线,停止运行
end
//其他信号,亮四个LED,不执行命令
else ledout<=4'b1111;
//红外遥控指令
if(Mode_Control==1)//如果遥控模式标志符置高
begin
if(signal==5'b0000)//停止
mode<=0;
if(signal==5'b0001)//前进
mode<=2;
if(signal==5'b0010)//后退
mode<=1;
if(signal==5'b0100)//左转
mode<=3;
if(signal==5'b1000)//右转
mode<=4;
end
end
ila_0 your_instance_name (
.clk(clk), // input wire clk
.probe0(distance), // input wire [15:0] probe0
.probe1(openmv_in) // input wire [1:0] probe1
);
endmodule
实例化蓝牙、超声波、电机模块,在always块中实时判断蓝牙的信息进行模式选择,在遥控模式中实时判断红外遥控的信息遥控小车,最后的代码是在ila中debug,实际没有用。
整体Arduino代码如下;
#include
#include
int data;
SoftwareSerial BT(8, 11); // 引脚2是arduino的RX端
//无-48 蓝-49 红-50 绿-51
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
String str;
void setup() {
Serial.begin(115200);
BT.begin(115200); //设置arduino的串口波特率与蓝牙模块的默认值相同为9600
irrecv.enableIRIn();
pinMode(2, OUTPUT);
pinMode(7, OUTPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
}
void loop() {
if (irrecv.decode(&results))
{
str = String(results.value); // 将结果转换为十六进制字符串
switch (results.value) {
case 16718055:
Serial.println("Forward");
digitalWrite(2, HIGH);
break;
case 16730805:
Serial.println("Back");
digitalWrite(7, HIGH);
break;
case 16716015:
Serial.println("Left");
digitalWrite(3, HIGH);
break;
case 16734885:
Serial.println("Right");
digitalWrite(5, HIGH);
break;
case 16726215:
Serial.println("Stop");
digitalWrite(2, LOW);
digitalWrite(7, LOW);
digitalWrite(3, LOW);
digitalWrite(5, LOW);
break;
}
irrecv.resume();
}
if (BT.available()>0)
{
data=BT.read(); //读取串口字符串
// 根据接收到的数据进行相应的处理
//00-无 01-红 10-绿 11-蓝
if (data == 49) {
Serial.println("Blue"); // 打印蓝色
digitalWrite(6, HIGH);
digitalWrite(9, HIGH);
} else if (data == 50) {
Serial.println("Red"); // 打印红色
digitalWrite(6,LOW);
digitalWrite(9, HIGH);
} else if (data == 51) {
Serial.println("Green"); // 打印绿色
digitalWrite(6,HIGH);
digitalWrite(9, LOW);
}
else
{
digitalWrite(6,LOW);
digitalWrite(9, LOW);
}
}
}