WS2812B-LED環形燈控制(FPGA)

在圖像處理領域,光線是非常重要的前提。燈源最好是環形燈,就像那些網紅給自己打光一樣,環形燈光照均勻。
WS2812B-LED環形燈工作時序如下:
數據的0/1用不同佔空比的pwm表示
在這裏插入圖片描述

0碼和1碼以及復位時間如上圖所示。
在這裏插入圖片描述

RGB888總共24位,每位0/1輸出,一個環形燈16個led,一個總週期需要連續發16個24位數據,再復位一段時間重新下一個輪迴。
在這裏插入圖片描述

數據高位先發,本程序爲0爲最先發的23爲最後發的。

在這裏插入圖片描述

設計思路:
主體爲一個3段式狀態機,0/1碼的週期設爲一致,只是高低電平持續時間互換,一個計數器設置週期循環。狀態輸出依照24位數據的當前位按0/1不同輸出,每個LED設爲一個狀態,每個LED結束轉到下一個狀態。最後一個LED轉到RST狀態,RST也需要一個計數器,計數到一定值跳出該狀態回到IDLE。
在這裏插入圖片描述

來一個彩圖

在這裏插入圖片描述

代碼如下

module LED
(
	input		clk,
	input		rst,
	output	led


);
//clk 50M
parameter	T0H = 6'd17;
parameter	T0L = 6'd50;//0碼的高低電平時間
parameter	T1H = 6'd50;
parameter	T1L = 6'd17;//1碼


parameter	RST = 14'd15000;//復位時間


parameter LED_1 = 25'b0_1111_0000_1111_0000_1111_0000;
parameter LED_2 = 25'b0_1111_0000_0000_0000_1111_0000;
parameter LED_3 = 25'b0_0000_0000_1111_0000_1111_0000;
parameter LED_4 = 25'b0_1111_0000_1111_0000_0000_0000;
parameter LED_5 = 25'b0_1100_0000_1111_1100_1111_0000;
parameter LED_6 = 25'b0_1111_0000_1100_0000_1111_1100;
parameter LED_7 = 25'b0_1111_1100_1111_0000_1100_0000;//反向取值從0-23爲高位至低位GRB的順序
parameter LED_8 = 25'b0_1010_0000_1111_0110_1111_0110;//第25位故意添加,由於bit_cnt在24變0
//FSM 16個LED,一個復位狀態
parameter IDLE        = 16'b0000_0000_0000_0000;
parameter LED_one     = 16'b0000_0000_0000_0001;
parameter LED_two     = 16'b0000_0000_0000_0010;
parameter LED_thr     = 16'b0000_0000_0000_0100;
parameter LED_fou     = 16'b0000_0000_0000_1000;
parameter LED_fiv     = 16'b0000_0000_0001_0000;
parameter LED_six     = 16'b0000_0000_0010_0000;
parameter LED_sev     = 16'b0000_0000_0100_0000;
parameter LED_eig     = 16'b0000_0000_1000_0000;
parameter LED_nin     = 16'b0000_0001_0000_0000;
parameter LED_ten     = 16'b0000_0010_0000_0000;
parameter LED_ele     = 16'b0000_0100_0000_0000;
parameter LED_twe     = 16'b0000_1000_0000_0000;
parameter LED_thi     = 16'b0001_0000_0000_0000;
parameter LED_fou_ten = 16'b0010_0000_0000_0000;
parameter LED_fiv_ten = 16'b0100_0000_0000_0000;
parameter LED_six_ten = 16'b1000_0000_0000_0000;
parameter RST_FSM     = 16'b1100_0000_0000_0000;
reg [15:0] state;
reg [15:0] state_n;//狀態

reg 	[6:0] cycle_cnt;//週期計數
reg    led_pwm;//  Led 輸出
reg    shift;//24位移位輸出
reg    state_tran;//狀態轉移第一個led到最後一個
reg	 state_tran_rst;//狀態轉移,復位至LEd+
reg [13:0]  rst_cnt;//復位輸出
reg [4:0]  bit_cnt;//對24位進行計數移位
//LEd數據高低週期,一個0/1碼持續時間
always @(posedge clk or negedge rst)
begin
if(!rst)
	cycle_cnt <= 7'd0;
