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

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


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


蓝牙APP+STC单片机

蓝牙APP+STC单片机


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

温度

温度

单片机

单片机



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

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


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


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

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

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

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

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

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

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

void ds1820disp();         // 温度显示

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

/***********端口定义*************/
sbit LED_R = P0^0 ;
sbit LED_G = P0^1 ;
sbit LED_B = P0^2 ;

/*******程序入口*********/
void main()
{

        unsigned int temperature , old ; // 保存温度数值
       
        Init_UART();  // 串口初始化
       
        LCD_Init();  // OLED 初始化
        LCD_CLS();   // 清屏
       
        LCD_P8x16Str(0 , 0 , "TEMP:");  // 温度开始位置
       
        temperature = ReadTemperature();
        old = temperature ;
        ds1820disp(); // 显示温度
        UART_SendStr(disdata); // 向串口发送数据
        LCD_P8x16Str(5*8 , 0 , disdata); // 显示温度
       
        while(1)
        {
               
                temperature=ReadTemperature();  // 读取一次新的温度
    if (temperature != old )          
          {         
                        old = temperature;
                        ds1820disp(); // 显示温度
                        UART_SendStr(disdata); // 向串口发送数据
                        LCD_P8x16Str(5*8 , 0 , disdata); // 显示温度

          }
               
                if(flag) // 接收数据完毕一次,就会进入中断一次
                {
                        flag = 0 ; // 将标志位还原,使得串口又可以重新接收数据
                                       
                        if(strcmp(RECEIVED_CMD , LED_ON) == 0)
                        {
                                P2 = 0xFF ; // P2口全亮
                                power_flag = 1 ; // 标志电源打开
                        }
                        else if(strcmp(RECEIVED_CMD , LED_OFF) == 0)
                        {
                                P2 = 0x00 ; // P2口全灭
                                power_flag = 0 ;// 标志电源关闭
                        }
                        else if(strcmp(RECEIVED_CMD , LED_01_ON) == 0)
                        {
                                if(power_flag)                 // 如果电源开关是关闭的,就不执行以下操作
                                        P2 = 0x55 ;                 // ‭01010101‬ 为1位置的灯是亮着的
                                else
                                        UART_SendStr(FAILD); // 向串口发送失败原因
                        }
                        else if(strcmp(RECEIVED_CMD , LED_01_OFF) == 0)
                        {
                                P2 = P2^0x55 ; // P2口01010101相应位置的灯要全灭,所以使用异或操作
                        }
                        else if(strcmp(RECEIVED_CMD , LED_02_ON) == 0)
                        {
                                if(power_flag)                 // 如果电源开关是关闭的,就不执行以下操作
                                        P2 = 0xAA ;                 // ‭10101010‬ 为1位置的灯是亮着的
                                else
                                        UART_SendStr(FAILD); // 向串口发送失败原因
                        }
                        else if(strcmp(RECEIVED_CMD , LED_02_OFF) == 0)
                        {
                                P2 = P2^0xAA ; // P2口10101010相应位置的灯要全灭,所以使用异或操作
                        }
                        else if(strcmp(RECEIVED_CMD , FAN_ON) == 0)
                        {
                                test_Fan(1);
                        }
                        else if(strcmp(RECEIVED_CMD , FAN_OFF) == 0)
                        {
                                test_Fan(0);
                        }                       

                       
                        // 用完之后要记得数组清零处理
      RECEIVED_INDEX = 0 ;        // 数组指引复位
      memset(RECEIVED_CMD,0,10);  // 清0数组
                }
        }
}

/******************
** 初始化串口
*******************/
void Init_UART()
{
                SCON = 0x50;                     //设置8位数据位
                TMOD = 0x20;                     //8位自动重载
                TH1 = TL1 = -(FOSC/12/32/BAUD);  //设置重载值
                TR1 = 1;                         //使能时钟
                ES = 1;                          //使能串口中断
                EA = 1;                          //开中断开关
}

