2019-12-28 11:27:55 WideMouth
我的第二篇博客,其实我是一个纯物理专业的本科生,学习的是物理主流的力热电光原,阴差阳错的玩起了电子和编程(当然,也是兴趣所驱),考虑过转专业,但是迫于学校各种各样的因素,还是免了吧,就这样写写属于自己的博客,觉得挺好的。大学里默默做自己喜欢的事,还是不失自己的真心的。
一开始做蓝牙通信是在上一学期(大一下学期),那时对电子特别感兴趣,刚上手了51单片机,想玩点高级点的,想到了蓝牙和语音,然后去问电信专业的一个学长(现在是我的好哥们啦),貌似电信专业的都没玩过这个,很惊讶,那就只能自己玩啦,问了一个挺牛的大三学姐,她也没做过,然后给我讲了一些特别复杂懵逼的原理,不过给了我几篇博客,那我就带着这几篇博客自主搞啦,那时学姐那刚好有一块HC-06模块,说是捡的,还不知道能不能用,那就随便玩玩啦。嘻嘻!!!还是能玩的,虽然出了各种各样的状况,不过还是基本实现了蓝牙通信啦,那是还只能单字符(其实那时也用不到字符串),后来就自己买模块玩,HC-08、HC-12、LD3320语音模块。都上手成功啦。不过后来由于焊工不太好,烧了一块语音芯片(好几十块,心疼),加上玩电子实战要焊板子,一来二去不如编程来得方便,就改手编程了。一台笔记本电脑即可,无任何成本,实战快,不过电脑是初中买的Lenovo G40-70m(2900块),自己加了块内存条和固态,嘻嘻!!!就喜欢搞这些。由于自己对电脑比较熟悉,感觉自己电脑比同学花好几千新买的高配置电脑还好用。自豪!!!
好啦,下面开始分享啦!!!
先上完整代码:
1 2 /*----------------------------------------------------------------------------- 3 * 实 验 名 : WideMouth 51单片机字符串收发 4 * 实验说明 : 单片机串口收发数据控制灯亮灭 5 * 实验模块 : STC89C52RC单片机最小系统、HC-06蓝牙模块 6 * 连接方式 :蓝牙模块RXD、TXD端分别连接单片机TXD、RXD端,蓝牙正负极连接单片机正负极 7 * 注 意 : 单片机晶振使用的是11.0592 8 *******************************************************************************/ 9 10 #include<reg52.h> 11 #include<string.h> //字符串处理函数包 12 #include<intrins.h> 13 14 #define uchar unsigned char // 宏定义 51单片机内存资源有限 15 #define uint unsigned int //需考虑内存资源问题,故使用无符号类型 16 17 18 uchar receive_data[8]; 19 uint bytes=0; 20 uint bytes_old; 21 22 //--定义使用的IO--// 23 24 sbit Led301=P2^0; 25 sbit Led302=P2^3; 26 27 //--声明全局函数--// 28 void uart_init(); 29 void Delay_1ms(uint i); 30 void SendChar(uchar character); 31 void SendString(uchar *p); 32 33 /******************************************************************** 34 * 名称 : Com_Int() 35 * 功能 : 串口中断函数(接受和发送数据时都会调回此函数) 36 ***********************************************************************/ 37 void Com_Int(void) interrupt 4 38 { 39 EA = 0; 40 if(RI==1) //此句判断不能省略,否则发送数据时也会执行此语句,造成字符串错误!!!(RI为接收数据标志,当接收到数据自动置为1) 41 { 42 RI=0; 43 receive_data[bytes] = SBUF;//接收到的数据 44 bytes++; 45 } 46 EA = 1; 47 } 48 49 /******************************************************************************* 50 * 函 数 名 : main 51 * 函数功能 : 主函数(程序入口) 52 *******************************************************************************/ 53 54 void main() 55 { 56 bytes_old=0; 57 uart_init();//初始化串口 58 while(1) 59 { 60 while(1) 61 { 62 bytes_old=bytes; 63 64 Delay_1ms(30); //如果单片机接收来自蓝牙模块不少于1字节的串口数据,一定要加延时后再判断是否,延时时间自己可按情况而定 65 //接收数据中断一定发生在这30ms内 66 if(bytes_old==bytes) //如果在这30ms内无数据接收,说明字符串已接收完毕,这样才能完整的接收一帧串口数据 67 { 68 receive_data[bytes]=0; //字符串末尾加结尾标志0(对应/0) 69 if(bytes) break; //跳出循环,执行相应逻辑操作 70 } 71 } 72 73 SendString(receive_data); //将接收到的完整数据返回给发送端 74 75 //想干啥干啥吧 76 if(strcmp(receive_data,"3011")==0) //strcmp(str1,str2)字符串比较函数. 参数 str1 和 str2 是参与比较的两个字符串。 77 { //若str1=str2,则返回零; 78 Led301=0; //若str1<str2,则返回负数; 79 } //若str1>str2,则返回正数。 80 if(strcmp(receive_data,"3010")==0) 81 { 82 Led301=1; 83 } 84 if(strcmp(receive_data,"3021")==0) 85 { 86 Led302=0; 87 } 88 if(strcmp(receive_data,"3020")==0) 89 { 90 Led302=1; 91 } 92 bytes_old=0; //将bytes_old、bytes置为初始化值,等待接收下一字符串 93 bytes=0; 94 } 95 96 97 } 98 99 /******************************************************************************* 100 * 函 数 名 : uart_init() 101 * 函数功能 : 初始化配置串口 102 * 备注 :可直接复制 103 *******************************************************************************/ 104 105 void uart_init() //直接复制即可 106 { 107 SCON=0X50; //设置为工作方式1,8位数据,可变波特率 108 TMOD=0X20; //设置计数器工作方式2 109 PCON=0X00; //波特率不加倍 110 TH1=0XFd; //计数器初始值设置,9600@11.0592MHz 111 TL1=0XFd; 112 TR1=1; //打开计数器 113 ES = 1; //开串口中断 114 EA = 1; //开总中断 115 } 116 117 /******************************************************************** 118 * 名称 : Delay_1ms() 119 * 功能 : 延时子程序,延时时间为 1ms 120 * x * 输入 : x (单位为毫秒) 121 ***********************************************************************/ 122 void Delay_1ms(uint i) //1ms延时,直接复制即可 123 { 124 uint x,j; 125 for(j=0;j<i;j++) 126 for(x=0;x<=148;x++); 127 } 128 129 /******************************************************************** 130 * 名称 : SendChar(uchar character) 131 * 输入 :单个字符 132 * 功能 : 发送单个字符 133 ***********************************************************************/ 134 135 void SendChar(uchar character) 136 { 137 SBUF=character; //发送单个字符 138 while(!TI);TI=0; //发送完成标志 139 } 140 141 /******************************************************************** 142 * 名称 : SendString(uchar String[]) 143 * 功能 : 发送字符串 144 * 输入 :字符串 145 ***********************************************************************/ 146 147 void SendString(uchar String[]) 148 { 149 uchar *p=String; 150 while(*p) //若指针指向的地址为空,则跳出循环 151 { 152 SendChar(*p); //指针第一次默认指向首地址 153 Delay_1ms(2); //延时,作用为提高发送准确度 154 p++; 155 } 156 }
用的工具都是最简单的,编译软件是Keil C51,单片机是STC89C52RC,一块HC06蓝牙模块,很容易上手。程序中,uart_init()和Delay_1ms(uint i) 对于51单片机蓝牙通信都是通用的,复制即可,然后最后两个发送数据函数,第一个发送字符比较简单,第二个需要一点C语言基础,但逻辑很简单。程序最核心的是中断函数Com_Int(void)和主函数main(),中断函数比较简单,就是把接收的字符赋值给字符串,但是要注意的是必须要加上if(RI==1)判断,否则发送数据时也会执行赋值语句,造成字符串错误(RI为接收数据标志,当接收到数据自动置为1)!!!之前就是省了这一句,导致字符串老是重复,大家好奇的可以试一试,便于理解。然后最核心的是main函数中关于接收字符串的整理逻辑,从而得到一个完整的字符串数据,处理的巧妙之在于加了一行延时语句Delay_1ms(30); 函数里的时间可按情况设定,大家在这里需要花点时间好好理解一下里面的循环语句,弄明白他的处理机制,代码中有详细的备注便于你去理解。
现在单片机程序部分就完结了哦,现在需要你动手去实战啦!!!这时还需要最后一步,来生成单片机烧录的Hex文件。点击工具栏的“魔法棒”,在Target栏修改晶振频率为11.0592,Output栏勾选Creat Hex File,然后在主界面点击ReBuild编译生成Hex文件。在Build窗口出现creating hex file from " "...说明生成Hex文件成功啦!
附图:
现在轮到你去烧录啦,这里就不展示啦,需要你自己动手完成。加油,好运哦!!!
大功告成!!! @WideMouth
原文:https://www.cnblogs.com/WideMouth/p/12111275.html