目录
预计效果:
计划使用4x4按键矩阵来控制遥控车,并且希望实现以下功能:可调速、控制模式(循迹、避障、遥控)、OLED显示当前模式、按键状态、速度和运动姿态。
以下是对您的计划的详细说明:
-
按键输入:使用4x4按键矩阵进行按键输入。按键矩阵可以将多个按键连接到少量的引脚上。可以通过扫描按键矩阵来检测哪个按键被按下,并获取相应的按键状态。
-
调速功能:使用可调速的驱动器或控制器来控制遥控车的速度。根据按键输入或其他输入信号,调整驱动器的输出来控制车辆的速度。
-
控制模式:使用按键输入来切换遥控车的控制模式。可以定义不同的控制模式,如循迹、避障和遥控。根据按键输入的模式选择,切换遥控车的行为。
-
OLED显示:使用OLED显示屏来显示当前的控制模式、按键状态、速度和运动姿态等信息。可以使用合适的库或驱动程序来控制OLED显示屏,并将相关信息显示在屏幕上。
使用4x4按键矩阵来控制遥控车,并实现可调速、控制模式切换和信息显示等功能。
材料清单:
- ZYNQ ECO开发板(用于遥控车控制)
- STM32F103C8T6微控制器(用于遥控器)
- 4x4矩阵按键(用于遥控器输入)
- N20电机(数量:4)
- 麦克纳姆轮(数量:4)
- HC14蓝牙模块(用于无线通信)
- 0.96寸OLED显示屏(用于显示车辆状态)
- HC-SR04超声波测距模块(用于距离测量)
- TCRT5000循迹模块(数量:2,用于循迹功能)
- TB6612FNG电机驱动(数量:2)
- 12V电池
- 智能小车电源模块DC-DC 12V转5V 3.3V
程序编写:
配置ZYNQ ECO开发板
1. 串口接收模块
`timescale 1ns / 1ps
module rx_dat(
input clk ,
input rst_n ,
input rx ,
output rx_done ,
output [7:0] rx_data
);
parameter HZ=50_000_000;
parameter bps = 9600;
//parameter HZ =50_00;//1s时间
//parameter bps = 96 ;//波特率
parameter delay=HZ/bps ;//传输一个bit需要的时间
reg [31:0] cnt; //时钟计数器
reg [5:0 ] cnt_bit; //传输第几bit计数器
reg en; //使能
reg [7:0 ] data_reg; //数据中间寄存
always @(posedge clk)
if(!rst_n)
en<=0;
else if(!rx)
en<=1;
else if(cnt==delay/2-1&&cnt_bit==9)
en<=0;
else
en<=en;
always @(posedge clk)
if(!rst_n)begin
cnt<=0;
cnt_bit<=0;
end
else if(en)begin
if(cnt==delay-1)begin
cnt<=0;;
cnt_bit<=cnt_bit+1;
end
else begin
cnt<=cnt+1;
cnt_bit<=cnt_bit;
end
end
else begin
cnt<=0;
cnt_bit<=0;
end
always @(posedge clk)
if(!rst_n)
data_reg<=0;
else if(cnt_bit>0&&cnt_bit<9&&cnt==delay/2-1)
data_reg[cnt_bit-1]=rx;
else
data_reg<=data_reg;
assign rx_data=(cnt_bit==9)?data_reg:rx_data;
assign rx_done=(cnt_bit==9&&cnt==delay/2-1)?1:0;
endmodule
时钟输入clk
、复位输入rst_n
、接收数据输入rx
、接收完成信号输出rx_done
和接收数据输出rx_data
。
该模块的功能是接收串口数据,并将接收到的数据存储在rx_data
中,同时产生rx_done
信号表示数据接收完成。
parameter
行定义了两个参数:HZ
表示时钟频率,bps
表示波特率。delay
是一个计算所需时间的参数,表示传输一个bit所需要的时钟周期数。cnt
是一个32位的时钟计数器,用于计数时钟周期。cnt_bit
是一个6位的计数器,用于计数传输的第几个bit。en
是一个使能信号,用于控制数据接收的使能状态。data_reg
是一个8位的寄存器,用于暂存接收到的数据。always @(posedge clk)
语句表示在时钟上升沿触发的时候执行内部逻辑。- 最后的
assign
语句用于将data_reg
和rx_data
连接起来,并将接收完成的条件赋值给rx_done
。
该模块的功能是在每个时钟周期中计数,根据时钟周期和波特率的关系来判断何时接收到一个完整的数据位,并将其存储在rx_data
中。接收完成时,会产生rx_done
信号。
请注意,该模块仅用于接收数据,还需要后面的模块来处理接收到的数据,
2. LED模块
`timescale 1ns / 1ps
module led_mk(
input clk ,
input rst_n ,
input [4:0] led_zt ,
output reg[3:0] led
);
parameter led1 = 0;
parameter led2 = 1;
parameter led3 = 2;
parameter led4 = 3;
parameter led5 = 4;
reg [3:0] c_led;
reg [3:0] n_led;
always @(posedge clk)
if(!rst_n)
c_led <= led1;
else
c_led <= n_led;
always @(*)
if(!rst_n)
n_led = 0;
else begin
case(led_zt)
led1: begin
n_led = led1;
end
led2:begin
n_led = led2;
end
led3:begin
n_led = led3;
end
led4:begin
n_led = led4;
end
led5:begin
n_led = led5;
end
default:
n_led = n_led;
endcase
end
always @(posedge clk)
if(!rst_n)
led <= 0;
else begin
case(c_led)
led1: begin
led <= 4'b0000;
end
led2:begin
led <= 4'b0001;
end
led3:begin
led <= 4'b0011;
end
led4:begin
led <= 4'b0111;
end
led5:begin
led <= 4'b1111;
end
default:
led <= led;
endcase
end
endmodule
一个简单的LED驱动模块,根据输入的led_zt
选择不同的LED显示模式。
module led_mk
定义了模块名和输入输出端口。parameter
行定义了LED的不同状态,通过数字编码来表示。reg
行定义了两个寄存器c_led
和n_led
,用于存储当前和下一个LED状态。always @(posedge clk)
表示在时钟上升沿触发的时候执行内部逻辑。if-else
语句用于根据时钟和复位信号的状态更新c_led
寄存器。always @(*)
表示在输入信号变化时执行内部逻辑。case
语句用于根据led_zt
选择不同的LED状态,并将结果存储到n_led
寄存器中。- 另一个
always @(posedge clk)
块用于根据c_led
的值来更新led
输出。 case
语句提供了不同的LED状态对应的输出值。
该模块的功能是根据输入的led_zt
选择不同的LED状态,并在时钟上升沿更新LED的输出值。此模块没有提供复杂的控制逻辑,只是简单地根据输入来选择LED的状态。
3. 电机驱动模块
`timescale 1ns / 1ps
module DIRECTION(
input clk ,
input rst_n ,
input [4:0] DIRECTION_zt ,
output reg[1:0] left_whell ,
output reg[1:0] right_whell
);
//此处采用2为二进制控制
// 1 0
// 10前进 01后退 00停止
//
parameter forward = 0;
parameter retreat = 1;
parameter turn_right = 2;
parameter turn_left = 3;
parameter stop = 4;
reg [3:0] c_whell;
reg [3:0] n_whell;
always @(posedge clk)
if(!rst_n)
c_whell <= stop;
else
c_whell <= n_whell;
always @(*)
if(!rst_n)
n_whell = 0;
else begin
case(DIRECTION_zt)
forward: begin
n_whell = forward;
end
retreat:begin
n_whell = retreat;
end
turn_right:begin
n_whell = turn_right;
end
turn_left:begin
n_whell = turn_left;
end
stop:begin
n_whell = stop;
end
default:
n_whell = stop;
endcase
end
always @(posedge clk)
if(!rst_n) begin
left_whell <= 2'b00;
right_whell <= 2'b00;
end
else begin
case(c_whell)
forward: begin
left_whell <= 2'b10;
right_whell <= 2'b10;
end
retreat:begin
left_whell <= 2'b01;
right_whell <= 2'b01;
end
turn_right:begin
left_whell <= 2'b10;
right_whell <= 2'b01;
end
turn_left:begin
left_whell <= 2'b01;
right_whell <= 2'b10;
end
stop:begin
left_whell <= 2'b00;
right_whell <= 2'b00;
end
default:begin
left_whell <= 2'b00;
right_whell <= 2'b00;
end
endcase
end
endmodule
DIRECTION
模块通过根据输入的方向状态控制车辆的左右轮引脚电平,从而控制电机的转向。
- 前进(0):左轮引脚为2'b10,右轮引脚为2'b10,让遥控车向前行驶。
- 后退(1):左轮引脚为2'b01,右轮引脚为2'b01,让遥控车后退。
- 左转(2):左轮引脚为2'b01,右轮引脚为2'b10,让遥控车向左转。
- 右转(3):左轮引脚为2'b10,右轮引脚为2'b01,让遥控车向右转。
- 停止(4):左轮引脚为2'b00,右轮引脚为2'b00,让遥控车停止。
4. 速度控制模块
`timescale 1ns / 1ps
module SY6_PWM(
input clk ,
input rst_n ,
input [31:0] speed ,
output left_pwm ,
output right_pwm
);
reg [31:0] i = 0;
//parameter delay=1;
parameter delay=50;
reg [31:0] cnt ;
reg [31:0] us ;
reg [31:0] ms ;
//基础计数 先计数到50
always @(posedge clk)
if(!rst_n)
cnt <=0;
else if(cnt == delay -1)
cnt<=0;
else
cnt<=cnt+1;
always @(posedge clk)
if(!rst_n)
us <=0;
else if(cnt == delay -1)begin
if(us == 999)
us <=0;
else
us<=us+1;
end
else
us<=us;
always @(posedge clk)
if(!rst_n)begin
ms <=0;
end
else if(cnt == delay -1 && us== 999)begin
if(ms == 999)begin
ms <=0;
end
else
ms<=ms+1;
end
else
ms<=ms;
assign left_pwm =(speed >= us ) ?1:0;
assign right_pwm =(speed >= us) ?1:0;
/*
always @(*)begin
if(!rst_n) begin
led <= 0;
//mode <= H;
end
else if(mode == H)
led <= (ms>=us)?4'b0111:4'b0000;
else if(mode == L )
led <= (ms<=us)?4'b0111:4'b0000;
end
*/
endmodule
输入的speed
参数决定了PWM输出的占空比。当us
计数小于等于speed
时,left_pwm
和right_pwm
输出高电平;否则输出低电平。需要注意的是,一旦speed
参数被接收后,不能对其进行处理,否则PWM输出将一直为低电平。
该模块的功能是根据输入的speed
参数控制左右PWM输出的占空比。通过调整speed
参数的值可以控制PWM输出的高电平时间比例,从而控制电机的转速。
5. 超声波模块
`timescale 1ns / 1ps
module SR_04(
input clk ,
input rst_n ,
input echo , //接收端,判断端口返回值
output [15:0] dis , //最终距离
output trig //脉冲发出
);
parameter delay = (50*15) + (50*1000*100); //60ms以上的周期
parameter s1 = 0; //空闲
parameter s2 = 1; //echo开始计时
parameter s3 = 2; //计时结束
reg [31:0] cnt_trig;
reg [31:0] cnt_echo;
reg [31:0] cnt_echo_reg;
reg [2:0] c_state;
reg [2:0] n_state;
always @(posedge clk)
if(!rst_n)
cnt_trig <= 0;
else if(cnt_trig == delay -1)
cnt_trig <= 0;
else
cnt_trig <= cnt_trig +1
;
assign trig = ((cnt_trig >0) && (cnt_trig<(50*15))) ? 1:0;
always @(posedge clk)
if(!rst_n)
c_state <= s1;
else
c_state <= n_state;
always @(*)
case(c_state)
s1: begin
if(echo == 1)
n_state = s2;
else
n_state = s1;
end
s2: begin
if(echo == 0)
n_state = s3;
else
n_state = s2;
end
s3: begin
n_state = s1;
end
endcase
always @(posedge clk)
if(!rst_n)begin
cnt_echo<=0;
cnt_echo_reg <= 0;
end
else begin
case(c_state)
s1: begin
cnt_echo<=0;
cnt_echo_reg <= cnt_echo_reg;
end
s2: begin
cnt_echo<=cnt_echo +1;
cnt_echo_reg <= cnt_echo_reg;
end
s3: begin
cnt_echo<=cnt_echo;
cnt_echo_reg <= cnt_echo;
end
endcase
end
assign dis = (cnt_echo_reg * 20)/1000/58;
endmodule
此处我们只需要调用输出的dis距离进行程序处理即可。
6. 循迹模块
`timescale 1ns / 1ps
module infrared(
input clk ,
input rst_n ,
input [1:0] infrared ,
output reg [1:0] infrared_data
);
always @(posedge clk)
if(!rst_n)
infrared_data <= 0;
else
infrared_data <= infrared;
endmodule
这是一个循迹模块,根据输入的红外传感器信号infrared
来更新输出的红外数据infrared_data
。
timescale 1ns / 1ps
定义了时间单位和精度。module infrared
定义了模块名和输入输出端口。always @(posedge clk)
表示在时钟上升沿触发的时候执行内部逻辑。if-else
语句用于根据时钟和复位信号的状态更新infrared_data
寄存器。- 在复位信号为低电平时,将
infrared_data
寄存器清零。 - 在时钟上升沿时,将输入的红外传感器信号
infrared
赋值给infrared_data
寄存器。
根据上述代码,该模块的功能是将红外传感器的输入信号infrared
直接赋值给infrared_data
输出寄存器。这样可以将两路循迹模块的输入接口进行处理,以适应主程序控制模块的整体思路。
7. 主程序
// 功能 循迹 避障 遥控车
// 位数 8 7 6 5 4 3 2 1
//第8位为控制位,控制自动和手动 0 = 自动 1 = 手动
// 7 6 5 控制方向: 4 3 2 1 速度:
// 010 前进 0XA0 01 遥控车 01 慢速 0X81
// 101 后退 0XD0 10 循迹 10 中速 0X82
// 001 右转 0X90 11 避障 11 高速 0X83
// 100 左转 0XC0
// 000 停车 0X80
//针脚配置
//串口 rx P20 //左轮控制 左方向:N18 T20 //右轮控制 右方向 P18 U20
// tx 左pwm P19 右pwm V20
// //超声波 teig W20 //循迹 左 W16
// echo R18 右 R17
引脚配置
module car_kz(
input clk ,
input rst_n ,
input rx ,
output reg[3:0] led ,
//行驶方向控制
output reg[1:0] left_whell ,
output reg[1:0] right_whell ,
output left_pwm ,
output right_pwm ,
//超声波gpio
input echo ,//接收端,判断超声波端口返回值
output trig ,//脉冲发出
//循迹
input [1:0] infrared
);
模块引入
rx_dat UART1_RX(
. clk (clk ),
. rst_n (rst_n ),
. rx (rx ),
. rx_done (rx_done ),
. rx_data (rx_data )
);
led_mk led_k(
. clk ( clk ) ,
. rst_n ( rst_n ) ,
. led_zt ( led_zt ) ,
. led ( led_kz )
);
DIRECTION fxkz(
. clk (clk ) ,
. rst_n (rst_n ) ,
. DIRECTION_zt (DIRECTION_zt) ,
. left_whell (left_whell_output ) ,
. right_whell (right_whell_output )
);
SY6_PWM pwm_db(
. clk ( clk ) ,
. rst_n ( rst_n ) ,
. speed ( speed_pwm ) ,
. left_pwm ( left_pwm_mk ) ,
. right_pwm ( right_pwm_mk)
);
SR_04 SR_CSB(
. clk (clk ) ,
. rst_n (rst_n) ,
. echo (echo ) , //接收端,判断端口返回值
. dis (dis ) , //最终距离
. trig (trig ) //脉冲发出
);
infrared XJ(
. clk (clk ) ,
. rst_n (rst_n ) ,
. infrared (infrared_mk ) ,
. infrared_data (infrared_data)
);
模式判断
wire [2:0] car_mode;
parameter remote_control_car = 2'b01;
parameter tracking_car = 2'b10;
parameter Avoiding_car = 2'b11;
assign car_mode = rx_data[3:2];
always@(posedge clk) begin
if(!rst_n)
Avoiding_car_cnt <= 0;
else
case(car_mode)
remote_control_car: begin
if(rx_data[1:0] == speed1 || rx_data[1:0] == speed2 || rx_data[1:0] == speed3) begin
speed <= rx_data[1:0];
end
else
speed <= speed;
car_run <= rx_data[6:4];
end
tracking_car: begin
speed <= speed1;
if(infrared_data[1] == 1 && infrared_data[0] == 1)
car_run <= stop;
else if(infrared_data[1] == 1 && infrared_data[0] == 0)
car_run <= turn_left;
else if(infrared_data[1] == 0 && infrared_data[0] == 1)
car_run <= turn_right;
else
car_run <= forward;
end
Avoiding_car: begin
//speed <= speed2;
//冲突,此处和程序不同,不可同时满足多种情况, !!!!:不可一循环内先满足后满足,实现后满足情况
if(dis <= Avoiding_distance) begin
Avoiding_car_qk <= 1;
Avoiding_car_cnt <= 0;
speed <= speed1;
car_run <= turn_right;
end
else if(dis > Avoiding_distance && Avoiding_car_qk == 1 && Avoiding_car_cnt <= Avoiding_car_delay - 1) begin
Avoiding_car_cnt <= Avoiding_car_cnt + 1;
speed <= speed1;
car_run <= turn_right;
end
else if(Avoiding_car_cnt > Avoiding_car_delay - 1) begin
Avoiding_car_qk <= 0;
Avoiding_car_cnt <= 0;
end
else begin
speed <= speed2;
car_run <= forward;
end
end
default: begin
speed <= speed0;
car_run <= stop;
end
endcase
end
car_mode保存4 3位的数据,确定小车模式(循迹,避障,遥控),Avoiding_car模式中,需要在识别障碍物后转动一部分时间。
LED控制
//*************************************** LED控制 *********************************************************//
//led控制
always @(posedge clk)
if(!rst_n)
c_speed_led <= led1;
else
c_speed_led <= n_speedl_led;
always @(*)
case(speed)
speed0 :begin
n_speedl_led = led1;
end
speed1 :begin
n_speedl_led = led2;
end
speed2 :begin
n_speedl_led = led3;
end
speed3 :begin
n_speedl_led = led4;
end
default:begin
n_speedl_led = 0;
end
endcase
always @(posedge clk)
if(!rst_n)
led_zt <= 0;
else
led_zt <= c_speed_led;
always @(posedge clk)
if(!rst_n)
led <= 0;
else
led <= led_kz;
//*************************************************************************************************************//
PWM调速
//****************************************** PWM控制车速 **********************************************************//
//此处直接将led值输入给pwm速度,因为 led在此处用于表达速度
always @(posedge clk)
if(!rst_n)
speed_pwm <= 0;
else
speed_pwm <= c_speed_led * 250;
assign right_pwm = right_pwm_mk;
assign left_pwm = left_pwm_mk;
/*
always @(*)
if(!rst_n)begin
left_pwm = 0;
right_pwm = 0;
end
else begin
left_pwm = left_pwm_mk;
right_pwm = right_pwm_mk;
end */
//*************************************************************************************************************//
方向控制
//************************************* 方向控制 **************************************************************//
always @(posedge clk)
if(!rst_n)
c_whell_contel <= stop;
else
c_whell_contel <= n_whell_contel;
always @(*)
case(car_run)
forward :begin
n_whell_contel = whell_forward;
end
retreat :begin
n_whell_contel = whell_whell_retreat;
end
turn_right :begin
n_whell_contel = whell_turn_right;
end
turn_left :begin
n_whell_contel = whell_turn_left;
end
stop :begin
n_whell_contel = whell_stop;
end
default:begin
n_whell_contel = whell_stop;
end
endcase
always @(posedge clk)
if(!rst_n)
DIRECTION_zt <= 0;
else
DIRECTION_zt <= c_whell_contel;
always @(posedge clk)
if(!rst_n)begin
left_whell <= 0;
right_whell <= 0;
end
else begin
left_whell <= left_whell_output;
right_whell <= right_whell_output;
end
//*************************************************************************************************************//
car_kz(最终程序)
`timescale 1ns / 1ps
// 功能 循迹 避障 遥控车
// 位数 8 7 6 5 4 3 2 1
//第8位为控制位,控制自动和手动 0 = 自动 1 = 手动
// 7 6 5 控制方向: 4 3 2 1 速度:
// 010 前进 0XA0 01 遥控车 01 慢速 0X81
// 101 后退 0XD0 10 循迹 10 中速 0X82
// 001 右转 0X90 11 避障 11 高速 0X83
// 100 左转 0XC0
// 000 停车 0X80
//针脚配置
//串口 rx P20 //左轮控制 左方向:N18 T20 //右轮控制 右方向 P18 U20
// tx 左pwm P19 右pwm V20
// //超声波 teig W20 //循迹 左 W16
// echo R18 右 R17
module car_kz(
input clk ,
input rst_n ,
input rx ,
output reg[3:0] led ,
//行驶方向控制
output reg[1:0] left_whell ,
output reg[1:0] right_whell ,
output left_pwm ,
output right_pwm ,
//超声波gpio
input echo ,//接收端,判断超声波端口返回值
output trig ,//脉冲发出
//循迹
input [1:0] infrared
);
//小车状态
//处理小车状态
//wire [2:0] car_mode;
wire [2:0] car_mode;
parameter remote_control_car = 2'b01;
parameter tracking_car = 2'b10;
parameter Avoiding_car = 2'b11;
//速度
parameter speed0 = 2'b00;
parameter speed1 = 2'b01;
parameter speed2 = 2'b10;
parameter speed3 = 2'b11;
//wire [2:0] speed;
reg [2:0] speed;
reg [31:0] speed_pwm;
//控制方向
//wire [2:0] car_run;
reg [2:0] car_run;
parameter forward = 3'b010;
parameter retreat = 3'b101;
parameter turn_right = 3'b001;
parameter turn_left = 3'b100;
parameter stop = 3'b000;
//方向状态机
reg [4:0] c_whell_contel;
reg [4:0] n_whell_contel;
reg [4:0] DIRECTION_zt ; //处理方向控制状态
wire [1:0] left_whell_output;
wire [1:0] right_whell_output;
parameter whell_forward = 0 ;
parameter whell_whell_retreat = 1 ;
parameter whell_turn_right = 2 ;
parameter whell_turn_left = 3 ;
parameter whell_stop = 4 ;
//超声波
wire [15:0] dis; //获取超声波距离 单位 cm
parameter Avoiding_car_delay = 50_000_000 ;
parameter Avoiding_distance = 20; //避障距离
reg [31:0] Avoiding_car_cnt;
reg [2:0] Avoiding_car_qk;
//循迹
wire [1:0] infrared_data;
reg [1:0] infrared_mk;
//led相关控制
reg [4:0] led_zt;
wire [3:0] led_kz;
parameter led1 = 0;
parameter led2 = 1;
parameter led3 = 2;
parameter led4 = 3;
parameter led5 = 4;
reg [4:0] c_speed_led;
reg [4:0] n_speedl_led;
//串口相关控制
wire rx_done;
wire [7:0] rx_data;
reg [7:0] data;
//
wire left_pwm_mk;
wire right_pwm_mk;
//处理接收信号
//assign speed = rx_data[1:0];
//assign car_run = rx_data[6:4];
assign car_mode = rx_data[3:2];
always@(posedge clk) begin
if(!rst_n)
Avoiding_car_cnt <= 0;
else
case(car_mode)
remote_control_car: begin
if(rx_data[1:0] == speed1 || rx_data[1:0] == speed2 || rx_data[1:0] == speed3) begin
speed <= rx_data[1:0];
end
else
speed <= speed;
car_run <= rx_data[6:4];
end
tracking_car: begin
speed <= speed1;
if(infrared_data[1] == 1 && infrared_data[0] == 1)
car_run <= stop;
else if(infrared_data[1] == 1 && infrared_data[0] == 0)
car_run <= turn_left;
else if(infrared_data[1] == 0 && infrared_data[0] == 1)
car_run <= turn_right;
else
car_run <= forward;
end
Avoiding_car: begin
//speed <= speed2;
//冲突,此处和程序不同,不可同时满足多种情况, !!!!:不可一循环内先满足后满足,实现后满足情况
if(dis <= Avoiding_distance) begin
Avoiding_car_qk <= 1;
Avoiding_car_cnt <= 0;
speed <= speed1;
car_run <= turn_right;
end
else if(dis > Avoiding_distance && Avoiding_car_qk == 1 && Avoiding_car_cnt <= Avoiding_car_delay - 1) begin
Avoiding_car_cnt <= Avoiding_car_cnt + 1;
speed <= speed1;
car_run <= turn_right;
end
else if(Avoiding_car_cnt > Avoiding_car_delay - 1) begin
Avoiding_car_qk <= 0;
Avoiding_car_cnt <= 0;
end
else begin
speed <= speed2;
car_run <= forward;
end
end
default: begin
speed <= speed0;
car_run <= stop;
end
endcase
end
//*************************************** 超声波避障处理 ********************************************************//
/*always @(posedge clk)
if(!rst_n)begin
Avoiding_car_qk <= 0;
Avoiding_car_cnt <= 0;
//speed <= speed1;
//car_run <= turn_right;
end
else if(Avoiding_car_qk == 1 && Avoiding_car_cnt <= Avoiding_car_delay - 1 && dis > 20)begin
speed <= speed1;
car_run <= turn_right;
Avoiding_car_cnt <= Avoiding_car_cnt + 1;
if(Avoiding_car_cnt >Avoiding_car_delay - 1) begin
Avoiding_car_cnt <= 0;
Avoiding_car_qk <= 0;
end
end
else begin
Avoiding_car_qk <= Avoiding_car_qk;
Avoiding_car_cnt <= Avoiding_car_cnt;
end
*/
//*************************************************************************************************************//
//*************************************************** 循迹控制 *********************************************//
always @(posedge clk)
if(!rst_n)
infrared_mk <= 0;
else
infrared_mk <= infrared;
//*************************************************************************************************************//
//*************************************** LED控制 *********************************************************//
//led控制
always @(posedge clk)
if(!rst_n)
c_speed_led <= led1;
else
c_speed_led <= n_speedl_led;
always @(*)
case(speed)
speed0 :begin
n_speedl_led = led1;
end
speed1 :begin
n_speedl_led = led2;
end
speed2 :begin
n_speedl_led = led3;
end
speed3 :begin
n_speedl_led = led4;
end
default:begin
n_speedl_led = 0;
end
endcase
always @(posedge clk)
if(!rst_n)
led_zt <= 0;
else
led_zt <= c_speed_led;
always @(posedge clk)
if(!rst_n)
led <= 0;
else
led <= led_kz;
//*************************************************************************************************************//
//****************************************** PWM控制车速 **********************************************************//
//此处直接将led值输入给pwm速度,因为 led在此处用于表达速度
always @(posedge clk)
if(!rst_n)
speed_pwm <= 0;
else
speed_pwm <= c_speed_led * 250;
assign right_pwm = right_pwm_mk;
assign left_pwm = left_pwm_mk;
/*
always @(*)
if(!rst_n)begin
left_pwm = 0;
right_pwm = 0;
end
else begin
left_pwm = left_pwm_mk;
right_pwm = right_pwm_mk;
end */
//*************************************************************************************************************//
//************************************* 方向控制 **************************************************************//
always @(posedge clk)
if(!rst_n)
c_whell_contel <= stop;
else
c_whell_contel <= n_whell_contel;
always @(*)
case(car_run)
forward :begin
n_whell_contel = whell_forward;
end
retreat :begin
n_whell_contel = whell_whell_retreat;
end
turn_right :begin
n_whell_contel = whell_turn_right;
end
turn_left :begin
n_whell_contel = whell_turn_left;
end
stop :begin
n_whell_contel = whell_stop;
end
default:begin
n_whell_contel = whell_stop;
end
endcase
always @(posedge clk)
if(!rst_n)
DIRECTION_zt <= 0;
else
DIRECTION_zt <= c_whell_contel;
always @(posedge clk)
if(!rst_n)begin
left_whell <= 0;
right_whell <= 0;
end
else begin
left_whell <= left_whell_output;
right_whell <= right_whell_output;
end
//*************************************************************************************************************//
rx_dat UART1_RX(
. clk (clk ),
. rst_n (rst_n ),
. rx (rx ),
. rx_done (rx_done ),
. rx_data (rx_data )
);
led_mk led_k(
. clk ( clk ) ,
. rst_n ( rst_n ) ,
. led_zt ( led_zt ) ,
. led ( led_kz )
);
DIRECTION fxkz(
. clk (clk ) ,
. rst_n (rst_n ) ,
. DIRECTION_zt (DIRECTION_zt) ,
. left_whell (left_whell_output ) ,
. right_whell (right_whell_output )
);
SY6_PWM pwm_db(
. clk ( clk ) ,
. rst_n ( rst_n ) ,
. speed ( speed_pwm ) ,
. left_pwm ( left_pwm_mk ) ,
. right_pwm ( right_pwm_mk)
);
SR_04 SR_CSB(
. clk (clk ) ,
. rst_n (rst_n) ,
. echo (echo ) , //接收端,判断端口返回值
. dis (dis ) , //最终距离
. trig (trig ) //脉冲发出
);
infrared XJ(
. clk (clk ) ,
. rst_n (rst_n ) ,
. infrared (infrared_mk ) ,
. infrared_data (infrared_data)
);
endmodule
STM32F103C8T6遥控器
1. 4*4按键矩阵
输出引脚5、6、7、8设置为高电平,输入引脚1、2、3、4进行信号接收
matrix_4x4.c
#include "matrix_4x4.h"
#include "gpio.h"
void matrix_4x4_init(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
}
void matrix_4x4_1100(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, L);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, L);
}
void matrix_4x4_0011(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, L);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, L);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
}
void matrix_4x4_1000(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, L);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, L);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, L);
}
void matrix_4x4_0100(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, L);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, L);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, L);
}
void matrix_4x4_0010(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, L);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, L);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, L);
}
void matrix_4x4_0001(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, L);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, L);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, L);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
}
//4*4矩阵按键
/*uint8_t matrix_4x4(void)
{
matrix_4x4_init();
HAL_Delay(50);
uint8_t matrix_4x4_input[4] = {0,0,0,0};
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
}*/
uint8_t matrix_4x4(void)
{
matrix_4x4_init();
int i = 50;
HAL_Delay(i);
static uint8_t matrix_4x4_number = 0; //输出结果 莫个按键
uint8_t matrix_4x4_input[4] = {0,0,0,0};
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
//if(matrix_4x4_input != 0)
if(matrix_4x4_input[0] == 1 || matrix_4x4_input[1] == 1 || matrix_4x4_input[2] == 1 || matrix_4x4_input[3] == 1)
{
HAL_Delay(i);
//uint8_t matrix_4x4_output_n[4];
/*
matrix_4x4_output_n[0] = 1;
matrix_4x4_output_n[1] = 1;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);*/
matrix_4x4_1100();
HAL_Delay(i); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
else
matrix_4x4_input[0] = 0;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
else
matrix_4x4_input[1] = 0;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
else
matrix_4x4_input[2] = 0;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
else
matrix_4x4_input[3] = 0;
//1100
//if(matrix_4x4_input != 0)
if(matrix_4x4_input[0] == 1 || matrix_4x4_input[1] == 1 || matrix_4x4_input[2] == 1 || matrix_4x4_input[3] == 1)
{
//1000
HAL_Delay(i);
/*
matrix_4x4_output_n[0] = 1;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);*/
matrix_4x4_1000();
HAL_Delay(i); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
else
matrix_4x4_input[0] = 0;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
else
matrix_4x4_input[1] = 0;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
else
matrix_4x4_input[2] = 0;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
else
matrix_4x4_input[3] = 0;
//if(matrix_4x4_input != 0)
if(matrix_4x4_input[0] == 1 || matrix_4x4_input[1] == 1 || matrix_4x4_input[2] == 1 || matrix_4x4_input[3] == 1)
{
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 4;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 3;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 2;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 1;
else
matrix_4x4_number = matrix_4x4_number;
}
else
{ //0100
HAL_Delay(i);
/*
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 1;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);*/
matrix_4x4_0100();
HAL_Delay(i); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 8;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 7;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 6;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 5;
else
matrix_4x4_number = matrix_4x4_number;
}
}
else
{
//0011
HAL_Delay(i);
/*
uint8_t matrix_4x4_output_n[4];
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 1;
matrix_4x4_output_n[3] = 1;
matrix_4x4_output(matrix_4x4_output_n);*/
matrix_4x4_0011();
HAL_Delay(i); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
else
matrix_4x4_input[0] = 0;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
else
matrix_4x4_input[1] = 0;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
else
matrix_4x4_input[2] = 0;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
else
matrix_4x4_input[3] = 0;
//if(matrix_4x4_input != 0)
if(matrix_4x4_input[0] == 1 || matrix_4x4_input[1] == 1 || matrix_4x4_input[2] == 1 || matrix_4x4_input[3] == 1)
{
//0010
HAL_Delay(i);
/*
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 1;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);*/
matrix_4x4_0010();
HAL_Delay(i); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
else
matrix_4x4_input[0] = 0;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
else
matrix_4x4_input[1] = 0;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
else
matrix_4x4_input[2] = 0;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
else
matrix_4x4_input[3] = 0;
//if(matrix_4x4_input != 0)
if(matrix_4x4_input[0] == 1 || matrix_4x4_input[1] == 1 || matrix_4x4_input[2] == 1 || matrix_4x4_input[3] == 1)
{
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 12;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 11;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 10;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 9;
else
matrix_4x4_number = matrix_4x4_number;
}
else
{ //0001
HAL_Delay(i);
/*
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 1;
matrix_4x4_output(matrix_4x4_output_n);*/
matrix_4x4_0001();
HAL_Delay(i); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 16;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 15;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 14;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 13;
else
matrix_4x4_number = matrix_4x4_number;
}
}
}
}
return matrix_4x4_number;
}
void matrix_4x4_output(uint8_t i[4])
{
if(i[0] == 0)
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, L);
else
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
if(i[1] == 0)
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, L);
else
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
if(i[2] == 0)
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, L);
else
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
if(i[3] == 0)
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, L);
else
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
/*
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
*/
}
/*
#include "matrix_4x4.h"
#include "gpio.h"
void matrix_4x4_init(void)
{
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
}
//4*4矩阵按键
uint8_t matrix_4x4(void)
{
matrix_4x4_init();
HAL_Delay(50);
int matrix_4x4_number = 0; //输出结果 莫个按键
uint8_t matrix_4x4_input[4] = {0,0,0,0};
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
if(matrix_4x4_input != 0)
{
HAL_Delay(20);
uint8_t matrix_4x4_output_n[4];
matrix_4x4_output_n[0] = 1;
matrix_4x4_output_n[1] = 1;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);
HAL_Delay(100); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
else
matrix_4x4_input[0] = 0;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
else
matrix_4x4_input[1] = 0;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
else
matrix_4x4_input[2] = 0;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
else
matrix_4x4_input[3] = 0;
//1100
if(matrix_4x4_input != 0)
{
//1000
HAL_Delay(20);
matrix_4x4_output_n[0] = 1;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);
HAL_Delay(100); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 4;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 3;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 2;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 1;
else
matrix_4x4_number = matrix_4x4_number;
}
else
{ //0100
HAL_Delay(20);
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 1;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);
HAL_Delay(100); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 8;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 7;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 6;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 5;
else
matrix_4x4_number = matrix_4x4_number;
}
}
else
{
//0011
HAL_Delay(20);
uint8_t matrix_4x4_output_n[4];
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 1;
matrix_4x4_output_n[3] = 1;
matrix_4x4_output(matrix_4x4_output_n);
HAL_Delay(100); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_input[0] = 1;
else
matrix_4x4_input[0] = 0;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_input[1] = 1;
else
matrix_4x4_input[1] = 0;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_input[2] = 1;
else
matrix_4x4_input[2] = 0;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_input[3] = 1;
else
matrix_4x4_input[3] = 0;
if(matrix_4x4_input != 0)
{
//0010
HAL_Delay(20);
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 1;
matrix_4x4_output_n[3] = 0;
matrix_4x4_output(matrix_4x4_output_n);
HAL_Delay(100); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 12;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 11;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 10;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 9;
else
matrix_4x4_number = matrix_4x4_number;
}
else
{ //0001
HAL_Delay(20);
matrix_4x4_output_n[0] = 0;
matrix_4x4_output_n[1] = 0;
matrix_4x4_output_n[2] = 0;
matrix_4x4_output_n[3] = 1;
matrix_4x4_output(matrix_4x4_output_n);
HAL_Delay(100); //等待电平变化
//再次判断状态
if(HAL_GPIO_ReadPin(P4_1_GPIO_Port, P4_1_Pin) == H)
matrix_4x4_number = 16;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_2_GPIO_Port, P4_2_Pin) == H)
matrix_4x4_number = 15;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_3_GPIO_Port, P4_3_Pin) == H)
matrix_4x4_number = 14;
else
matrix_4x4_number = matrix_4x4_number;
if(HAL_GPIO_ReadPin(P4_4_GPIO_Port, P4_4_Pin) == H)
matrix_4x4_number = 13;
else
matrix_4x4_number = matrix_4x4_number;
}
}
return matrix_4x4_number;
}
void matrix_4x4_output(uint8_t i[4])
{
if(i[0] == 0)
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, L);
else
HAL_GPIO_WritePin(P4_5_GPIO_Port, P4_5_Pin, H);
if(i[1] == 0)
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, L);
else
HAL_GPIO_WritePin(P4_6_GPIO_Port, P4_6_Pin, H);
if(i[2] == 0)
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, L);
else
HAL_GPIO_WritePin(P4_7_GPIO_Port, P4_7_Pin, H);
if(i[3] == 0)
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, L);
else
HAL_GPIO_WritePin(P4_8_GPIO_Port, P4_8_Pin, H);
}
*/
matrix_4x4.h
#ifndef MATRIX_4X4_H
#define MATRIX_4X4_H
#include <stdint.h>
#define MATRIX_ROWS 4
#define MATRIX_COLS 4
#define H GPIO_PIN_SET //GPIO_PIN_SET 1
#define L GPIO_PIN_RESET //GPIO_PIN_RESET 0
uint8_t matrix_4x4(void);
void matrix_4x4_init(void);
void matrix_4x4_output(uint8_t i[4]);
void matrix_4x4_1100(void);
void matrix_4x4_0011(void);
void matrix_4x4_1000(void);
void matrix_4x4_0100(void);
void matrix_4x4_0010(void);
void matrix_4x4_0001(void);
#endif /* MATRIX_4X4_H */
2. 主程序
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "matrix_4x4.h"
#include "oled.h"
#include "Number.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
//4*4按键初始化
//uint8_t m4x4 = 0;
uint8_t m4x4_sz[1];
//初始化oled
OLED_Init(); //初始化oled
OLED_Clear(); //清屏
HAL_Delay(100);
OLED_ShowCHinese(0, 0, 0);
OLED_ShowCHinese(16, 0, 1);
//OLED_ShowCHinese(32, 0, 2);
OLED_ShowCHinese(60, 0, 3);
OLED_ShowCHinese(76, 0, 4);
OLED_ShowCHinese(92, 0, 2);
//OLED_ShowCHinese(98, 0, 3);
//OLED_ShowCHinese(114, 0, 4);
//初始化发送数据
uint8_t data[1] = {0x00};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
m4x4_sz[0] = matrix_4x4();
//
// 低速 前进 1 3
// 中速 左转 停止 右转 5 6 7 8
// 高速 后退 9 11
// 避障 循迹 遥控 14 15 16
//
//
//
//
switch(m4x4_sz[0] ){
case 13:
{
data[0] = change_bit(data[0], 1, 1);
data[0] = change_bit(data[0], 2, 0);
OLED_ShowCHinese(98, 6, 11);
OLED_ShowCHinese(114, 6, 14);
break;
}
case 2:
break;
case 3:
{
data[0] = change_bit(data[0], 7, 0);
data[0] = change_bit(data[0], 6, 1);
data[0] = change_bit(data[0], 5, 0);
OLED_ShowCHinese(44, 2, 15);
OLED_ShowCHinese(60, 2, 16);
break;
}
case 4:
{
data[0] = change_bit(data[0], 7, 1);
data[0] = change_bit(data[0], 6, 0);
data[0] = change_bit(data[0], 5, 1);
OLED_ShowCHinese(44, 2, 17);
OLED_ShowCHinese(60, 2, 18);
break;
}
case 5:
{
data[0] = change_bit(data[0], 1, 0);
data[0] = change_bit(data[0], 2, 1);
OLED_ShowCHinese(98, 6, 12);
OLED_ShowCHinese(114, 6, 14);
break;
}
case 6:
{
data[0] = change_bit(data[0], 7, 1);
data[0] = change_bit(data[0], 6, 0);
data[0] = change_bit(data[0], 5, 0);
OLED_ShowCHinese(44, 2, 19);
OLED_ShowCHinese(60, 2, 21);
break;
}
case 7:
{
data[0] = change_bit(data[0], 7, 0);
data[0] = change_bit(data[0], 6, 0);
data[0] = change_bit(data[0], 5, 0);
OLED_ShowCHinese(44, 2, 22);
OLED_ShowCHinese(60, 2, 23);
break;
}
case 8:
{
data[0] = change_bit(data[0], 7, 0);
data[0] = change_bit(data[0], 6, 0);
data[0] = change_bit(data[0], 5, 1);
OLED_ShowCHinese(44, 2, 20);
OLED_ShowCHinese(60, 2, 21);
break;
}
case 9:
{
data[0] = change_bit(data[0], 1, 1);
data[0] = change_bit(data[0], 2, 1);
OLED_ShowCHinese(98, 6, 13);
OLED_ShowCHinese(114, 6, 14);
break;
}
case 10:
break;
case 11:
{
data[0] = change_bit(data[0], 7, 1);
data[0] = change_bit(data[0], 6, 0);
data[0] = change_bit(data[0], 5, 1);
OLED_ShowCHinese(44, 2, 17);
OLED_ShowCHinese(60, 2, 18);
break;
}
case 12:
break;
case 1:
break;
case 14:
{
data[0] = change_bit(data[0], 4, 0);
data[0] = change_bit(data[0], 3, 1);
OLED_ShowCHinese(98, 0, 9);
OLED_ShowCHinese(114, 0, 10);
break;
}
case 15:
{
data[0] = change_bit(data[0], 4, 1);
data[0] = change_bit(data[0], 3, 0);
OLED_ShowCHinese(98, 0, 5);
OLED_ShowCHinese(114, 0, 6);
break;
}
case 16:
{
data[0] = change_bit(data[0], 4, 1);
data[0] = change_bit(data[0], 3, 1);
OLED_ShowCHinese(98, 0, 7);
OLED_ShowCHinese(114, 0, 8);
break;
}
default :
;
}
OLED_ShowNum(32, 0, m4x4_sz[0], 2, 16);
HAL_UART_Transmit(&huart1, &data[0], 1,0xffff);
//HAL_UART_Transmit(&huart1, "\r\n", 4,10);
//HAL_Delay(10);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */