基于低功耗蓝牙和微信小程序的门禁系统(FPGA课设设计)

这篇具有很好参考价值的文章主要介绍了基于低功耗蓝牙和微信小程序的门禁系统(FPGA课设设计)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于低功耗蓝牙和微信小程序的门禁系统(FPGA课设设计)

本次FPGA课程设计基于Cyclone IV的 EP4CE6F17C8。使用的是AX301开发板(正点原子的新起点也是用同一种芯片,只是要修改引脚)。

本系统能够实现通过蓝牙发送密码给FPGA,并在开发板的数码管上显示密码,密码正确,则手机端(微信小程序)接收到开门信号,并显示开门。其余时候显示关闭。
fpga蓝牙,fpga开发,微信小程序

一、低功耗蓝牙(BLE)的配置和与FPGA通信代码

1.1 低功耗蓝牙的介绍及配置

低功耗蓝牙的介绍见这篇文章:BLE基础知识详解
买到蓝牙模块后,使用AT指令对蓝牙进行配置,详见:常见蓝牙模块介绍和AT指令
fpga蓝牙,fpga开发,微信小程序
用串口调试助手配置蓝牙

1.2 低功耗蓝牙与FPGA通信

蓝牙通过串口收发实现与FPGA的数据交换,想要了解串口通信可以看这篇文章: 串口通信详解

代码:

// 串口接收模块
module uart_rx(
	input 			sys_clk,			//50M系统时钟
	input 			sys_rst_n,			//系统复位
	input 			uart_rxd,			//接收数据线
	output reg 		uart_rx_done,		//数据接收完成标志
	output reg [7:0]uart_rx_data		//接收到的数据
);
//常量化波特率,可更改
    parameter	BPS=9600;					//波特率9600bps,可更改
    parameter	SYS_CLK_FRE=50_000_000;		//50M系统时钟
    localparam	BPS_CNT=SYS_CLK_FRE/BPS;	//传输一位数据所需要的时钟个数
     
    reg 			uart_rx_d0;		//寄存1拍
    reg 			uart_rx_d1;		//寄存2拍
    reg [15:0]		clk_cnt;				//时钟计数器
    reg [3:0]		rx_cnt;					//接收计数器
    reg 			rx_flag;				//接收标志位
    reg [7:0]		uart_rx_data_reg;		//数据寄存
        
    wire 			neg_uart_rx_data;		//数据的下降沿
     
    assign	neg_uart_rx_data=uart_rx_d1 & (~uart_rx_d0);  //捕获数据线的下降沿,用来标志数据传输开始
    //将数据线打两拍,作用1:同步不同时钟域信号,防止亚稳态;作用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
    //捕获到数据下降沿(起始位0)后,拉高传输开始标志位,并在第9个数据(终止位)的传输过程正中(数据比较稳定)再将传输开始标志位拉低,标志传输结束
    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个数据(终止位)的传输过程正中(数据比较稳定)再将传输开始标志位拉低,标志传输结束
                rx_flag<=1'b0;
            else 
                rx_flag<=rx_flag;			
        end
    end
    //时钟每计数一个BPS_CNT(传输一位数据所需要的时钟个数),即将数据计数器加1,并清零时钟计数器
    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
    //在每个数据的传输过程正中(数据比较稳定)将数据线上的数据赋值给数据寄存器
    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	
    //当数据传输到终止位时,拉高传输完成标志位,并将数据输出
    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

// 串口发送模块
module uart_tx(
	input 			sys_clk,	//50M系统时钟
	input 			sys_rst_n,	//系统复位
	input	[7:0] 	uart_data,	//发送的8位置数据
	input			uart_tx_en,	//发送使能信号
	output reg 		uart_txd	//串口发送数据线
 
);
 
parameter 	SYS_CLK_FRE=50_000_000;    //50M系统时钟 
parameter 	BPS=9_600;                 //波特率9600bps,可更改
localparam	BPS_CNT=SYS_CLK_FRE/BPS;   //传输一位数据所需要的时钟个数
 
reg	uart_tx_en_d0;			//寄存1拍
reg uart_tx_en_d1;			//寄存2拍
reg tx_flag;				//发送标志位
reg [7:0]  uart_data_reg;	//发送数据寄存器
reg [15:0] clk_cnt;			//时钟计数器
reg [3:0]  tx_cnt;			//发送个数计数器
 