else if(cycle_cnt == (T0H + T0L - 6'd1))
	cycle_cnt <= 7'd0;
	else if(state != RST_FSM)//一輪傳輸下來,復位後對齊
	cycle_cnt <= cycle_cnt + 1'b1;
else
	cycle_cnt <= 7'd0;
end



//FSM 1
always @ (posedge clk or negedge rst)
begin
	if(!rst)
		state <= IDLE;
	else
		state <= state_n;
end

//FSM 2  狀態輸出
always @ (posedge clk or negedge rst)
begin
	if(!rst)
		begin
		led_pwm <= 1'b0;
		shift <= 1'b0;
		end
	else 
	begin
		case(state)
		
		IDLE :
				begin 
				led_pwm <= 1'b1;
				end
		LED_one:
				begin
				shift <= LED_1[bit_cnt];//隨着cnt的計數,變換0/1,
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_two:
				begin
				shift <= LED_2[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end	
		LED_thr:
				begin
				shift <= LED_3[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_fou:
				begin
				shift <= LED_4[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end					
		LED_fiv:
				begin
				shift <= LED_5[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_six:
				begin
				shift <= LED_6[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end	
		LED_sev:
				begin
				shift <= LED_7[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_eig:
				begin
				shift <= LED_8[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_nin:
				begin
				shift <= LED_8[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_ten:
				begin
				shift <= LED_7[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_ele:
				begin
				shift <= LED_6[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_twe:
				begin
				shift <= LED_5[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_thi:
				begin
				shift <= LED_4[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_fou_ten:
				begin
				shift <= LED_3[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_fiv_ten:
				begin
				shift <= LED_2[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end
		LED_six_ten:
				begin
				shift <= LED_1[bit_cnt];
				if(shift == 1'b1)
					begin
						if(cycle_cnt == T1H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				else
					begin
						if(cycle_cnt == T0H)
						led_pwm <= 1'b0;
						else if(cycle_cnt == (T1H + T0H - 6'd1))
						led_pwm <= 1'b1;
						else
						led_pwm <= led_pwm;
					end
				end				
		RST_FSM:
				begin
					led_pwm <= 1'b0;
				end
				
		default:
				begin
					led_pwm <= 1'b0;
				end
		endcase
		end
end

assign led = led_pwm;


//FSM  3  狀態轉移
always @ (*)
begin
	case (state)
	IDLE:
			state_n = LED_one;
	LED_one:
			begin
			if(state_tran)
			state_n = LED_two;
			else
			state_n = state;
			end
	LED_two:
			begin
			if(state_tran)
			state_n = LED_thr;
			else
			state_n = state;
			end
	LED_thr:
			begin
			if(state_tran)
			state_n = LED_fou;
			else
			state_n = state;
			end
	LED_fou:
			begin
			if(state_tran)
			state_n = LED_fiv;
			else
			state_n = state;
			end
	LED_fiv:
			begin
			if(state_tran)
			state_n = LED_six;
			else
			state_n = state;
			end
	LED_six:
			begin
			if(state_tran)
			state_n = LED_sev;
			else
			state_n = state;
			end
	LED_sev:
			begin
			if(state_tran)
			state_n = LED_eig;
			else
			state_n = state;
			end
	LED_eig:
			begin
			if(state_tran)
			state_n = LED_nin;
			else
			state_n = state;
			end
	LED_nin:
			begin
			if(state_tran)
			state_n = LED_ten;
			else
			state_n = state;
			end
	LED_ten:
			begin
			if(state_tran)
			state_n = LED_ele;
			else
			state_n = state;
			end
	LED_ele:
			begin
			if(state_tran)
			state_n = LED_twe;
			else
			state_n = state;
			end
	LED_twe:
			begin
			if(state_tran)
			state_n = LED_thi;
			else
			state_n = state;
			end
	LED_thi:
			begin
			if(state_tran)
			state_n = LED_fou_ten;
			else
			state_n = state;
			end
	LED_fou_ten:
			begin
			if(state_tran)
			state_n = LED_fiv_ten;
			else
			state_n = state;
			end
	LED_fiv_ten:
			begin
			if(state_tran)
			state_n = LED_six_ten;
			else
			state_n = state;
			end
	LED_six_ten:
			begin
			if(state_tran)
			state_n = RST_FSM;
			else
			state_n = state;
			end
	RST_FSM:
			begin
			if(state_tran_rst)
			state_n = IDLE;
			else
			state_n = state;
			end
	default:
			state_n =RST_FSM;
	endcase
end

	
	


//記錄24位的時間,方便轉移狀態led
always @(posedge clk or negedge rst)
begin
	if(!rst)
		begin
		bit_cnt <= 5'd0;
		state_tran <= 1'b0;
		end
	else if (bit_cnt == 5'd24)
		begin
		bit_cnt <= 5'd0;
		state_tran <= 1'b1;
		end
	else if(cycle_cnt == (T0H + T0L - 6'd1))
		begin
		bit_cnt <= bit_cnt + 1'b1;
		state_tran <= 1'b0;
		end
	else
		begin
		bit_cnt <= bit_cnt;
		state_tran <= 1'b0;
		end
end
//記錄rst的時間,狀態轉換
always @(posedge clk or negedge rst)
begin
	if(!rst)
		rst_cnt <= 14'd0;
	else if(state == RST_FSM)
		rst_cnt <= rst_cnt + 1'b1;
	else
		rst_cnt <= 14'd0;
end
 //rst的時間一到就髮狀態轉移信號,開始下一輪
always @(posedge clk or negedge rst)
begin
	if(!rst)
	state_tran_rst <= 1'b0;
	else if(rst_cnt == RST)
	state_tran_rst <=1'b1;
	else
	state_tran_rst <= 1'b0;
end


		




endmodule

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章