/********************
** 串口中断处理
*********************/
void UART_Isr() interrupt 4 using 1
{
        // 串口接收中断处理
        if(RI)
        {
                RI = 0 ;                              // 清除中断标志位
                RECEIVED_CMD[RECEIVED_INDEX] = SBUF ; // 保存串口接收的数据
                if(RECEIVED_CMD[RECEIVED_INDEX] == 0x0A ){ // 遇到了结束符号
                         flag = 1 ;           // 接收结束,到循环中处理接收的数据
                }else {
                         RECEIVED_INDEX ++ ;   // 继续接收数据
                }
        }

        // 串口发送中断处理
        if(TI)
        {
                TI = 0 ;  // 清发送中断标志位
        }
               
}

/**************************
** 通过串口发送一位数据
***************************/
void UART_SendData(char dat)
{
        ES = 0 ;      // 串口工作的时候禁止中断
        SBUF = dat ;  // 待发送的数据放到SBUF中
        while(!TI) ;  // 等待发送完毕
        TI = 0 ;      // 清TI中断
        ES = 1 ;      // 打开中断
}

/*****************************
**  通过串口发送字符串
******************************/
void UART_SendStr(char *str)
{
                do
                {
                        UART_SendData(*str);
                }while(*str ++  != '\0' ); // 一直到字符串结束
}

/****************************
**  显示RGB灯的颜色
*****************************/
void RGB_Display(int index)
{
        LED_R = color_table[index%8][0];
        LED_G = color_table[index%8][1];
        LED_B = color_table[index%8][2];
}

void Delay1ms()                //@11.0592MHz
{
        unsigned char i, j;

        _nop_();
        i = 2;
        j = 199;
        do
        {
                while (--j);
        } while (--i);
}

/****************
** 模拟风扇运行
****************/
void test_Fan(char flag)
{
        unsigned int t , count = 500 ;

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

///***********************************
//** 字符串截取函数
//***********************************/
//void split(char str[],char delims[])
//{
//        char *result = NULL;
//        result = strtok( str, delims );  
//        while( result != NULL ) {  
//                 result = strtok( NULL, delims );  
//        }
//}

/***************************
** 温度值显示
***************************/
void ds1820disp()
{        
          unsigned char flagdat;
       
                if(tflag==0)
//                        flagdat=0x20;//正温度不显示符号
                  flagdat=0x2b;//正温度显示符号
                else
                  flagdat=0x2d;//负温度显示负号:-
               
//                disdata[0] = flagdat; //符号位
       
                disdata[1]=tvalue/1000+0x30;//百位数
                disdata[2]=tvalue%1000/100+0x30;//十位数
                disdata[3]=tvalue%100/10+0x30;//个位数
                disdata[4]= 0x2E ;//小数点
                disdata[5]=tvalue%10/1+0x30;//小数位

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

#include "DS18b20.h"

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

void delay(unsigned int i)
{
while(i--);
}

void Init_DS18B20(void)
{
        unsigned char x=0;
        DQ = 1;   
        delay(8);  
        DQ = 0;   
        delay(80);
        DQ = 1;   
        delay(14);
        x=DQ;      
        delay(20);
}

unsigned char ReadOneChar(void)
{
        unsigned char i=0;
        unsigned char dat = 0;
        for (i=8;i>0;i--)
        {
                DQ = 0;
                dat>>=1;
                DQ = 1;
                if(DQ)
                 dat|=0x80;
                delay(4);
        }
        return(dat);
}

void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
  DQ = 0;
  DQ = dat&0x01;
  delay(5);
  DQ = 1;
  dat>>=1;
}
}

int ReadTemperature(void)
{
        unsigned char a=0;
        unsigned char b=0;

        Init_DS18B20();
        WriteOneChar(0xCC);
        WriteOneChar(0x44);
        Init_DS18B20();
        WriteOneChar(0xCC);
        WriteOneChar(0xBE);
        a=ReadOneChar();
        b=ReadOneChar();
        tvalue = b;
        tvalue <<= 8;
        tvalue = tvalue|a;
        if(tvalue<0x0fff)
                tflag=0;
        else
  {
                tvalue=~tvalue+1;
                tflag=1;
  }
        tvalue = tvalue*(0.625);//温度值扩大10倍,精确到1位小数
        return(tvalue);
}


我把源码都上传到了github上,最后放上源码地址:
此部分内容已被设置为付费内容,您可以在支付 0.1 元 人民币后浏览本楼层全部付费内容点击购买








本楼层付费信息已有12人购买
评论
dirtwillfly 2018-10-3 14:38 回复TA
感谢分析 

相关帖子

涛声依旧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

粉丝