wire pos_uart_en_txd;		//使能信号的上升沿
//捕捉使能端的上升沿信号,用来标志输出开始传输
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
//捕获到使能端的上升沿信号,拉高传输开始标志位,并在第9个数据(终止位)的传输过程正中(数据比较稳定)再将传输开始标志位拉低,标志传输结束
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个数据(终止位)的传输过程正中(数据比较稳定)再将传输开始标志位拉低,标志传输结束
		tx_flag<=1'b0;
		uart_data_reg<=8'd0;
	end
	else begin
		uart_data_reg<=uart_data_reg;
		tx_flag<=tx_flag;	
	end
end
//时钟每计数一个BPS_CNT(传输一位数据所需要的时钟个数),即将数据计数器加1,并清零时钟计数器
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
//在每个数据的传输过程正中(数据比较稳定)将数据寄存器的数据赋值给数据线
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蓝牙,fpga开发,微信小程序

二、FPGA控制器的设计

由于串口接收器输出的是ASCII码(8位)的vector,这样检测6位密码需要6*8=48个寄存器。我们可以将接收端并行输出的8位数组经过译码器得到4位数组(0-9十进制数用4位二进制数表示)。这样不仅节省了寄存器,也使后续的计算变得方便。所以,我们首先设计84译码器。

2.1 8-4译码器的设计

原理比较简单,直接放代码。注意这里使用的是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必须只持续一个时钟周期,因为我没做上升沿检测
                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 主控器的设计

主控器的作用是接收发送的密码并存储,当密码正确时向手机端发送开门信号,其余时候发送关门信号。
同时,主控器还连接着数码管,能将输入的密码实时显示出来。
整体设计图如下:
fpga蓝牙,fpga开发,微信小程序我们小组的本课程设计是实现一整个智慧门控系统(包括VGA显示,开门驱动,摄像头识别开门,红外检测等),我只是将我本人的工作开源,我也负责整个智慧门控系统的主控设计,但这里不需要主控电路的代码,在这篇文章里,主控电路就是上述框图中的BLE_PSW_数码管控制器。
这里给出BLE_PSW_数码管控制器(即主控器)的代码

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;           --这里是上升沿检测的入口
        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;   --检测en_rxd的上升沿


    pin<="011001100110011001100110";     --密码的初值,就是66
    
    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为数码管不显示
--                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';                --串口发送未开门
                next_state <= s2;     
            when s2=>
                txd_out_buff := "00111111";
                en_txd <= not en_txd;  
                --disp_data <= "001000110110011110000101";   --1为数码管不显示
                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;                --串口发送开门
                if (shutdoor = '1') then
                    next_state <= s0;
                else
                    next_state <= s4;
                end if;
        end case;    
    end process com
end behav;

主控器的ASM图:
fpga蓝牙,fpga开发,微信小程序

Modelsim仿真结果
fpga蓝牙,fpga开发,微信小程序检查RTL图,我们可以通过RTL图更好理解代码
fpga蓝牙,fpga开发,微信小程序

三、数码管译码电路以及数码管轮询显示

数码管译码电路就是数码管7段译码器,轮询显示就是通过片选的方式每1ms给其中一个数码管供电,每6ms一循环,人的肉眼就看不出数码管的变化。
代码:

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永远高电平就行了
            when "0000"=> dig <= "0000001";   --数字0
            when "0001"=> dig <= "1001111";   --数字1
            when "0010"=> dig <= "0010010";   --数字2
            when "0011"=> dig <= "0000110";   --数字3
            when "0100"=> dig <= "1001100";   --数字4
            when "0101"=> dig <= "0100100";   --数字5
            when "0110"=> dig <= "0100000";   --数字6
            when "0111"=> dig <= "0001111";   --数字7
            when "1000"=> dig <= "0000000";   --数字8
            when "1001"=> dig <= "0000100";   --数字9
            when "1111"=> dig <= "1111111";   --全灭
            when others=> dig <= "1111111"; 
        end case;
    end process decode;
end behav;                                                  

