分享一个手撕红外解码模块源码

仿真验证已通过,有问题欢迎指正和讨论
//
// Company: 
// Engineer: Deng zhuo bin(邓工)
// 
// Create Date: 2023/6/02 10:00:16
// Design Name: 
// Module Name: infrared_decode
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module	infrared_decode#
(
	parameter	GUIDE_CODE_9MS_H				=	19'd450_000,
	parameter	GUIDE_CODE_4_5MS_L				=	18'd225_000,
	parameter	A_D_R_CODE_560US_H				=	15'd280_00,
	parameter	A_D_CODE_1690US_L				=	17'd845_00,
	parameter	A_D_CODE_560US_L				=	15'd280_00,
	
	parameter	REPEAT_CODE_TIME_INTERVAL_110MS	=	23'd5_500_000,
	parameter	REPEAT_CODE_9MS_H				=	19'd450_000,
	parameter	REPEAT_CODE_2250US_L			=	17'd112_500,
	parameter	REPEAT_CODE_560US_H				=	15'd280_00
	
)
(
	input				sys_clk,
	input				sys_rst_n,
	
	input				i_infrared,
	
	output	reg	[7:0]	o8_decode_data
);

localparam	SM00 = 5'd0,
	        SM01 = 5'd1,
	        SM02 = 5'd2,
	        SM03 = 5'd3,
	        SM04 = 5'd4,
	        SM05 = 5'd5,
	        SM06 = 5'd6,
	        SM07 = 5'd7,
			SM08 = 5'd8,
			SM09 = 5'd9,
			SM10 = 5'd10,
			SM11 = 5'd11,
			SM12 = 5'd12,
			SM13 = 5'd13,
			SM14 = 5'd14,
			SM15 = 5'd15,
			SM16 = 5'd16,
			SM17 = 5'd17,
			SM18 = 5'd18,
			SM19 = 5'd19;
			
			
parameter	A_D_NUM_MAX			=	4'd8;

reg	r_infrared_cur;
reg r_infrared_pre;
wire w_infrared_fall;
wire w_infrared_rise;

reg	[4:0] r5_state_cur;
reg [4:0] r5_state_next;

reg [14:0] r15_560us_cnt;
reg	[16:0] r17_1690_560us_cnt;
reg [17:0] r18_4_5ms_cnt;
reg [18:0] r19_9ms_cnt;
reg [3:0] r4_a_d_cnt;
reg [31:0] r32_a_d_data;
reg [7:0] r8_addr_inv_data;
reg r_addr_inv_receive_finish;
reg r_addr_receive_finish;
reg r_data_receive_finish;
reg [7:0] r8_data_data;
reg [7:0] r8_data_inv_data;
reg r_data_inv_receive_finish;
reg [7:0] r8_addr_data;
reg [16:0] r17_2_25ms_cnt;
reg [22:0] r23_repeat_time_cnt;
reg r_addr_check;
reg r_data_check;


wire w_560us_h;
wire w_g_code_4_5ms_l;
wire w_g_code_9ms_h;
//wire w_addr_receive_finish;
wire w_a_d_value;
//wire w_addr_inv_receive_finish;
wire w_r_code_9ms_h;
wire w_r_code_2_25ms_l;
wire w_r_code_560us_h;

/*generate fall and rise edge*/
assign w_infrared_fall = ((r_infrared_pre == 1'b1)&&(r_infrared_cur == 1'b0)) ? 1'b1 : 1'b0;
assign w_infrared_rise = ((r_infrared_pre == 1'b0)&&(r_infrared_cur == 1'b1)) ? 1'b1 : 1'b0;

/*Synchronization from asynchronous clock signals,at the same time,generate fall and rise condition */
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		r_infrared_pre <= 1'b0;
		r_infrared_cur <= 1'b0;
	end
	else begin
		r_infrared_cur <= i_infrared;
		r_infrared_pre <= r_infrared_cur;
	end	
end


always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		r5_state_cur <= SM00;
	end
	else begin
		r5_state_cur <= r5_state_next;
	end
end

