STC单片机通过蓝牙模块与手机通信

[复制链接]
2999|5
 楼主| 涛声依旧520 发表于 2018-9-30 22:38 | 显示全部楼层 |阅读模式
哈哈,机缘巧合之下又做跟硬件相关的工作了,突然发现了二姨这里还有账号,所以来凑凑热闹发个贴纸,也跟坛里的新手一起切磋下。高手勿喷!


这次分享的内容如标题所示:通过APP蓝牙和单片机通讯。先给大家看下效果图




因为是截取的动图,可能效果不太好,我这里再贴一个高清图,




功能描述:
  • 单片机通过蓝牙模块上传温度数据到手机,手机进行界面显示。
  • 手机APP下发开灯或关灯的指令,单片机接收到指令后,控制LED的亮灭。

模块参数
  • 单片机:STC89c52RC,老早买的还没用完的。
  • 蓝牙模块:HC-05
  • 温度传感器:DS18b20
  • 显示:0.96英寸OLED
  • APP:自己编写的APP应用,或者可以使用串口调试工具。


  1. /****************************************
  2. **       蓝牙串口接收数据
  3. **
  4. **   作者:江涛
  5. **   时间:2018/08/31
  6. **   描述:串口发送数据兼用OLED显示
  7. ****************************************/
  8. #include "STC89C5xRC_RDP.h"
  9. #include "string.h"     // 要使用字符串对比函数,需要引入该头文件
  10. #include "OLED.h"       // OLED显示屏头文件
  11. #include "DS18b20.h"


  12. // 定义系统时钟和串口波特率
  13. #define FOSC 11059200L      // 系统时钟
  14. #define BAUD 9600           // 串口波特率

  15. /******变量声明*********/
  16. char RECEIVED_CMD[10] ;               // 暂定为10字节的指令
  17. char RECEIVED_INDEX ;                 // 数组指示索引,当接收到一个数据之后,索引会跟随增加
  18. unsigned char flag = 0 ;              // 数据接收的标志位
  19. unsigned char power_flag = 0 ;  // 电源开关的标志位

  20. /******命令常量*******/
  21. code const char* LED_ON = "ON\r\n" ;                                        // 电源开指令
  22. code const char* LED_OFF = "OFF\r\n" ;                                // 电源关指令
  23. code const char* LED_01_ON = "L1ON\r\n" ;                        // 灯组01开指令
  24. code const char* LED_01_OFF = "L1OFF\r\n" ;                // 灯组01关指令
  25. code const char* LED_02_ON = "L2ON\r\n" ;                        // 灯组02开指令
  26. code const char* LED_02_OFF = "L2OFF\r\n" ;                // 灯组02关指令
  27. code const char* FAN_ON = "FANON\r\n" ;                                // 风扇开指令,使用RGB灯循环来模拟风扇工作
  28. code const char* FAN_OFF = "FANOFF\r\n" ;                        // 风扇关指令
  29. code const char* FAILD = "power_off\r\n" ;                // 返回失败原因,电源关闭了

  30. extern unsigned int tvalue;                        //温度值
  31. extern unsigned char tflag;                        //温度正负标志
  32. unsigned char disdata[7];                         // 温度数据,使用8字节数组来存储

  33. char color_table[8][3] = { // 颜色表
  34.         {0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}
  35. };

  36. /*******函数声明*********/
  37. void Init_UART(); // 初始化串口
  38. void UART_SendData(char dat); // 串口发送数据
  39. void UART_SendStr(char* str); // 串口发送字符串
  40. void RGB_Display(int index);  // RGB灯显示

  41. //void split(char str[],char delims[]); // 字符串截取函数

  42. void ds1820disp();         // 温度显示

  43. void test_Fan(char flag);                // 模拟测试风扇运行
  44. void Delay1ms();                                                //@11.0592MHz

  45. /***********端口定义*************/
  46. sbit LED_R = P0^0 ;
  47. sbit LED_G = P0^1 ;
  48. sbit LED_B = P0^2 ;

  49. /*******程序入口*********/
  50. void main()
  51. {

  52.         unsigned int temperature , old ; // 保存温度数值
  53.        
  54.         Init_UART();  // 串口初始化
  55.        
  56.         LCD_Init();  // OLED 初始化
  57.         LCD_CLS();   // 清屏
  58.        
  59.         LCD_P8x16Str(0 , 0 , "TEMP:");  // 温度开始位置
  60.        
  61.         temperature = ReadTemperature();
  62.         old = temperature ;
  63.         ds1820disp(); // 显示温度
  64.         UART_SendStr(disdata); // 向串口发送数据
  65.         LCD_P8x16Str(5*8 , 0 , disdata); // 显示温度
  66.        
  67.         while(1)
  68.         {
  69.                
  70.                 temperature=ReadTemperature();  // 读取一次新的温度
  71.     if (temperature != old )          
  72.           {         
  73.                         old = temperature;
  74.                         ds1820disp(); // 显示温度
  75.                         UART_SendStr(disdata); // 向串口发送数据
  76.                         LCD_P8x16Str(5*8 , 0 , disdata); // 显示温度

  77.           }
  78.                
  79.                 if(flag) // 接收数据完毕一次,就会进入中断一次
  80.                 {
  81.                         flag = 0 ; // 将标志位还原,使得串口又可以重新接收数据
  82.                                        
  83.                         if(strcmp(RECEIVED_CMD , LED_ON) == 0)
  84.                         {
  85.                                 P2 = 0xFF ; // P2口全亮
  86.                                 power_flag = 1 ; // 标志电源打开
  87.                         }
  88.                         else if(strcmp(RECEIVED_CMD , LED_OFF) == 0)
  89.                         {
  90.                                 P2 = 0x00 ; // P2口全灭
  91.                                 power_flag = 0 ;// 标志电源关闭
  92.                         }
  93.                         else if(strcmp(RECEIVED_CMD , LED_01_ON) == 0)
  94.                         {
  95.                                 if(power_flag)                 // 如果电源开关是关闭的,就不执行以下操作
  96.                                         P2 = 0x55 ;                 // ‭01010101‬ 为1位置的灯是亮着的
  97.                                 else
  98.                                         UART_SendStr(FAILD); // 向串口发送失败原因
  99.                         }
  100.                         else if(strcmp(RECEIVED_CMD , LED_01_OFF) == 0)
  101.                         {
  102.                                 P2 = P2^0x55 ; // P2口01010101相应位置的灯要全灭,所以使用异或操作
  103.                         }
  104.                         else if(strcmp(RECEIVED_CMD , LED_02_ON) == 0)
  105.                         {
  106.                                 if(power_flag)                 // 如果电源开关是关闭的,就不执行以下操作
  107.                                         P2 = 0xAA ;                 // ‭10101010‬ 为1位置的灯是亮着的
  108.                                 else
  109.                                         UART_SendStr(FAILD); // 向串口发送失败原因
  110.                         }
  111.                         else if(strcmp(RECEIVED_CMD , LED_02_OFF) == 0)
  112.                         {
  113.                                 P2 = P2^0xAA ; // P2口10101010相应位置的灯要全灭,所以使用异或操作
  114.                         }
  115.                         else if(strcmp(RECEIVED_CMD , FAN_ON) == 0)
  116.                         {
  117.                                 test_Fan(1);
  118.                         }
  119.                         else if(strcmp(RECEIVED_CMD , FAN_OFF) == 0)
  120.                         {
  121.                                 test_Fan(0);
  122.                         }                       

  123.                        
  124.                         // 用完之后要记得数组清零处理
  125.       RECEIVED_INDEX = 0 ;        // 数组指引复位
  126.       memset(RECEIVED_CMD,0,10);  // 清0数组
  127.                 }
  128.         }
  129. }

  130. /******************
  131. ** 初始化串口
  132. *******************/
  133. void Init_UART()
  134. {
  135.                 SCON = 0x50;                     //设置8位数据位
  136.                 TMOD = 0x20;                     //8位自动重载
  137.                 TH1 = TL1 = -(FOSC/12/32/BAUD);  //设置重载值
  138.                 TR1 = 1;                         //使能时钟
  139.                 ES = 1;                          //使能串口中断
  140.                 EA = 1;                          //开中断开关
  141. }

  142. /********************
  143. ** 串口中断处理
  144. *********************/
  145. void UART_Isr() interrupt 4 using 1
  146. {
  147.         // 串口接收中断处理
  148.         if(RI)
  149.         {
  150.                 RI = 0 ;                              // 清除中断标志位
  151.                 RECEIVED_CMD[RECEIVED_INDEX] = SBUF ; // 保存串口接收的数据
  152.                 if(RECEIVED_CMD[RECEIVED_INDEX] == 0x0A ){ // 遇到了结束符号
  153.                          flag = 1 ;           // 接收结束,到循环中处理接收的数据
  154.                 }else {
  155.                          RECEIVED_INDEX ++ ;   // 继续接收数据
  156.                 }
  157.         }

  158.         // 串口发送中断处理
  159.         if(TI)
  160.         {
  161.                 TI = 0 ;  // 清发送中断标志位
  162.         }
  163.                
  164. }

  165. /**************************
  166. ** 通过串口发送一位数据
  167. ***************************/
  168. void UART_SendData(char dat)
  169. {
  170.         ES = 0 ;      // 串口工作的时候禁止中断
  171.         SBUF = dat ;  // 待发送的数据放到SBUF中
  172.         while(!TI) ;  // 等待发送完毕
  173.         TI = 0 ;      // 清TI中断
  174.         ES = 1 ;      // 打开中断
  175. }

  176. /*****************************
  177. **  通过串口发送字符串
  178. ******************************/
  179. void UART_SendStr(char *str)
  180. {
  181.                 do
  182.                 {
  183.                         UART_SendData(*str);
  184.                 }while(*str ++  != '\0' ); // 一直到字符串结束
  185. }

  186. /****************************
  187. **  显示RGB灯的颜色
  188. *****************************/
  189. void RGB_Display(int index)
  190. {
  191.         LED_R = color_table[index%8][0];
  192.         LED_G = color_table[index%8][1];
  193.         LED_B = color_table[index%8][2];
  194. }

  195. void Delay1ms()                //@11.0592MHz
  196. {
  197.         unsigned char i, j;

  198.         _nop_();
  199.         i = 2;
  200.         j = 199;
  201.         do
  202.         {
  203.                 while (--j);
  204.         } while (--i);
  205. }

  206. /****************
  207. ** 模拟风扇运行
  208. ****************/
  209. void test_Fan(char flag)
  210. {
  211.         unsigned int t , count = 500 ;

  212.         if(!flag) return ; // 如果传入的是0,表示停止,不往下继续进行
  213.        
  214.         for(t=0 ; t<8 ; t++)
  215.         {
  216.                 RGB_Display(t);                // 风扇
  217.                 for( ; count > 0 ; count --)
  218.                         Delay1ms();
  219.         }       
  220. }

  221. ///***********************************
  222. //** 字符串截取函数
  223. //***********************************/
  224. //void split(char str[],char delims[])
  225. //{
  226. //        char *result = NULL;
  227. //        result = strtok( str, delims );  
  228. //        while( result != NULL ) {  
  229. //                 result = strtok( NULL, delims );  
  230. //        }
  231. //}

  232. /***************************
  233. ** 温度值显示
  234. ***************************/
  235. void ds1820disp()
  236. {        
  237.           unsigned char flagdat;
  238.        
  239.                 if(tflag==0)
  240. //                        flagdat=0x20;//正温度不显示符号
  241.                   flagdat=0x2b;//正温度显示符号
  242.                 else
  243.                   flagdat=0x2d;//负温度显示负号:-
  244.                
  245. //                disdata[0] = flagdat; //符号位
  246.        
  247.                 disdata[1]=tvalue/1000+0x30;//百位数
  248.                 disdata[2]=tvalue%1000/100+0x30;//十位数
  249.                 disdata[3]=tvalue%100/10+0x30;//个位数
  250.                 disdata[4]= 0x2E ;//小数点
  251.                 disdata[5]=tvalue%10/1+0x30;//小数位

  252.                 if(disdata[1]==0x30) // 如果百位为0
  253.                 {
  254.                         disdata[0]= 0x20; // 第一位不显示
  255.                         disdata[1]= flagdat; // 百位显示符号
  256.                         if(disdata[2]==0x30) //如果百位为0,十位为0
  257.                         {
  258.                                 disdata[1]=0x20; // 百位不显示符号
  259.                                 disdata[2]=flagdat; // 10位显示符号
  260.                         }
  261.                 }
  262. }