最后整个电路整个蓝牙密码显示电路放在bdf图中如下所示。红框里的是本模块的电路。
fpga蓝牙,fpga开发,微信小程序这个程序存在一些接口是无用的,这些是为了和主控器通信的,到时候删掉就可以了。

四、微信小程序的设计

低功耗蓝牙微信小程序官方给出了很多示例代码,我的代码是参考这篇文章微信小程序调用Android手机蓝牙BLE传输数据 改写的。效果如下
fpga蓝牙,fpga开发,微信小程序fpga蓝牙,fpga开发,微信小程序fpga蓝牙,fpga开发,微信小程序
fpga蓝牙,fpga开发,微信小程序关键程序的代码(主要就是.js和.wxml)文章来源地址https://www.toymoban.com/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:'关闭',
    temperature:'20.0'
  },
  onLoad: function () {
 
  },
  open_BLE: function () {
    var that = this
 
    that.setData({
      isbluetoothready: !that.data.isbluetoothready,
    })
    if (that.data.isbluetoothready) {
      //开启蓝牙模块并初始化
      wx.openBluetoothAdapter({
        success: function (res) {
 
        },
        fail: function (res) {
          wx.showModal({
            title: '提示',
            content: '请检查手机蓝牙是否打开',
          })
        }
      })
      //开启蓝牙模块并初始化
 
      //检查蓝牙模块是否初始化成功
      wx.getBluetoothAdapterState({
        success: function (res) {
          var available = res.available
          if (!available) {
            wx.showToast({
              title: '蓝牙初始化失败',
              icon: 'loading',
              duration: 2000
            })
          }
          else {
            wx.showToast({
              title: '蓝牙初始化成功',
              icon: 'success',
              duration: 2000
            })
          }
        }
      })
      //检查蓝牙模块是否初始化成功
    }
    else{
      wx.closeBLEConnection({
        deviceId: that.data.connectedDeviceId,
        complete: function (res) {
          that.setData({
            deviceconnected: false,
            connectedDeviceId: ""
          })
          wx.showToast({
            title: '蓝牙连接断开',
            icon: 'success',
            duration: 2000
          })
        }
      })
      setTimeout(function () {
        that.setData({
          list: []
        })
        //释放蓝牙适配器
        wx.closeBluetoothAdapter({
          success: function (res) {
            that.setData({
              isbluetoothready: false,
              deviceconnected: false,
              devices: [],
              searchingstatus: false,
              receivedata: ''
            })
            wx.showToast({
              title: '蓝牙适配器释放',
              icon: 'success',
              duration: 2000
            })
          },
          fail: function (res) {
 
          }
        })
        //释放蓝牙适配器
      }, 1000)
    }
  },
 
  search_BLE: function () {
    temp = []
    var that = this
    if (!that.data.searchingstatus) {
      var that = this
      //开始搜索附近蓝牙设备
      wx.startBluetoothDevicesDiscovery({
        success: function (res) {
          wx.showToast({
            title: '开始搜索BLE',
            icon: 'loading',
            duration: 2000
          })
          that.setData({
            searchingstatus: !that.data.searchingstatus
          })
        }
      })
      //开始搜索附近蓝牙设备
    } else {
      //停止搜索附近蓝牙设备
      wx.stopBluetoothDevicesDiscovery({
        success: function (res) {
          wx.showToast({
            title: '停止搜索BLE',
            icon: 'success',
            duration: 2000
          })
          that.setData({
            searchingstatus: !that.data.searchingstatus
          })
        }
      })
      //停止搜索附近蓝牙设备
      setTimeout(function () {
        //获取发现的蓝牙设备
        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
            })
          }
        })
        //获取发现的蓝牙设备
      }, 1000) //1s后执行函数
    }
  },
 
  connectTO: function (e) {
    var that = this
      wx.showLoading({
        title: '连接蓝牙设备中...',
      })
      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转为16进制数
          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进制数转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("");
          }
          //监听回调,接收数据
          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='关闭'
              
            }
            else {state_of_door='开启'}

            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: '连接设备失败',
            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: '发送成功',
          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>蓝牙开关</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?"搜索中":"搜索蓝牙"}} </button>
   </view>
  
   <block wx:for="{{list}}">     <!-- 第三行 -->
     <view class="section" style="flex-direction:row" >
       <view>
         <text>{{index}}:\n </text>
         <text>设备名称:  {{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门的状态 \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密码发送:</text>
         <input name="senddata"/>
         <button size="mini" formType="submit">发送</button>
         <button size="mini" formType="reset">清空</button>
       </form>
     </view>
 </block>
  
 </view>

到了这里,关于基于低功耗蓝牙和微信小程序的门禁系统(FPGA课设设计)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Spring Boot和微信小程序的智能小程序商城

    🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 基于Spring Boot和微信小程序的智能小程序商城,java项目。 eclipse和idea都能打开运行。 推荐环境配置:eclipse/idea jdk1.8 maven

    2024年02月03日
    浏览(57)
  • 基于SpringBoot和微信小程序的校园快递平台系统

    🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 基于SpringBoot和微信小程序的校园快递平台系统,java项目。 eclipse和idea都能打开运行。 推荐环境配置:eclipse/idea jdk1.8 mav

    2024年02月03日
    浏览(51)
  • 基于SpringBoot的和微信小程序养老院管理系统

    🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 基于SpringBoot的和微信小程序养老院管理系统,java项目。 eclipse和idea都能打开运行。 推荐环境配置:eclipse/idea jdk1.8 maven

    2024年02月03日
    浏览(54)
  • 【开源】基于Vue.js和微信小程序的班级考勤管理系统

    文末获取源码,项目编号: S 080 。 color{red}{文末获取源码,项目编号:S080。} 文末获取源码,项目编号: S 080 。 基于JAVA+Vue+SpringBoot+MySQL的班级考勤管理系统,分为微信小程序端和管理后台,包含了学生档案、班级档案、教师档案、学生考勤、学生请假模块,还包含系统自

    2024年02月02日
    浏览(49)
  • 基于Spring、SpringMVC、MyBatis和微信小程序的点餐系统

    🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 基于Spring、SpringMVC、MyBatis和微信小程序的点餐系统,java项目。 eclipse和idea都能打开运行。 推荐环境配置:eclipse/idea jdk1

    2024年02月05日
    浏览(43)
  • 基于SpringBoot和微信小程序的校园失物招领系统的设计与实现

    🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 基于SpringBoot和微信小程序的校园失物招领系统的设计与实现,java项目。 eclipse和idea都能打开运行。 推荐环境配置:eclip

    2024年01月16日
    浏览(49)
  • 【简单小程序项目源码】基于python和微信小程序的刷题系统设计与实现

    ​ 目录 一、整体目录: 文档含项目摘要、前言、技术介绍、可行性分析、流程图、结构图、ER属性图、数据库表结构信息、功能介绍、测试致谢等约1万字等 二、运行截图 三、代码部分(示范): 四、数据库表(示范): 数据库表有注释,可以导出数据字典及更新数据库时间

    2024年02月04日
    浏览(59)
  • 微信小程序和微信H5有什么区别?

    前言:进入公司会发现会从最常见的PC端开发,慢慢将重心转移到H5开发,再到小程序开发,后面随着公司业务的发展还需要开发APP,也就是Android。也有可能顺序不一样,作为一个合格的后端甚至全栈,这些还是要会的。 在开发微信小程序功能的时候,发现微信小程序和微信

    2024年02月11日
    浏览(56)
  • uniapp和微信小程序去掉顶部标题

    今天刚开始做一个uniapp的项目,新建的项目带有默认顶部标题,要去掉。 找到配置文件pages.json,小程序在app.json 添加代码 完成。 最后这个项目会一直更新所遇到的问题,可能会比较慢,希望自己能够坚持完成。

    2024年02月13日
    浏览(50)
  • 【uniapp】多端(H5和微信小程序)

    目录 一、运行H5页面 二、去除H5顶部导航栏 三、区分H5页面和微信小程序的样式 四、H5页面下载视频、PDF 五、H5页面适配  打开网页后复制网页地址 然后打开微信开发者工具,点击公众号网页版,输入地址即可看到H5页面 无论是页面还是js还是css,都是一样的使用,样式如下

    2024年02月10日
    浏览(108)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包