• 手机打开蓝牙可以搜索到蓝牙芯片并可以连接连接码为1234。系统开启后数码管全0,继电器低电平,LED灯不亮。 手机连接到系统后,扫描二维码,得到一串数字后,输入该串密码,得以解锁继电器。输入密码,支持断点续...

    一.实验结果

    手机安装HC-PDA-ANDROID.apk软件后,开启系统。手机打开蓝牙可以搜索到蓝牙芯片并可以连接,连接码为1234。系统开启后数码管全0,继电器低电平,LED灯不亮。

    手机连接到系统后,扫描二维码,得到一串数字后,输入该串密码,得以解锁继电器。输入密码,支持断点续传密码,如本次输入“123”,再次输入“456”,即可完成输入“123456”。输入错误可以选择按键S5清空输入后重新输入。单片机暂时内部设置密码为“12345678”。输入密码的过程中,流水灯会展示输入密码的最后一个字符的ASCII码,用于指示传输过程中字符是否正确被接收。如果输入了错误的密码,则会返回一串错误提示消息,并将数码管清空。输入错误的字符后,流水灯全亮。

    输入正确的密码后,继电器高电平,LED构成回路后点亮,返回给手机端计费信息和成功解锁提示。数码管开始计时,每10毫秒变动一次,8个数码管两个一组,分别显示小时、分钟、秒、十毫秒。当处于计费状态时,手机端发送数据,返回无法发送的字样。按下按键S4后,停止计费,返回到手机端计时时长和本次费用,数码管清零,等待下次解锁。

    二.单片机工作原理

    51单片机有P0、P1、P2、P3四个端口。本次实验将其中P0用于数码管的显示数字,P1用于流水灯的显示,P2端口的第1位(P2^1)接在继电器的DIO端,在单片机内控制高低电平。P3端口的第0位连接蓝牙的TX端,是单片机串口的接收端,P3端口的第1位连接蓝牙的RX端,是单片机串口的发送端。按键S4在内部连接P3端口的第2位,为外部中断0。按键S5在内部连接P3端口的第3位,为外部中断1。开启定时器0,设置好计数器的初始值;外部中断0,1打开;串口中断打开,设置好波特率9600,0,0与蓝牙模块一致即可。

    串口的中断触发后,需要软件清除RI(接收中断)与TI(发送中断)值为0,SBUF存放串口接收数据或发送数据,在C语言代码中赋值相同寄存器,在物理上分为发送和接收,每次1字节缓冲。

    定时器0设置工作方式0,13位计数器,计数到8192。晶振为11.0592MHz,每个机器周期需要12个时钟周期,计数5000次,所以每次进入中断的时间为5000*12/11.0592M=0.00543s,所以每次进入中断时间为0.005秒,数码管需要每10ms进入一次,所以每次加到2的时候,数码管变动。计数器初值为(8192-5000),分别存放入TH0与TL0,高低位。

    外部中断直接设置触发方式ITx=0/1低电平触发或下降沿触发后,开启外部中断,EXx=1后,编写相应中断函数即可。

    蓝牙模块首先按住复位键上电,即进入AT指令模式,对它输入AT指令进行设置名字、串口波特率、主从回环等后,连接到单片机上即可使用。

    三.模块工作原理

    二维码扫描APP:

    通过谷歌开源ZXing库开发了一款安卓APP,并安装到手机,扫描出数据后通过蓝牙模块输入到单片机中。

    扫描后为“12345678”。


    蓝牙模块HC-05:

    TX连接单片机P3.0口,RX连接单片机P3.1口。

    在蓝牙模块连接到单片机上前,首先通过USB-TTL转接器,连接到电脑上后,通过串口调试助手调试。首先进入命令调试模式,输入AT指令,设置模块的参数。

    设置蓝牙的名称,用指令

    AT+name=”LiMou”\r\n          设置蓝牙模块名字为LiMou,方便后续查找。

    设置自动连接模式的串口波特率为9600,用指令

    AT+uart=9600,0,0\r\n             设置波特率为9600,停止位1位,无校验位。

    用于手机与单片机之间的通信者,发送密码到密码上,在接入计费系统时,向手机端发送解锁成功标志,并提供计费标准。解锁失败发送解锁失败指示。

    测试问题:

    如果串口收不到数据,换一个模块。

    如果单片机收到数据错误,调整波特率,通过串口助手调节。

    继电器模块:

           继电器电源连接VCC,GND接地,DIO连接单片机P2.1端口,继电器的模块的开闭表示单车的开闭锁。在继电器下接入一个LED的小灯,用它的亮灭来表示继电器是否上电,是否已经开锁。

           LED:

    连接通过继电器构成回路,长脚(正极)接电源,短脚(负极)接继电器常闭端,继电器公共触点引到地,构成回路,点亮小灯(在继电器DIO高电平时)。


    数码管:

           给P1口送编码即可,0-F的编码分别为0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71。

    其中P2^6为段选通,P2^7为位选通。

    用于计时模块和指示通过蓝牙传入的密码数据。

    按键:

           根据不同按键连接的端口触发不同的中断,编写对应的中断函数。在本系统中,外部中断0通过独立键盘模块按键S4实现,低电平触发,在计费状态下,停止计费,并向手机发送计费结果。

           外部中断1通过独立键盘模块按键S5实现,下降沿触发,当在非计费状态下,清空数码管显示为全0。

          

    流水灯:

    流水灯连接到单片机的P1端口,直接对P1口赋值即可,高电平为灭,低电平亮。用于指示接收数据的ASCII码和错误输入提示,全亮。


    51单片机代码:

    #include "reg51.h"
    #include <intrins.h>
    sbit lock = P2 ^ 1;
    sbit dula = P2 ^ 6;
    sbit wela = P2 ^ 7;
    
    unsigned char digit_led_pointer = 0;
    unsigned char count = 0;
    unsigned char opened = 0;
    
    unsigned char code table[] = { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71 };	// 数码管0-f表
    
    unsigned char led[] = { 0, 1, 2, 3, 4, 0, 0, 0 };	//存放8个数码管显示的数字
    
    
    void delay(unsigned int i)		//延迟函数
    {
    	while (--i);
    }
    
    void clear_digit(void)			//清空数码管,全变成0
    {
    	unsigned char i = 0;
    	for (; i < 8; ++i)
    		led[i] = 0;
    	digit_led_pointer = 0;
    }
    
    
    void send(unsigned char dat)	//通过串口发送到蓝牙模块上,蓝牙模块发送出去一个字节的字符
    {
    	ES = 0;
    	SBUF = dat;
    	while (!TI);
    	TI = 0;
    	ES = 1;
    }
    
    void send_str(unsigned char * str)	//通过蓝牙模块发送一个字符串
    {
    	while (*str != '\0')
    		send(*str++);
    }
    
    
    void display(unsigned char dig)		//输入密码阶段的显示,在已经输入的密码后续进行输入
    {
    	led[digit_led_pointer++] = dig;
    	if (digit_led_pointer == 8)
    	{
    		//判断如果输入密码为12345678的话,返回解锁成功
    		if (led[7] == 8 && led[6] == 7 && led[5] == 6 && led[4] == 5 && led[3] == 4 && led[2] == 3 && led[1] == 2 && led[0] == 1 && (opened == 0))
    		{
    			//开锁状态置位
    			opened = 1;
    			lock = 1;	//开锁继电器,高电平,点亮LED
    			clear_digit();
    			send_str("price: 1Yuan/min\n");
    			send_str("lock successfully!\n");
    		}
    		else
    		{
    			delay(10000000);	//输入8位密码后,延迟显示错误密码
    			clear_digit();
    			//解锁失败
    			send_str("lock fail!\n");	//向手机发送提示信息
    		}
    		digit_led_pointer = 0;
    	}
    }
    
    
    //计时模块,每次进入该函数,为10毫秒
    void time_add_10ms()
    {
    	led[7]++;
    	//100进位,每次10毫秒
    	if (led[7] == 10)
    	{
    		led[7] = 0; led[6]++;
    	}
    
    	if (led[6] == 10)
    	{
    		led[6] = 0; led[5]++;
    	}
    
    	//60进位,为秒数
    	if (led[5] == 10)
    	{
    		led[5] = 0; led[4]++;
    	}
    
    	if (led[4] == 6)
    	{
    		led[4] = 0; led[3]++;
    	}
    	//分钟数
    	if (led[3] == 10)
    	{
    		led[3] = 0; led[2]++;
    	}
    
    	if (led[2] == 10)
    	{
    		led[2] = 0; led[1]++;
    	}
    	//小时数,如果100个小时清零
    	if (led[1] == 10)
    	{
    		led[1] = 0; led[0]++;
    	}
    
    	if (led[0] == 10)
    		clear_digit();
    }
    
    //定时器0,为1号中断
    void timer0_ISR(void) interrupt 1
    {
    	if (opened == 1)
    	{
    		//晶振为11.0592MHz,每个机器周期需要12个时钟周期,计数5000次,所以每次进入中断的时间为
    		//	5000*12/11.0592M=0.00543s,每次进入add_10ms函数需要计数2次,所以每次count==2的时候,数码管显示+1
    		TL0 = (8192 - 5000) % 32;
    		TH0 = (8192 - 5000) / 32;
    		count++;
    		if (count == 2)
    		{
    			//达到10ms了
    			time_add_10ms();
    			count = 0;
    		}
    	}
    }
    
    
    
    void uart() interrupt 4
    {
    	unsigned char ky;
    
    	if (RI)
    	{
    		RI = 0;		//需要软件清除标志位
    		ky = SBUF;	//接收到的数据保存到
    		if (opened == 1)
    		{
    			send_str("can't stop, please press the button S4!\n");	//计费状态不接受输入,并返回提示信息。
    			return;
    		}
    		ES = 0;
    		P1 = ky;	//data send to Port 1,通过流水灯显示接收到的数据的ASCII码
    
    		//根据收到的数据进行异常处理或数码管输入
    		if (ky >= '0'&&ky <= '9')
    		{
    			display(ky - '0');
    		}
    		else if (ky >= 'a' && ky < 'f')
    		{
    			display((unsigned char)((ky - 'a') + 10));
    		}
    		else
    		{
    			//错误数据,流水灯全亮。
    			P1 = 0x00;
    		}
    		ES = 1;
    	}
    }
    
    void init_uart()
    {
    	TMOD = 0x25;            //定时器1工作方式2,计数器0工作方式1
    	SCON = 0x50;            //串口工作方式1
    	EA = 1;             //开总中断
    	ES = 1;             //开串口中断
    	TH1 = 0xfd;            //串口波特率9600
    	TL1 = 0xfd;
    	TR1 = 1;             //定时器1工作	
    }
    
    void timer0_init(void)
    {
    	TMOD &= 0xF0;	//计数器0方式0
    	TL0 = (8192 - 5000) % 32;	//计数5000次
    	TH0 = (8192 - 5000) / 32;
    	count = 0;
    	ET0 = 1;		//开启计时器和中断
    	TR0 = 1;		
    }
    
    void init_EX(void)
    {
    	EX0 = 1;
    	IT0 = 0;
    	EX1 = 1;		//开启外部中断 0
    	IT1 = 1;          //设置成低电平触发,1为下降沿触发
    }
    
    //把计时费用转换成字符串发送给手机端
    void num2str(int cost)
    {
    	while (1)
    	{
    		if (cost / 10 != 0)
    			send(cost / 10 + '0');
    		else
    		{
    			send(cost + '0');
    			break;
    		}
    		cost %= 10;
    	}
    }
    
    //外部中断0,S4按下停止计费
    void Ex0_IRQ(void) interrupt 0
    {
    	//不在计费状态下没反应
    	if (opened == 1)
    	{
    
    		int time;
    		opened = 0;
    		send_str("duration:");
    		send(led[0] + '0'); send(led[1] + '0'); send(':');
    		send(led[2] + '0'); send(led[3] + '0'); send(':');
    		send(led[4] + '0'); send(led[5] + '0');
    		send('\n');
    		time = ((led[0] + led[1]) * 60 + (led[2] * 10 + led[3]));
    		send_str("cost: RMB "); num2str(time + 1); send('\n');
    		lock = 0;
    		clear_digit();
    	}
    }
    
    //外部中断1,2号中断,S5按下后清空数码管
    void Ex1_IRQ(void) interrupt 2
    {
    	//不在计费状态下才有反应
    	if (opened == 0)
    	{
    		digit_led_pointer = 0;
    		clear_digit();
    	}
    }
    
    void main()
    {
    	unsigned char num = 0;
    	//初始化
    	init_uart();
    	timer0_init();
    	clear_digit();
    	init_EX();
    	lock = 0;
    	while (1)
    	{
    		//显示数码管
    		for (num = 0; num < 8; ++num)
    		{
    			wela = 1;
    			P0 = _crol_(0xfe, num);	//选中数码管,循环左移
    			wela = 0;
    			dula = 1;
    			P0 = table[led[num]];
    			delay(100);
    			dula = 0;
    		}
    	}
    }


    展开全文
  • 51单片机蓝牙模块连接 2018-02-22 12:17:38
    不久前开始学习使用蓝牙模块,在模块与51单片机连接的过程中出现了非常多的问题,我想应该也是很多新手和我一样会遇到这样的问题,因此特地写这篇文章,想分享下在学习过程中遇到的问题以及解决方法。此次学习用到...
  • 使用无底板的HC-05蓝牙模块,包括连线,通过SSCOM32进行配置,编写安卓端的程序实现和蓝牙模块的通信,数据传输
  • 要想使用HC-05蓝牙模块进行单片机之间通讯或者单片机蓝牙设备之间通讯,首先要配置好HC-05蓝牙模块的参数。设置好蓝牙的名称、密码、波特率等待。 step1: 连接usb转ttl模块和蓝牙模块,把两个模块的VCC口相连...
  • 51单片机蓝牙模块的串口51单片机蓝牙模块的串口通信C程序通信C程序
  • 手机通过蓝牙控制51单片机蓝牙点亮led,内有手机端的apk
  • 基于蓝牙51 单片机智能控制开关设计pdf,随着互联网技术的快速发展和通信技术的突飞猛进,物联网技术的发展得到了保障,同时物联网技术也逐 渐被人们接受,应用领域越来越广,基于此背景下,智能家居应运而生。...
  • 51单片机蓝牙小车(精要版) 实现:通过手机与小车的蓝牙通信,实现手机控制小车前后左右的移动。 这是博主学了51单片机第一次做的单片机项目,选择了许多人喜欢的蓝牙小车作为第一个项目。 准备材料: 1.小车亚克力...
  • 利用51单片机 手机APP连接蓝牙 发送指令 控制继电器开关 数量自己决定 控制的外设看自己创新(此贴为更新贴 原帖积分不够没资格删除)
  • 实现Android手机通过蓝牙控制51单片机小车 #一、材料: 1.stc51单片机最小系统板(最好带上拉电阻); 2.HC-02蓝牙芯片; 3.蓝牙小车,带驱动; 4.充电宝; 5.Android手机及app; #二、硬件连接 1.把小车...
  • 基于51单片机蓝牙程序 2020-05-31 23:31:03
    这是基于51 单片机蓝牙程序 本人亲自编写 亲测可用 波特率9600 希望对你们有所帮助
  • 基于51单片机蓝牙控制 2020-07-05 23:30:12
    基于51单片机蓝牙控制板,AD工程压缩。含PCB图。板载俩个继电器,可直接控制
  • 51单片机蓝牙通信程序 2020-06-17 17:35:08
    该程序实现了51单片机蓝牙通信程序,并在适当地方做了注释
  • 基于51单片机蓝牙遥控小车基于51单片机蓝牙遥控小车基于51单片机蓝牙遥控小车
  • 基于51单片机的HC-08蓝牙程序,初学51可以试做一下蓝牙遥控小车。
  • 51单片机蓝牙模块 2019-06-22 17:03:53
    51单片机的蓝牙模块,是在蓝牙通讯的基础上,进行蓝牙51模块与外部蓝牙发射接收设备之间,相互收发数据。并且其引脚为VCC,GND,TXD,RXD,可以通过串口通信与外部上位机或单片机通信。 代码如下(注意蓝牙模块是5V...
  • 上一次介绍了基于51单片机蓝牙遥控小车,使用的是手机APP作为遥控器,本节中介绍使用51单片机制作遥控器。 1.单片机 同样使用51单片机作为控制芯片,同样只需要一个芯片和一个晶振电路单片机就能运行,但是注意...
  • 基于51单片机蓝牙小车 2020-06-16 23:30:21
    基于51单片机蓝牙小车软件 包含上位机apk和单片机代码。。
  • STC51单片机一般是通过串口线下载程序到MCU。但是,有时候单片机放在作品上,串口线不够长,不方便下载,或者频繁拔插单片机,也不方便。 本方法,通过笔记本蓝牙蓝牙串口模块HC-05,即可实现STC51单片机无线下载...
  • 该App功能为通过蓝牙接收单片机采集的温度传感器数据,同时可以通过蓝牙发送预设温度数据给单片机 蓝牙通信代码仿照参考代码进行编写,不再提供github代码 关键代码 主要是接收和发送数据,在参考的代码里面...
1 2 3 4 5 ... 20
收藏数 1,357
精华内容 542