一、串口通信
1.1前言
STC89C51RC/RD+系列单片机内部集成有一个功能很强的双全工串行通信口
设有两个相互独立的接收、发送缓冲器,可以同时发送和接收数据,发送缓冲器只能写入而不能读出,接收缓冲器只能读出而不能写入,因而两个缓冲器可以使用一个地址吗(99H)。两个缓冲器统称为串行通信特殊功能寄存器SBUF。
1.2 单片机中数据打印到PC端
1.2.1 单片机中单个字符打印到PC端
#include "reg52.h"
#include "intrins.h"
sfr AUXR = 0x8e;//声明AUXR寄存器的地址
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
UartInit(void)
{
AUXR = 0x01;//提升EMI信号
SCON = 0X40;//1、配置串口工作方式,REN不使能接收
TMOD &= 0X0F;
TMOD |= 0X20;//2、配置定时器1 工作方式:8位自动重载
TH1 = 0XFD;//3、计算9600波特率的初值
TL1 = 0XFD;
TR1 = 1;//4、启动定时器
}
void main()
{
char data_msg = 'a';//在51中data为关键字,所以这里不能单纯使用data
//每隔一秒发送一个字符给PC,因为我这里100ms类似于现实的1秒,1000ms类似10秒,故使用100ms
//配置C51串口的通信方式
UartInit();
while(1)
{
Delay1000ms();
//往发送缓冲区写入数据,就完成了数据的发送
SBUF = data_msg;
}
}
1.2.2 单片机中字符串打印到PC端
#include "reg52.h"
#include "intrins.h"
sfr AUXR = 0x8e;//声明AUXR寄存器的地址
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
UartInit(void)
{
AUXR = 0x01;//提升EMI信号
SCON = 0X40;//1、配置串口工作方式,REN不使能接收
TMOD &= 0X0F;
TMOD |= 0X20;//2、配置定时器1 工作方式:8位自动重载
TH1 = 0XFD;//3、计算9600波特率的初值
TL1 = 0XFD;
TR1 = 1;//4、启动定时器
}
void sendByte(char data_msg)
{
SBUF = data_msg;
//需要延时一下,让它好好的传字符
while(!TI);//TI是中断请求标志位
//在停止位开始发送时由内部硬件置位,必须由软件复位(发送到最后一位的时候,就会自动的TI=1)
TI = 0;//手动复位
}
void sendString(char* str)
{
while(*str != '\0')//字符串最后一位是\0
{
sendByte(*str);//一个字符一个字符的往里传
str++;
}
}
void main()
{
//配置C51串口的通信方式
UartInit();
while(1)
{
Delay1000ms();
//往发送缓冲区写入数据,就完成了数据的发送
sendString("lijinshuang\r\n");//\r\n是让字符换行操作
}
}
1.3 pc端数据传到单片机中
1.3.1 PC端的单个字符传到单片机中引起led灯的变化
#include "reg52.h"
#include "intrins.h"
sfr AUXR = 0X8e;//声明寄存器地址
sbit D5 = P3^7;
char cmd;
void Delay100ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
UartInit(void)
{
AUXR = 0x01;//提升EMI信号
SCON = 0X50;//1、配置串口工作方式,REN能接收
TMOD &= 0X0F;
TMOD |= 0X20;//2、配置定时器1 工作方式:8位自动重载
TH1 = 0XFD;//3、计算9600波特率的初值
TL1 = 0XFD;
TR1 = 1;//4、启动定时器
EA = 1;//开启总中断
ES = 1;//开启串口中断
}
void sendByte(char data_msg){
SBUF = data_msg;
while(!TI);//初值TI=0,置位后TI=1,此时请求中断
TI =0;//手动置位
}
void sendString(char* str){
while(*str != '\0')
{
sendByte(*str);
str++;
}
}
void main()
{
D5 = 1;
//配置C51串口的通信方式
UartInit();
while(1){
Delay100ms();
sendString("lijinshuang\r\n");
}
}
void Uart_Handler() interrupt 4
{
if(RI)//RI的中断处理函数,单片机接收数据中断的处理
{
RI = 0;//手动置0,清除接收中断标志位
cmd = SBUF;//由PC传数据到单片机中是给SBUF赋值
//由单片机给PC端传数据是将SBUF的值赋给别人
if(cmd == 'o'){
D5 = 0;//低电平点亮D5
}
if(cmd == 'c'){
D5 = 1;//高电平熄灭D5
}
}
if(TI);
}
1.3.2 PC端的字符串传到单片机中引起led灯的变化
#include "reg52.h"
#include "intrins.h"
#include "string.h"
#define SIZE 12//宏定义指令
sfr AUXR = 0X8E;
sbit D5 = P3^7;
char cmd[SIZE];//数组
UartInit(void){
AUXR = 0X8E;
SCON = 0X50;
EA = 1;
ES = 1;
TMOD &= 0X0F;
TMOD |= 0X20;
TH1 = 0XFD;
TL1 = 0XFD;
TR1 = 1;
}
void Delay100ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg){
SBUF = data_msg;
while(!TI);
TI = 0;
}
void sendString(char* str){
while(*str != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
D5 = 1;
UartInit();
while(1){
Delay100ms();
sendString("lijinshuang\r\n");
}
}
void Uart_Handler() interrupt 4 //中断处理函数
{
static int i=0;//静态变量,被初始化一次,不会因为每次执行函数的时候而改变值
if(RI){//由RI中断时处理如下
RI=0;//手动置位
cmd[i] = SBUF;//cmd数组分别被赋予SBUF中的值
i++;//数组向下遍历
if(i == SIZE){//达到12位,重新开始
i=0;
}
if(strstr(cmd,"open")){//用于查找子串在母串中的位置
D5 = 0;
i = 0;
memset(cmd,'\0',SIZE);//清空。重新来
}
if(strstr(cmd,"close")){
D5 = 1;
i = 0;
memset(cmd,'\0',SIZE);//将cmd指向的内存区域的前SIZE个字节全部设置为字符'\0'。
}
}
}
二、蓝牙
2.1 简介
蓝牙模块,又叫蓝牙串口模块
串口透穿技术
透传即透明传送,是指在数据的传输过程中,通过无线的方式这组数据不发生任何形式的改变,仿佛传输过程是透明的一样,同时保证传输的质量,原封不动地到了最终接收者手里。
我们只需要明白,如何通过串口编程获得数据即可。
2.2 接线方式
2.3 使用方式
运行一个使用了双全工通信的代码。
将上官一号和蓝牙模块连接起来,插在电脑上,烧写
手机下载HC蓝牙助手(扫下面的码下载)
在手机上点击连接蓝牙
打开串口
连接成功后可以在手机端输入数据在电脑端的串口助手上,单片机上显示出来,依旧可以执行指令,操作上官一号单片机