基于低功耗藍(lán)牙和微信小程序的門(mén)禁系統(tǒng)(FPGA課設(shè)設(shè)計(jì))
本次FPGA課程設(shè)計(jì)基于Cyclone IV的 EP4CE6F17C8。使用的是AX301開(kāi)發(fā)板(正點(diǎn)原子的新起點(diǎn)也是用同一種芯片,只是要修改引腳)。
本系統(tǒng)能夠?qū)崿F(xiàn)通過(guò)藍(lán)牙發(fā)送密碼給FPGA,并在開(kāi)發(fā)板的數(shù)碼管上顯示密碼,密碼正確,則手機(jī)端(微信小程序)接收到開(kāi)門(mén)信號(hào),并顯示開(kāi)門(mén)。其余時(shí)候顯示關(guān)閉。
一、低功耗藍(lán)牙(BLE)的配置和與FPGA通信代碼
1.1 低功耗藍(lán)牙的介紹及配置
低功耗藍(lán)牙的介紹見(jiàn)這篇文章:BLE基礎(chǔ)知識(shí)詳解
買(mǎi)到藍(lán)牙模塊后,使用AT指令對(duì)藍(lán)牙進(jìn)行配置,詳見(jiàn):常見(jiàn)藍(lán)牙模塊介紹和AT指令
用串口調(diào)試助手配置藍(lán)牙
1.2 低功耗藍(lán)牙與FPGA通信
藍(lán)牙通過(guò)串口收發(fā)實(shí)現(xiàn)與FPGA的數(shù)據(jù)交換,想要了解串口通信可以看這篇文章: 串口通信詳解
代碼:
// 串口接收模塊
module uart_rx(
input sys_clk, //50M系統(tǒng)時(shí)鐘
input sys_rst_n, //系統(tǒng)復(fù)位
input uart_rxd, //接收數(shù)據(jù)線
output reg uart_rx_done, //數(shù)據(jù)接收完成標(biāo)志
output reg [7:0]uart_rx_data //接收到的數(shù)據(jù)
);
//常量化波特率,可更改
parameter BPS=9600; //波特率9600bps,可更改
parameter SYS_CLK_FRE=50_000_000; //50M系統(tǒng)時(shí)鐘
localparam BPS_CNT=SYS_CLK_FRE/BPS; //傳輸一位數(shù)據(jù)所需要的時(shí)鐘個(gè)數(shù)
reg uart_rx_d0; //寄存1拍
reg uart_rx_d1; //寄存2拍
reg [15:0] clk_cnt; //時(shí)鐘計(jì)數(shù)器
reg [3:0] rx_cnt; //接收計(jì)數(shù)器
reg rx_flag; //接收標(biāo)志位
reg [7:0] uart_rx_data_reg; //數(shù)據(jù)寄存
wire neg_uart_rx_data; //數(shù)據(jù)的下降沿
assign neg_uart_rx_data=uart_rx_d1 & (~uart_rx_d0); //捕獲數(shù)據(jù)線的下降沿,用來(lái)標(biāo)志數(shù)據(jù)傳輸開(kāi)始
//將數(shù)據(jù)線打兩拍,作用1:同步不同時(shí)鐘域信號(hào),防止亞穩(wěn)態(tài);作用2:用以捕獲下降沿
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_rx_d0<=1'b0;
uart_rx_d1<=1'b0;
end
else begin
uart_rx_d0<=uart_rxd;
uart_rx_d1<=uart_rx_d0;
end
end
//捕獲到數(shù)據(jù)下降沿(起始位0)后,拉高傳輸開(kāi)始標(biāo)志位,并在第9個(gè)數(shù)據(jù)(終止位)的傳輸過(guò)程正中(數(shù)據(jù)比較穩(wěn)定)再將傳輸開(kāi)始標(biāo)志位拉低,標(biāo)志傳輸結(jié)束
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rx_flag<=1'b0;
else begin
if(neg_uart_rx_data)
rx_flag<=1'b1;
else if((rx_cnt==4'd9)&&(clk_cnt==BPS_CNT/2))//在第9個(gè)數(shù)據(jù)(終止位)的傳輸過(guò)程正中(數(shù)據(jù)比較穩(wěn)定)再將傳輸開(kāi)始標(biāo)志位拉低,標(biāo)志傳輸結(jié)束
rx_flag<=1'b0;
else
rx_flag<=rx_flag;
end
end
//時(shí)鐘每計(jì)數(shù)一個(gè)BPS_CNT(傳輸一位數(shù)據(jù)所需要的時(shí)鐘個(gè)數(shù)),即將數(shù)據(jù)計(jì)數(shù)器加1,并清零時(shí)鐘計(jì)數(shù)器
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
rx_cnt<=4'd0;
clk_cnt<=16'd0;
end
else if(rx_flag)begin
if(clk_cnt<BPS_CNT-1'b1)begin
clk_cnt<=clk_cnt+1'b1;
rx_cnt<=rx_cnt;
end
else begin
clk_cnt<=16'd0;
rx_cnt<=rx_cnt+1'b1;
end
end
else begin
rx_cnt<=4'd0;
clk_cnt<=16'd0;
end
end
//在每個(gè)數(shù)據(jù)的傳輸過(guò)程正中(數(shù)據(jù)比較穩(wěn)定)將數(shù)據(jù)線上的數(shù)據(jù)賦值給數(shù)據(jù)寄存器
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
uart_rx_data_reg<=8'd0;
else if(rx_flag)
if(clk_cnt==BPS_CNT/2) begin
case(rx_cnt)
4'd1:uart_rx_data_reg[0]<=uart_rxd;
4'd2:uart_rx_data_reg[1]<=uart_rxd;
4'd3:uart_rx_data_reg[2]<=uart_rxd;
4'd4:uart_rx_data_reg[3]<=uart_rxd;
4'd5:uart_rx_data_reg[4]<=uart_rxd;
4'd6:uart_rx_data_reg[5]<=uart_rxd;
4'd7:uart_rx_data_reg[6]<=uart_rxd;
4'd8:uart_rx_data_reg[7]<=uart_rxd;
default:;
endcase
end
else
uart_rx_data_reg<=uart_rx_data_reg;
else
uart_rx_data_reg<=8'd0;
end
//當(dāng)數(shù)據(jù)傳輸?shù)浇K止位時(shí),拉高傳輸完成標(biāo)志位,并將數(shù)據(jù)輸出
always@(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_rx_done<=1'b0;
uart_rx_data<=8'd0;
end
else if(rx_cnt==4'd9)begin
uart_rx_done<=1'b1;
uart_rx_data<=uart_rx_data_reg;
end
else begin
uart_rx_done<=1'b0;
uart_rx_data<=8'd0;
end
end
endmodule
// 串口發(fā)送模塊
module uart_tx(
input sys_clk, //50M系統(tǒng)時(shí)鐘
input sys_rst_n, //系統(tǒng)復(fù)位
input [7:0] uart_data, //發(fā)送的8位置數(shù)據(jù)
input uart_tx_en, //發(fā)送使能信號(hào)
output reg uart_txd //串口發(fā)送數(shù)據(jù)線
);
parameter SYS_CLK_FRE=50_000_000; //50M系統(tǒng)時(shí)鐘
parameter BPS=9_600; //波特率9600bps,可更改
localparam BPS_CNT=SYS_CLK_FRE/BPS; //傳輸一位數(shù)據(jù)所需要的時(shí)鐘個(gè)數(shù)
reg uart_tx_en_d0; //寄存1拍
reg uart_tx_en_d1; //寄存2拍
reg tx_flag; //發(fā)送標(biāo)志位
reg [7:0] uart_data_reg; //發(fā)送數(shù)據(jù)寄存器
reg [15:0] clk_cnt; //時(shí)鐘計(jì)數(shù)器
reg [3:0] tx_cnt; //發(fā)送個(gè)數(shù)計(jì)數(shù)器
wire pos_uart_en_txd; //使能信號(hào)的上升沿
//捕捉使能端的上升沿信號(hào),用來(lái)標(biāo)志輸出開(kāi)始傳輸
assign pos_uart_en_txd= uart_tx_en_d0 && (~uart_tx_en_d1);
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
uart_tx_en_d0<=1'b0;
uart_tx_en_d1<=1'b0;
end
else begin
uart_tx_en_d0<=uart_tx_en;
uart_tx_en_d1<=uart_tx_en_d0;
end
end
//捕獲到使能端的上升沿信號(hào),拉高傳輸開(kāi)始標(biāo)志位,并在第9個(gè)數(shù)據(jù)(終止位)的傳輸過(guò)程正中(數(shù)據(jù)比較穩(wěn)定)再將傳輸開(kāi)始標(biāo)志位拉低,標(biāo)志傳輸結(jié)束
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
tx_flag<=1'b0;
uart_data_reg<=8'd0;
end
else if(pos_uart_en_txd)begin
uart_data_reg<=uart_data;
tx_flag<=1'b1;
end
else if((tx_cnt==4'd9) && (clk_cnt==BPS_CNT/2))begin//在第9個(gè)數(shù)據(jù)(終止位)的傳輸過(guò)程正中(數(shù)據(jù)比較穩(wěn)定)再將傳輸開(kāi)始標(biāo)志位拉低,標(biāo)志傳輸結(jié)束
tx_flag<=1'b0;
uart_data_reg<=8'd0;
end
else begin
uart_data_reg<=uart_data_reg;
tx_flag<=tx_flag;
end
end
//時(shí)鐘每計(jì)數(shù)一個(gè)BPS_CNT(傳輸一位數(shù)據(jù)所需要的時(shí)鐘個(gè)數(shù)),即將數(shù)據(jù)計(jì)數(shù)器加1,并清零時(shí)鐘計(jì)數(shù)器
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
clk_cnt<=16'd0;
tx_cnt <=4'd0;
end
else if(tx_flag) begin
if(clk_cnt<BPS_CNT-1)begin
clk_cnt<=clk_cnt+1'b1;
tx_cnt <=tx_cnt;
end
else begin
clk_cnt<=16'd0;
tx_cnt <=tx_cnt+1'b1;
end
end
else begin
clk_cnt<=16'd0;
tx_cnt<=4'd0;
end
end
//在每個(gè)數(shù)據(jù)的傳輸過(guò)程正中(數(shù)據(jù)比較穩(wěn)定)將數(shù)據(jù)寄存器的數(shù)據(jù)賦值給數(shù)據(jù)線
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
uart_txd<=1'b1;
else if(tx_flag)
case(tx_cnt)
4'd0: uart_txd<=1'b0;
4'd1: uart_txd<=uart_data_reg[0];
4'd2: uart_txd<=uart_data_reg[1];
4'd3: uart_txd<=uart_data_reg[2];
4'd4: uart_txd<=uart_data_reg[3];
4'd5: uart_txd<=uart_data_reg[4];
4'd6: uart_txd<=uart_data_reg[5];
4'd7: uart_txd<=uart_data_reg[6];
4'd8: uart_txd<=uart_data_reg[7];
4'd9: uart_txd<=1'b1;
default:;
endcase
else
uart_txd<=1'b1;
end
endmodule
編譯代碼后可以生成元件,放入bdf中
如下圖所示
二、FPGA控制器的設(shè)計(jì)
由于串口接收器輸出的是ASCII碼(8位)的vector,這樣檢測(cè)6位密碼需要6*8=48個(gè)寄存器。我們可以將接收端并行輸出的8位數(shù)組經(jīng)過(guò)譯碼器得到4位數(shù)組(0-9十進(jìn)制數(shù)用4位二進(jìn)制數(shù)表示)。這樣不僅節(jié)省了寄存器,也使后續(xù)的計(jì)算變得方便。所以,我們首先設(shè)計(jì)84譯碼器。
2.1 8-4譯碼器的設(shè)計(jì)
原理比較簡(jiǎn)單,直接放代碼。注意這里使用的是VHDL代碼。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity uart_rx_encoder is
port(clk, en_rxd: in std_logic;
en_rxd_next: out std_logic;
D: in std_logic_vector(7 downto 0);
Q: out std_logic_vector(3 downto 0));
end entity;
architecture behav of uart_rx_encoder is
signal data: std_logic_vector(7 downto 0);
begin
process(clk)
begin
if (clk'event and clk='1') then
if (en_rxd = '1') then --en_rxd必須只持續(xù)一個(gè)時(shí)鐘周期,因?yàn)槲覜](méi)做上升沿檢測(cè)
data <= D;
en_rxd_next<='1';
else
en_rxd_next<='0';
end if;
end if;
end process;
with data select
Q<= "0000" when "00110000",
"0001" when "00110001",
"0010" when "00110010",
"0011" when "00110011",
"0100" when "00110100",
"0101" when "00110101",
"0110" when "00110110",
"0111" when "00110111",
"1000" when "00111000",
"1001" when "00111001",
"1111" when others;
end behav;
2.2 主控器的設(shè)計(jì)
主控器的作用是接收發(fā)送的密碼并存儲(chǔ),當(dāng)密碼正確時(shí)向手機(jī)端發(fā)送開(kāi)門(mén)信號(hào),其余時(shí)候發(fā)送關(guān)門(mén)信號(hào)。
同時(shí),主控器還連接著數(shù)碼管,能將輸入的密碼實(shí)時(shí)顯示出來(lái)。
整體設(shè)計(jì)圖如下:我們小組的本課程設(shè)計(jì)是實(shí)現(xiàn)一整個(gè)智慧門(mén)控系統(tǒng)(包括VGA顯示,開(kāi)門(mén)驅(qū)動(dòng),攝像頭識(shí)別開(kāi)門(mén),紅外檢測(cè)等),我只是將我本人的工作開(kāi)源,我也負(fù)責(zé)整個(gè)智慧門(mén)控系統(tǒng)的主控設(shè)計(jì),但這里不需要主控電路的代碼,在這篇文章里,主控電路就是上述框圖中的BLE_PSW_數(shù)碼管控制器。
這里給出BLE_PSW_數(shù)碼管控制器(即主控器)的代碼
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ble_led_psw_controller2 is
port(clk,rst: in std_logic;
en_rxd,shutdoor: in std_logic;
indata: in std_logic_vector(3 downto 0);
ledout: out std_logic_vector(23 downto 0);
doorstate: out std_logic;
en_txd: buffer std_logic;
txd_out: out std_logic_vector(7 downto 0));
end entity;
architecture behav of ble_led_psw_controller2 is
type state_type is (s0,s1,s2,s3,s4);
signal present_state, next_state : state_type;
signal disp_data: std_logic_vector(27 downto 0);
signal pin: std_logic_vector(23 downto 0);
signal en_rxd0,en_rxd1,en_rxd_posedge: std_logic;
begin
process(clk)
begin
if clk'event and clk = '1' then
en_rxd0 <= en_rxd; --這里是上升沿檢測(cè)的入口
end if;
end process;
process(clk)
begin
if clk'event and clk = '1' then
en_rxd1 <= en_rxd0;
end if;
end process;
en_rxd_posedge <= en_rxd0 and not en_rxd1; --檢測(cè)en_rxd的上升沿
pin<="011001100110011001100110"; --密碼的初值,就是6個(gè)6
seq:process(clk,en_rxd_posedge)
variable count : integer range 0 to 4;
begin
if rst='0' then
disp_data <= "1111111111111111111111111111";
if (present_state /= s4) then
present_state <= s0;
else
present_state <= s4;
end if;
elsif (rising_edge(clk)) then
present_state <= next_state;
if (en_rxd_posedge = '1') then
disp_data(3 downto 0) <= indata;
count := 4;
elsif count > 0 then
disp_data <= to_stdlogicvector(to_bitvector(disp_data) sll 1);
count := count - 1;
end if;
case present_state is
when s0=>
disp_data <= "1111111111111111111111111111";
when others=>
null;
end case;
-- case present_state is
-- when s0=>
-- disp_data <= "001000110110011110000101"; --全1為數(shù)碼管不顯示
-- when s1=>
-- disp_data <= "001000110110011110000101";
-- when s2=>
-- if (en_rxd_posedge = '1')then
-- disp_data <= disp_data(19 downto 0) & indata ;
-- end if;
-- when others=>null;
-- end case;
end if;
end process seq;
ledout <= disp_data(27 downto 4);
com:process(present_state,en_rxd_posedge,shutdoor)
variable txd_out_buff: std_logic_vector(7 downto 0);
begin
doorstate <= '0';
en_txd <= '0';
txd_out <= txd_out_buff;
case present_state is
when s0=>
next_state <= s1;
when s1=>
txd_out_buff := "00111111";
en_txd <= '1'; --串口發(fā)送未開(kāi)門(mén)
next_state <= s2;
when s2=>
txd_out_buff := "00111111";
en_txd <= not en_txd;
--disp_data <= "001000110110011110000101"; --全1為數(shù)碼管不顯示
if (en_rxd_posedge = '1')then
next_state <= s3;
else
next_state <= s2;
end if;
when s3=>
if (disp_data(27 downto 4) = pin) then
next_state <= s4;
doorstate <= '1';
else
next_state <= s1;
end if;
when s4=>
txd_out_buff := "00111110";
en_txd <= not en_txd; --串口發(fā)送開(kāi)門(mén)
if (shutdoor = '1') then
next_state <= s0;
else
next_state <= s4;
end if;
end case;
end process com
end behav;
主控器的ASM圖:
Modelsim仿真結(jié)果檢查RTL圖,我們可以通過(guò)RTL圖更好理解代碼
三、數(shù)碼管譯碼電路以及數(shù)碼管輪詢顯示
數(shù)碼管譯碼電路就是數(shù)碼管7段譯碼器,輪詢顯示就是通過(guò)片選的方式每1ms給其中一個(gè)數(shù)碼管供電,每6ms一循環(huán),人的肉眼就看不出數(shù)碼管的變化。
代碼:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity leddisplay is
port(in_information: in std_logic_vector(23 downto 0);
clk,rst: in std_logic;
sel: out std_logic_vector(5 downto 0);
dig: out std_logic_vector(6 downto 0);
cnt_ceshi: out std_logic_vector(14 downto 0);
clk1_ceshi: out std_logic);
end leddisplay;
architecture behav of leddisplay is
signal sel_count: std_logic_vector(2 downto 0);
signal original_information: std_logic_vector(3 downto 0);
signal clk1: std_logic;
begin
freq_divide:process(clk,rst)
variable cnt : std_logic_vector(14 downto 0);
begin
if (rst='0') then
cnt:="000000000000000";
clk1 <= '0';
elsif (clk'event and clk = '1') then
if (cnt = "110000110100111") then
--if (cnt = "000000000000111") then
cnt:="000000000000000";
clk1 <= not clk1;
else cnt:=cnt+'1';
end if;
end if;
cnt_ceshi <= cnt;
end process freq_divide;
clk1_ceshi <= clk1;
sel_counter:process(clk1)
begin
if (rst='0') then
sel_count<="000";
elsif (rising_edge(clk1)) then
if (sel_count = "101") then
sel_count<="000";
else sel_count<=sel_count+'1';
end if;
end if;
end process sel_counter;
display:process(sel_count)
begin
case sel_count is
when "000" => sel <= "011111"; original_information<=in_information(3 downto 0);
when "001" => sel <= "101111"; original_information<=in_information(7 downto 4);
when "010" => sel <= "110111"; original_information<=in_information(11 downto 8);
when "011" => sel <= "111011"; original_information<=in_information(15 downto 12);
when "100" => sel <= "111101"; original_information<=in_information(19 downto 16);
when "101" => sel <= "111110"; original_information<=in_information(23 downto 20);
when others=> null;
end case;
end process display;
decode:process(original_information)
begin
case original_information is --我們按照從高到低為ABCDEFG,讓H永遠(yuǎn)高電平就行了
when "0000"=> dig <= "0000001"; --數(shù)字0
when "0001"=> dig <= "1001111"; --數(shù)字1
when "0010"=> dig <= "0010010"; --數(shù)字2
when "0011"=> dig <= "0000110"; --數(shù)字3
when "0100"=> dig <= "1001100"; --數(shù)字4
when "0101"=> dig <= "0100100"; --數(shù)字5
when "0110"=> dig <= "0100000"; --數(shù)字6
when "0111"=> dig <= "0001111"; --數(shù)字7
when "1000"=> dig <= "0000000"; --數(shù)字8
when "1001"=> dig <= "0000100"; --數(shù)字9
when "1111"=> dig <= "1111111"; --全滅
when others=> dig <= "1111111";
end case;
end process decode;
end behav;
最后整個(gè)電路整個(gè)藍(lán)牙密碼顯示電路放在bdf圖中如下所示。紅框里的是本模塊的電路。這個(gè)程序存在一些接口是無(wú)用的,這些是為了和主控器通信的,到時(shí)候刪掉就可以了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-720205.html
四、微信小程序的設(shè)計(jì)
低功耗藍(lán)牙微信小程序官方給出了很多示例代碼,我的代碼是參考這篇文章微信小程序調(diào)用Android手機(jī)藍(lán)牙BLE傳輸數(shù)據(jù) 改寫(xiě)的。效果如下關(guān)鍵程序的代碼(主要就是.js和.wxml)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-720205.html
4.1 bluetooth.js
// An highlighted block
// pages/bluetooth/bluetooth.js
var app = getApp()
var temp = []
var string_temp=""
var serviceId = "0000ffe0-0000-1000-8000-00805f9b34fb"
var characteristicId = "0000ffe1-0000-1000-8000-00805f9b34fb"
Page({
data: {
isbluetoothready: false,
defaultSize: 'default',
primarySize: 'default',
warnSize: 'default',
disabled: false,
plain: false,
loading: false,
searchingstatus: false,
receivedata: '666',
onreceiving: false,
id_text: string_temp,
list: [],
receive_data:'none',
door_state:'關(guān)閉',
temperature:'20.0'
},
onLoad: function () {
},
open_BLE: function () {
var that = this
that.setData({
isbluetoothready: !that.data.isbluetoothready,
})
if (that.data.isbluetoothready) {
//開(kāi)啟藍(lán)牙模塊并初始化
wx.openBluetoothAdapter({
success: function (res) {
},
fail: function (res) {
wx.showModal({
title: '提示',
content: '請(qǐng)檢查手機(jī)藍(lán)牙是否打開(kāi)',
})
}
})
//開(kāi)啟藍(lán)牙模塊并初始化
//檢查藍(lán)牙模塊是否初始化成功
wx.getBluetoothAdapterState({
success: function (res) {
var available = res.available
if (!available) {
wx.showToast({
title: '藍(lán)牙初始化失敗',
icon: 'loading',
duration: 2000
})
}
else {
wx.showToast({
title: '藍(lán)牙初始化成功',
icon: 'success',
duration: 2000
})
}
}
})
//檢查藍(lán)牙模塊是否初始化成功
}
else{
wx.closeBLEConnection({
deviceId: that.data.connectedDeviceId,
complete: function (res) {
that.setData({
deviceconnected: false,
connectedDeviceId: ""
})
wx.showToast({
title: '藍(lán)牙連接斷開(kāi)',
icon: 'success',
duration: 2000
})
}
})
setTimeout(function () {
that.setData({
list: []
})
//釋放藍(lán)牙適配器
wx.closeBluetoothAdapter({
success: function (res) {
that.setData({
isbluetoothready: false,
deviceconnected: false,
devices: [],
searchingstatus: false,
receivedata: ''
})
wx.showToast({
title: '藍(lán)牙適配器釋放',
icon: 'success',
duration: 2000
})
},
fail: function (res) {
}
})
//釋放藍(lán)牙適配器
}, 1000)
}
},
search_BLE: function () {
temp = []
var that = this
if (!that.data.searchingstatus) {
var that = this
//開(kāi)始搜索附近藍(lán)牙設(shè)備
wx.startBluetoothDevicesDiscovery({
success: function (res) {
wx.showToast({
title: '開(kāi)始搜索BLE',
icon: 'loading',
duration: 2000
})
that.setData({
searchingstatus: !that.data.searchingstatus
})
}
})
//開(kāi)始搜索附近藍(lán)牙設(shè)備
} else {
//停止搜索附近藍(lán)牙設(shè)備
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
wx.showToast({
title: '停止搜索BLE',
icon: 'success',
duration: 2000
})
that.setData({
searchingstatus: !that.data.searchingstatus
})
}
})
//停止搜索附近藍(lán)牙設(shè)備
setTimeout(function () {
//獲取發(fā)現(xiàn)的藍(lán)牙設(shè)備
wx.getBluetoothDevices({
success: function (res) {
for(var i=0;i<100;i++){
if (res.devices[i]) {
string_temp = string_temp + '\n' + res.devices[i].deviceId
}
}
that.setData({
id_text: string_temp,
list: res.devices
})
}
})
//獲取發(fā)現(xiàn)的藍(lán)牙設(shè)備
}, 1000) //1s后執(zhí)行函數(shù)
}
},
connectTO: function (e) {
var that = this
wx.showLoading({
title: '連接藍(lán)牙設(shè)備中...',
})
wx.createBLEConnection({
deviceId: e.currentTarget.id,
success: function (res) {
wx.hideLoading()
wx.showToast({
title: '連接成功',
icon: 'success',
duration: 1000
})
that.setData({
deviceconnected: true,
connectedDeviceId: e.currentTarget.id
})
// 啟用 notify 功能
wx.notifyBLECharacteristicValueChanged({
state: true,
deviceId: that.data.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success: function (res) {
}
})
// 啟用 notify 功能
// ArrayBuffer轉(zhuǎn)為16進(jìn)制數(shù)
function ab2hex(buffer) {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}
// 16進(jìn)制數(shù)轉(zhuǎn)ASCLL碼
function hexCharCodeToStr(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
}
//監(jiān)聽(tīng)回調(diào),接收數(shù)據(jù)
wx.onBLECharacteristicValueChange(function (characteristic) {
var hex = ab2hex(characteristic.value)
var string = hexCharCodeToStr(hex)
var state_of_door
var tem_temperature
if(string.charAt(0)=='?'){
state_of_door='關(guān)閉'
}
else {state_of_door='開(kāi)啟'}
if(string.charAt(0)=='s'){
if(string.slice(2,6)){tem_temperature=string.slice(2,6)}
else{tem_temperature='error'}
}
else {tem_temperature='error'}
that.setData({
receive_data: hexCharCodeToStr(hex),
door_state: state_of_door,
temperature: tem_temperature
})
})
},
fail: function (res) {
wx.hideLoading()
wx.showToast({
title: '連接設(shè)備失敗',
icon: 'success',
duration: 1000
})
that.setData({
connected: false
})
}
})
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
}
})
},
formSubmit: function (e) {
var senddata = e.detail.value.senddata;
var that = this
let buffer = new ArrayBuffer(senddata.length)
let dataView = new DataView(buffer)
for (var i = 0; i < senddata.length; i++) {
dataView.setUint8(i, senddata.charAt(i).charCodeAt())
}
wx.writeBLECharacteristicValue({
deviceId: that.data.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: buffer,
success: function (res) {
wx.showToast({
title: '發(fā)送成功',
icon: 'success',
duration: 2000
})
}
})
},
receiveMessages: function () {
var that = this;
wx.readBLECharacteristicValue({
deviceId: that.data.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success: function (res) {
}
})
},
})
4.2 bluetooth.wxml
// An highlighted block
<!--pages/bluetooth/bluetooth.wxml-->
<!--pages/mine/mine.wxml-->
<view class="container">
<view class="section"> <!-- 第一行 -->
<view class="content">
<text>藍(lán)牙開(kāi)關(guān)</text>
</view>
<view class="switch">
<switch checked="{{isbluetoothready}}" bindchange="open_BLE" />
</view>
</view>
<view class="section"> <!-- 第二行 -->
<button type="default" size="{{primarySize}}" loading="{{searchingstatus}}" plain="{{plain}}" disabled="{{disabled}}" bindtap="search_BLE"> {{searchingstatus?"搜索中":"搜索藍(lán)牙"}} </button>
</view>
<block wx:for="{{list}}"> <!-- 第三行 -->
<view class="section" style="flex-direction:row" >
<view>
<text>{{index}}:\n </text>
<text>設(shè)備名稱: {{item.name}}\n</text>
<text>MAC地址: {{item.deviceId}}</text>
</view>
<view class="connection">
<button id="{{item.deviceId}}" size="mini"
bindtap="connectTO"> {{deviceconnected?"已連接":"連接"}} </button>
</view>
</view>
</block>
<block wx:if="{{deviceconnected}}"> <!-- 第四行 -->
<view class="content1">
<text decode="{{true}}" space="{{true}}">\n\n門(mén)的狀態(tài) \n</text>
<!-- <text>{{receive_data}}\n</text> -->
<!-- <button size="mini" bindtap="receiveMessages">接收</button> -->
</view>
<view class="content1">
<!-- <text>{{receive_data}}\n</text> -->
<text decode="{{true}}" space="{{true}}">{{door_state}}\n</text>
<!-- <button size="mini" bindtap="receiveMessages">接收</button> -->
</view>
<view class="send">
<form bindsubmit="formSubmit">
<text>\n\n密碼發(fā)送:</text>
<input name="senddata"/>
<button size="mini" formType="submit">發(fā)送</button>
<button size="mini" formType="reset">清空</button>
</form>
</view>
</block>
</view>
到了這里,關(guān)于基于低功耗藍(lán)牙和微信小程序的門(mén)禁系統(tǒng)(FPGA課設(shè)設(shè)計(jì))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!