上面是main.c的内容,主要是串口要熟练使用,其实用蓝牙传数据主要就是串口的功劳,来看下DS18b20的部分,这部分再网上又很多高手又开源的例子,我就不多赘述了。

  1. #include "DS18b20.h"

  2. unsigned int tvalue;//温度值
  3. unsigned char tflag;//温度正负标志

  4. void delay(unsigned int i)
  5. {
  6. while(i--);
  7. }

  8. void Init_DS18B20(void)
  9. {
  10.         unsigned char x=0;
  11.         DQ = 1;   
  12.         delay(8);  
  13.         DQ = 0;   
  14.         delay(80);
  15.         DQ = 1;   
  16.         delay(14);
  17.         x=DQ;      
  18.         delay(20);
  19. }

  20. unsigned char ReadOneChar(void)
  21. {
  22.         unsigned char i=0;
  23.         unsigned char dat = 0;
  24.         for (i=8;i>0;i--)
  25.         {
  26.                 DQ = 0;
  27.                 dat>>=1;
  28.                 DQ = 1;
  29.                 if(DQ)
  30.                  dat|=0x80;
  31.                 delay(4);
  32.         }
  33.         return(dat);
  34. }

  35. void WriteOneChar(unsigned char dat)
  36. {
  37. unsigned char i=0;
  38. for (i=8; i>0; i--)
  39. {
  40.   DQ = 0;
  41.   DQ = dat&0x01;
  42.   delay(5);
  43.   DQ = 1;
  44.   dat>>=1;
  45. }
  46. }

  47. int ReadTemperature(void)
  48. {
  49.         unsigned char a=0;
  50.         unsigned char b=0;

  51.         Init_DS18B20();
  52.         WriteOneChar(0xCC);
  53.         WriteOneChar(0x44);
  54.         Init_DS18B20();
  55.         WriteOneChar(0xCC);
  56.         WriteOneChar(0xBE);
  57.         a=ReadOneChar();
  58.         b=ReadOneChar();
  59.         tvalue = b;
  60.         tvalue <<= 8;
  61.         tvalue = tvalue|a;
  62.         if(tvalue<0x0fff)
  63.                 tflag=0;
  64.         else
  65.   {
  66.                 tvalue=~tvalue+1;
  67.                 tflag=1;
  68.   }
  69.         tvalue = tvalue*(0.625);//温度值扩大10倍,精确到1位小数
  70.         return(tvalue);
  71. }


我把源码都上传到了github上,最后放上源码地址:[payamount]0.10[/payamount]
[pay]https://github.com/1989Jiangtao/BluetoothSCM[/pay]







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评论

感谢分析  发表于 2018-10-3 14:38
 楼主| 涛声依旧520 发表于 2018-9-30 22:41 | 显示全部楼层
源码内容中包含STC单片机和STM8的蓝牙通讯部分源码
kklocust 发表于 2018-10-2 16:55 | 显示全部楼层
了解下
cooldog123pp 发表于 2018-10-3 20:15 | 显示全部楼层
一毛钱,很有想法啊,我就围观一下
 楼主| 涛声依旧520 发表于 2018-10-6 17:10 | 显示全部楼层
cooldog123pp 发表于 2018-10-3 20:15
一毛钱,很有想法啊,我就围观一下

哈哈,知识付费嘛!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

17

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部