一、实践的目的
通过编写51单片机通讯聊天程序,掌握51单片机的各个模块的知识点和运用C语言编写51单片机的能力。
二、实践内容
用51单片机与口袋开发板设计实现一个单片机与电脑串口助手实现通讯功能的程序。程序的主要功能如下:
1 OLED初始化显示Welcome to Bluetooth communication! 字符串。
2 程序开始时处于接收信息模式, 电脑串口助手发送信息时,将从初始化字符第一个开始显示,电脑串口助手发送信息后,蜂鸣器响铃2秒左右。
3 每次同时按下左右键时,可以轮流切换接收/发送信息模式
4 在发送信息模式时,可以显示光标(第一次处于发送信息模式时光标显示在OLED的左上角),可以通过左右键、上下键控制光标移动
5 在发送信息模式下, 每次同时按下上下键, 可以将光标选中的字符发送到电脑串口助手,发送完字符后, led流水灯流动两次。
三、实践依托的实验设备与软件
- 口袋实验室
- Aultium Designer
- 使用的开发软件 : keil4、stc-isp-15xx-v6.28烧录软件
- PC电脑
四、硬件原理图
二、相关元器件特性分析
原器件名称 | 元器件特性简介 |
单片机 Stc89c52 | 系统运行的的核心 |
手柄板 | 系统运行的基础 |
OLED | 可以显示字符或字符串 |
蜂鸣器 | 接收信息时,可以响铃 |
LED灯 D1-D8 | 发送信息后,流水灯流动两次后熄灭 |
独立按键 | 切换接收/发送模式,发送信息时控制光标移动 |
蓝牙模块 | 与手机实现通讯,显示单片机发送的字符或字符串 |
五、主要算法流程图及描述
六、问题的分析与编写程序步骤与实现的过程
1、通过蓝牙模块与手机APP“SPP蓝牙串口”实现连接
将HC蓝牙模块通过杜邦线与开发板进行接线的连接。接线的方式是:将蓝牙模块RXD、TXD、GND、VCC分别与单片机的TX(单片机的串口发送脚)、RX(单片机串口接收脚)、GND、+5V相连接。接好线后如下图所示
打开手机蓝牙串口APP选择蓝牙HC-5,连接成功后如下图所示
蓝牙模块的指示灯没有快闪,说明连接成功了。
2、创建工程与编写OLED显示字符串的程序
通过软件Keil uVision4创建51单片机实现通讯工程后,新建两个文件,分别命名为Oled.h头文件与Oled.c源文件。
Oled.h头文件将变量的定义户函数的声明包含进来。因为OLED已经有示例程序提供给我们了,所以由我们系统要实现的功能,将相关的函数声明从示例程序赋值过来。如下图所示
OLED_Init()、OLED_Fill()、OLED_CLS()、OLED_WrCmd(byte)、OLED_WrDat(byte)是OLED工作的重要函数。这些函数是OLED液晶显示屏显示文字或图像等的基础。我们系统要显示的是文字,所以用void OLED_P8x16Str(byte, byte, byte[])函数将要显示的数据写入OLED中就可以显示我们想要显示的数据了。void OLED_Set_Pos(byte, byte )函数是用来设置数据显示在OLED屏幕的何处。它可以将我们要显示的数据放在指定的位置显示。
Oled.c源文件是将Oled.h头文件的声明的函数实现实现具体的功能。
现在新建两个文件保存为Main.c的源文件盒Main.h的头文件。在Main.h头文件中编写如下的代码
#ifndef _Main_H_ #define _Main_H_ #include <reg52.h> #define UINT unsigned int #define UCHAR unsigned char UINT i, index = 0; UCHAR dataChar; UCHAR dataString[64] = {"Welcome to Bluetooth communication!"}; // 单片机接收信息时, 用数组存放接收的信息 #endif
Main.c源文件中编写如下代码
#include "Main.h" #include "Oled.h" void main() { OLED_Init(); // OLED初始化 OLED_Fill(0x00); // OLED全屏 while(1) { OLED_P8x16Str(0, 0, dataString); // 显示单片机接收的字符或字符串 } }
编译程序,将生成的.hex文件用STC烧写软件-ISP-V6.82E软件将烧入到单片机中,单片机运行的效果如下图所示
现在已经成功实现OLED显示字符串了。
3、通过串口通断实现发送信息于OLED屏幕显示
上一步我们实现了OLED显示字符串的功能。现在我们将用串口中断实现电脑串口助手发送字符或字符串信息后,OLED屏幕显示发送的字符或字符串,同时蜂鸣器响铃1秒左右。
首先进行编写的是串口中断处理的初始化程序。在Main.h中声明void timer_portInit(); 函数。然后在Main.c中编写void timer_portInit()函数,如下所示
void timer_portInit() { SM0 = 0; //设置串口为工作方式1 SM1 = 1; TMOD=0X20; //设置计数器工作方式2 PCON=0X80; //波特率加倍 TH1=0XFa; //计数器初始值设置,注意波特率是9600的 TL1=0XFa; EA=1; // 打开总中断 ES=1; // 打开串口中断 REN = 1; // 允许串口接收数据 TR1=1; // 打开定时器T1 }
串口中断初始化程序已经编写完成了,现在我们编写串口中断处理的函数
void serialPort() interrupt 4 { dataChar = SBUF; // 读入串口接收到的数据 RI = 0; // 中断标志位置零 dataString[index] = dataChar; // 单片机接收的数据存放与数组中 index++; } }
中断处理程序编写完成,现在我们进行蜂鸣器在单片机接收信息后响铃2秒左右。在Main.h中定义sbit beep = P1^5; // 蜂鸣器,定义UINT beepTime = 300; UINT flagReceive = 0; 两个变量,分别对蜂鸣器响铃的时间进行控制、串口中断接收信息的标志控制蜂鸣器响铃,当flagReceive为1时就让蜂鸣器响铃。现在要改变串口中断处理程序的代码,将
dataString[index] = dataChar; // 单片机接收的数据存放与数组中
index++;
改成如下代码
if(funcSelect == 0) // 单片机接收的数据存放与数组中 { dataString[index] = dataChar; index++; flagReceive = 1; }