/*state motor*/
always@(*)begin
	case(r5_state_cur)
		SM00 :	//wait guide code 9ms rise edge arrive
			begin
				if(w_infrared_rise == 1'b1)
					begin
						r5_state_next = SM01;
					end
				else
					begin
						r5_state_next = SM00;
					end
			end
		
		SM01 :	//wait guide code 9ms high pulse count finish and guide code 9ms high pulse fall edge arrive
			begin
				if((w_g_code_9ms_h == 1'b1)&&(w_infrared_fall == 1'b1))
					begin
						r5_state_next = SM02;
					end
				else
					begin
						r5_state_next = SM01;
					end
			end
		
		SM02 :	//wait guide code 4.5ms rise edge arrive and guide code 4.5ms low pulse count finish
			begin
				if((w_infrared_rise == 1'b1)&&(w_g_code_4_5ms_l == 1'b1))
					begin
						r5_state_next = SM03;
					end
				else
					begin
						r5_state_next = SM02;
					end
			end
			
		SM03 :	//wait address code 560us high pulse count finish and address code 560us fall edge arrive
			begin
				if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
					begin
						r5_state_next = SM04;
					end
				else
					begin
						r5_state_next = SM03;
					end
			end
		
		SM04 :	
			begin
				//wait address code 560us or 1690us rise arrive and address code 560us or 1690us low count finish
				if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM03;
					end
				//wait address code 560us or 1690us rise arrive and address code 560us or 1690us low count finish and 8 bits address code receive finish
				else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM05;
					end
				else
					begin
						r5_state_next = SM04;
					end
			end
			
		SM05 :	//address inversion code
			begin
				if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
					begin
						r5_state_next = SM06;
					end
				else
					begin
						r5_state_next = SM05;
					end
			end
			
		SM06 :
			begin
				if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM05;
					end
				else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM07;
					end
				else
					begin
						r5_state_next = SM06;
					end
			end
			
		SM07 :	//data code
			begin
				if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
					begin
						r5_state_next = SM08;
					end
				else
					begin
						r5_state_next = SM07;
					end
			end
			
		SM08 :
			begin
				if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM07;
					end
				else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM09;
					end
				else
					begin
						r5_state_next = SM08;
					end
			end
			
		SM09 :	//data inversion code
			begin
				if((w_560us_h == 1'b1)&&(w_infrared_fall == 1'b1))
					begin
						r5_state_next = SM10;
					end
				else
					begin
						r5_state_next = SM09;
					end
			end
			
		SM10 :
			begin
				if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM09;
					end
				else if((w_infrared_rise == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)||
					(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
					begin
						r5_state_next = SM11;
					end
				else
					begin
						r5_state_next = SM10;
					end
			end
		
		SM11 :	//send repeat code 110ms time interval  
			begin
				if(r23_repeat_time_cnt == REPEAT_CODE_TIME_INTERVAL_110MS - 1'b1)
					begin
						r5_state_next = SM12;
					end
				else
					begin
						r5_state_next = SM11;
					end
			end
		
		SM12 :	//wait repeat code 9ms rise edge arrive
			begin
				if(w_infrared_rise == 1'b1)
					begin
						//detecte repeat code
						r5_state_next = SM13;
					end
				else
					begin
						//not detecte repeat code
						r5_state_next = SM16;
					end
			end
			
		SM13 :	//wait repeat code 9ms high pulse count finish and wait repeat code 9ms fall edge arrive
			begin
				if((w_r_code_9ms_h == 1'b1)&&(w_infrared_fall == 1'b1))
					begin
						r5_state_next = SM14;
					end
				else
					begin
						r5_state_next = SM13;
					end
			end
	
		SM14 :	//wait repeat code 2.25ms low pulse count finish and wait repeat code 2.25ms rise edge arrive
			begin
				if((w_infrared_rise == 1'b1)&&(w_r_code_2_25ms_l == 1'b1))
					begin
						r5_state_next = SM15;
					end
				else
					begin
						r5_state_next = SM14;
					end
			end
	
		SM15 :	//wait repeat code 560us high pulse count finish and wait repeat code 560us fall edge arrive
			begin
				if((w_infrared_fall == 1'b1)&&(w_r_code_560us_h == 1'b1))
					begin
						r5_state_next = SM11;
					end
				else
					begin
						r5_state_next = SM15;
					end
			end
			
		SM16 :	//receive a frame data finish
			begin
				r5_state_next = SM00;
			end
		default :
			begin
				r5_state_next = SM00;
			end
	endcase
end

assign w_g_code_9ms_h 	= ((r5_state_cur == SM01)&&(r19_9ms_cnt   == GUIDE_CODE_9MS_H	- 1'b1)) ? 1'b1 : 1'b0;
assign w_g_code_4_5ms_l = ((r5_state_cur == SM02)&&(r18_4_5ms_cnt == GUIDE_CODE_4_5MS_L - 1'b1)) ? 1'b1 : 1'b0;
assign w_560us_h 		= (((r5_state_cur == SM03)||(r5_state_cur == SM05)
							||(r5_state_cur == SM07)||(r5_state_cur == SM09))
							&&(r15_560us_cnt == A_D_R_CODE_560US_H - 1'b1)) ? 1'b1 : 1'b0;
assign w_a_d_value 		= (((r5_state_cur == SM04)||(r5_state_cur == SM06)
							||(r5_state_cur == SM08)||(r5_state_cur == SM10))
							&&(r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)) ? 1'b1 : 1'b0;
// assign w_addr_receive_finish 	 = ((r5_state_cur == SM04)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1))) ? 1'b1 : 1'b0;
// assign w_addr_inv_receive_finish = ((r5_state_cur == SM06)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1))) ? 1'b1 : 1'b0;

assign w_r_code_9ms_h	 = ((r5_state_cur == SM13)&&(r19_9ms_cnt == REPEAT_CODE_9MS_H - 1'b1)) ? 1'b1 : 1'b0;
assign w_r_code_2_25ms_l = ((r5_state_cur == SM14)&&(r17_2_25ms_cnt == REPEAT_CODE_2250US_L - 1'b1)) ? 1'b1 : 1'b0;
assign w_r_code_560us_h	 = ((r5_state_cur == SM15)&&(r15_560us_cnt == REPEAT_CODE_560US_H - 1'b1)) ? 1'b1 : 1'b0;

/*address code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r_addr_receive_finish <= 1'b0;
		end
	else
		begin
			if((r5_state_cur == SM04)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
				begin
					r_addr_receive_finish <= 1'b1;
				end
			else
				begin
					r_addr_receive_finish <= 1'b0;
				end
		end
end

/*address inversion code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r_addr_inv_receive_finish <= 1'b0;
		end
	else
		begin
			if((r5_state_cur == SM06)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
				begin
					r_addr_inv_receive_finish <= 1'b1;
				end
			else
				begin
					r_addr_inv_receive_finish <= 1'b0;
				end
		end
end

/*data code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r_data_receive_finish <= 1'b0;
		end
	else
		begin
			if((r5_state_cur == SM08)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
				begin
					r_data_receive_finish <= 1'b1;
				end
			else
				begin
					r_data_receive_finish <= 1'b0;
				end
		end
end

/*data inversion code receive finish*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r_data_inv_receive_finish <= 1'b0;
		end
	else
		begin
			if((r5_state_cur == SM10)&&((r4_a_d_cnt == A_D_NUM_MAX - 1'b1)))
				begin
					r_data_inv_receive_finish <= 1'b1;
				end
			else
				begin
					r_data_inv_receive_finish <= 1'b0;
				end
		end
end

/*counter*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r19_9ms_cnt <= 19'd0;
			
			r18_4_5ms_cnt <= 18'd0;
			
			r15_560us_cnt <= 15'd0;
			
			r17_1690_560us_cnt <= 17'd0;
			
			r4_a_d_cnt <= 4'd0;
			
			r23_repeat_time_cnt <= 23'd0;
			
			r17_2_25ms_cnt <= 17'd0;
		end
	else
		begin
			if((r5_state_cur == SM01)&&(r19_9ms_cnt < GUIDE_CODE_9MS_H - 1'b1))
				begin
					r19_9ms_cnt <= r19_9ms_cnt + 1'b1;
				end
			else if((r5_state_cur == SM01)&&(r19_9ms_cnt == GUIDE_CODE_9MS_H - 1'b1))
				begin
					r19_9ms_cnt <= 19'd0;
				end
			else if((r5_state_cur == SM02)&&(r18_4_5ms_cnt < GUIDE_CODE_4_5MS_L - 1'b1))
				begin
					r18_4_5ms_cnt <= r18_4_5ms_cnt + 1'b1;
				end
			else if((r5_state_cur == SM02)&&(r18_4_5ms_cnt == GUIDE_CODE_4_5MS_L - 1'b1))
				begin
					r18_4_5ms_cnt <= 18'd0;
				end
			else if(((r5_state_cur == SM03)||(r5_state_cur == SM05)
					||(r5_state_cur == SM07)||(r5_state_cur == SM09))
					&&(r15_560us_cnt < A_D_R_CODE_560US_H - 1'b1))
				begin
					r15_560us_cnt <= r15_560us_cnt + 1'b1;
				end
			else if(((r5_state_cur == SM03)||(r5_state_cur == SM05)
					||(r5_state_cur == SM07)||(r5_state_cur == SM09))
					&&(r15_560us_cnt == A_D_R_CODE_560US_H - 1'b1))
				begin
					r15_560us_cnt <= 15'd0;
				end
			else if(((r5_state_cur == SM04)||(r5_state_cur == SM06)
					||(r5_state_cur == SM08)||(r5_state_cur == SM10))
					&&(r_infrared_cur == 1'b0)&&(r17_1690_560us_cnt < A_D_CODE_1690US_L - 1'b1))
				begin
					r17_1690_560us_cnt <= r17_1690_560us_cnt + 1'b1;
				end
			else if(((r5_state_cur == SM04)||(r5_state_cur == SM06)
					||(r5_state_cur == SM08)||(r5_state_cur == SM10))
					&&(r_infrared_cur == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)
					||(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt < A_D_NUM_MAX - 1'b1))
				begin
					r17_1690_560us_cnt <= 17'd0;
					r4_a_d_cnt <= r4_a_d_cnt + 1'b1;
				end
			else if(((r5_state_cur == SM04)||(r5_state_cur == SM06)
					||(r5_state_cur == SM08)||(r5_state_cur == SM10))
					&&(r_infrared_cur == 1'b1)&&((r17_1690_560us_cnt == A_D_CODE_1690US_L - 1'b1)
					||(r17_1690_560us_cnt == A_D_CODE_560US_L - 1'b1))&&(r4_a_d_cnt == A_D_NUM_MAX - 1'b1))
				begin
					r17_1690_560us_cnt <= 17'd0;
					r4_a_d_cnt <= 4'd0;
				end
			else if((r5_state_cur == SM11)&&(r23_repeat_time_cnt < REPEAT_CODE_TIME_INTERVAL_110MS - 1'b1))
				begin
					r23_repeat_time_cnt <= r23_repeat_time_cnt + 1'b1;
				end
			else if((r5_state_cur == SM11)&&(r23_repeat_time_cnt == REPEAT_CODE_TIME_INTERVAL_110MS - 1'b1))
				begin
					r23_repeat_time_cnt <= 23'd0;
				end
			else if((r5_state_cur == SM13)&&(r19_9ms_cnt < REPEAT_CODE_9MS_H - 1'b1))
				begin
					r19_9ms_cnt <= r19_9ms_cnt + 1'b1;
				end
			else if((r5_state_cur == SM13)&&(r19_9ms_cnt == REPEAT_CODE_9MS_H - 1'b1))
				begin
					r19_9ms_cnt <= 19'd0;
				end
			else if((r5_state_cur == SM14)&&(r17_2_25ms_cnt < REPEAT_CODE_2250US_L - 1'b1))
				begin
					r17_2_25ms_cnt <= r17_2_25ms_cnt + 1'b1;
				end
			else if((r5_state_cur == SM14)&&(r17_2_25ms_cnt == REPEAT_CODE_2250US_L - 1'b1))
				begin
					r17_2_25ms_cnt <= 17'd0;
				end
			else if((r5_state_cur == SM15)&&(r15_560us_cnt < REPEAT_CODE_560US_H - 1'b1))
				begin
					r15_560us_cnt <= r15_560us_cnt + 1'b1;
				end
			else if((r5_state_cur == SM15)&&(r15_560us_cnt == REPEAT_CODE_560US_H - 1'b1))
				begin
					r15_560us_cnt <= 15'd0;
				end
			else
				begin
					r19_9ms_cnt <= 19'd0;
				    r18_4_5ms_cnt <= 18'd0; 
				    r15_560us_cnt <= 15'd0;
				    r17_1690_560us_cnt <= 17'd0;
					r4_a_d_cnt <= 4'd0;
					r23_repeat_time_cnt <= 23'd0;
				end	
		end         
end                 
  
  
/*receive 8 bits address code,	address inversion code,	data code,	data inversion code*/  
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r8_addr_data <= 8'd0;
			r8_addr_inv_data <= 8'd0;
			r8_data_data <= 8'd0;
			r8_data_inv_data <= 8'd0;
		end	
	else
		begin
			if(r5_state_cur == SM04)
				begin
					r8_addr_data[r4_a_d_cnt] <= w_a_d_value;
				end	
			else if(r5_state_cur == SM06)
				begin
					r8_addr_inv_data[r4_a_d_cnt] <= w_a_d_value;
				end
			else if(r5_state_cur == SM08)
				begin
					r8_data_data[r4_a_d_cnt] <= w_a_d_value;
				end
			else if(r5_state_cur == SM10)
				begin
					r8_data_inv_data[r4_a_d_cnt] <= w_a_d_value;
				end
			else
				begin
					r8_addr_data <= r8_addr_data;
					r8_addr_inv_data <= r8_addr_inv_data;
					r8_data_data <= r8_data_data;
					r8_data_inv_data <= r8_data_inv_data;
				end
		end
end


/*latch a frame 32bits data(8 bits address code, address inversion code, data code, data inversion code)*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r32_a_d_data <= 32'd0;
		end
	else
		begin
			if(r_addr_receive_finish == 1'b1)
				begin
					r32_a_d_data[7:0] <= r8_addr_data;
				end
			else if(r_addr_inv_receive_finish == 1'b1)
				begin
					r32_a_d_data[15:8] <= r8_addr_inv_data;
				end
			else if(r_data_receive_finish == 1'b1)
				begin
					r32_a_d_data[23:16] <= r8_data_data;
				end
			else if(r_data_inv_receive_finish == 1'b1)
				begin
					r32_a_d_data[31:24] <= r8_data_inv_data;
				end
			else
				begin
					r32_a_d_data <= r32_a_d_data;
				end
		end
end


/*address check*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r_addr_check <= 1'b0;
		end
	else
		begin
			if(r5_state_cur == SM11)
				begin
					if(r32_a_d_data[7:0] == ~r32_a_d_data[15:8])
						begin
							r_addr_check <= 1'b1;
						end
					else
						begin
							r_addr_check <= 1'b0;
						end
				end
			else
				begin
					r_addr_check <= r_addr_check;
				end
		end
end


/*data check*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			r_data_check <= 1'b0;
		end
	else
		begin
			if(r5_state_cur == SM11)
				begin
					if(r32_a_d_data[23:16] == ~r32_a_d_data[31:24])
						begin
							r_data_check <= 1'b1;
						end
					else
						begin
							r_data_check <= 1'b0;
						end
				end
			else
				begin
					r_data_check <= r_data_check;
				end
		end
end

/*output 8 bits effective data*/
always@(posedge sys_clk or negedge sys_rst_n)
begin
	if(!sys_rst_n)
		begin
			o8_decode_data <= 8'd0;
		end
	else
		begin
			if((r5_state_cur == SM11)&&(r_data_check == 1'b1))
				begin
					o8_decode_data <= r32_a_d_data[23:16];
				end
			else
				begin
					o8_decode_data <= o8_decode_data;
				end
		end
end

endmodule

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值