waqich 发表于 2025-1-16 22:09:43

基于8G单片机的手机蓝牙温控程序

基于8G单片机的手机蓝牙温控程序   手机(安卓版)通过蓝牙与单片机通信,1秒钟读取1次温度数据与运行参数,也可以设置参数,单片机程序中参考了国芯抡坛上的STC8G系列-串口相关程序,的一个例程,串口1中断收发-C语言-MODBUS协议,原贴链接(https://www.stcaimcu.com/forum.php?mod=viewthread&tid=375&extra=page%3D1)硬件电路如下:






实物图如上,温度传感器置于冰箱冷冻室内,蓝牙串口模块型号是大厦龙雀的BT-04E,模块资料可在大厦龙雀官网上下载。单片机主时钟22.1184M,串口波特率9600,8位数据位,1个停止位,无校验。手机APP界面如下图:




用C#做了个串口操作工具,可以用电脑串口来直接读写数据,运行界面如下:




部分程序源码如下:voidmain()                              //程序开始运行的入口
{
       u8   i;
       u16crc;
       u8 LED_Data = 0XFE;   
       u8 num=0;
       u8 LED_DataTab = { 0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F};
int TempVal,TempValb;      //TempVal大于0的温度, TempValb小于0的温度
   sys_init();         //IO口初始化
    P1M0 = 0x00;       //设置P1.0为ADC口
    P1M1 = 0x01;
    ydsx=-250;
      ydxx=150;
      ydjz=0;
    P_SW2|=0x80;
    ADCTIM=0x3f;//设置ADC内部程序
    P_SW2&=0x7f;
    ADCCFG=0x2f;//设置ADC时钟为系统时钟/2/16
    ADC_CONTR=0x80;//使能ADC选P10为ADC通道
    //EEPROM读操作,读取第0扇区,10 12 14字节-------------------
      ydsx=IapRead(SECTOR0 + 10); //从EEPROM第0扇区10字节取温度上限值
    ydxx=IapRead(SECTOR0 + 12); //从EEPROM第0扇区12字节取温度下限值
      ydjz=IapRead(SECTOR0 + 14); //从EEPROM第0扇区14字节取温度校准值
    modbus_reg= ydsx;
    modbus_reg= ydxx;
      modbus_reg= ydjz;
      Timer0_Config(0, MAIN_Fosc / 20000);   //t=0:reload值是主时钟周期数, (中断频率, 20000次/秒)
      UART1_config(9600UL,1, 0);       // brt: 通信波特率,timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特
      BEEP = 0;             //上电蜂鸣响一声
      delay_ms(10);       //延时10ms
      BEEP = 1;             //关闭蜂鸣响
    tm1650_start();
    write_byte(0x48);//数码显示模式
    tm1650_ack();
    write_byte(0x31);//3级亮度,开显示。这里的指令数据 详情参阅TM1650的datasheet
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x68);
    tm1650_ack();
    write_byte(Num_Buff);//数码管千位上电显示1
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6a);
    tm1650_ack();
    write_byte(Num_Buff);//数码管百位上电显示8
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6c);
    tm1650_ack();
    write_byte(Num_Buff);//数码管十位上电显示8
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6e);
    tm1650_ack();
    write_byte(Num_Buff);//数码管个位上电显示8
    tm1650_ack();
    tm1650_end();
      Timer0_Config(0, MAIN_Fosc / 20000);   //t=0:reload值是主时钟周期数, (中断频率, 20000次/秒)
      UART1_config(9600UL, 1, 0);   //brt: 通信波特率, timer=2: 波特率使用定时器2, 其它值:使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,=1: 切换到P3.6 P3.7, =2:切换到P1.6 P1.7, =3: 切换到P4.3 P4.4.
    EA = 1;
      while(1)                     //无限循环
         {
   if(B_RX1_OK && !B_TX1_Busy)//收到数据, 进行MODBUS-RTU协议解析
          {
                      if(MODBUS_CRC16(RX1_Buffer, RX1_cnt) == 0)      //首先判断CRC16是否正确, 不正确则忽略, 不处理也不返回信息
                      {
                            if((RX1_Buffer ==0x00) || (RX1_Buffer == SL_ADDR))   //然后判断站号地址是否正确, 或者是否广播地址(不返回信息)
                            {
                                 if(RX1_cnt> 2) RX1_cnt -= 2;      //去掉CRC16校验字节
                                 i =MODBUS_RTU();      //MODBUS-RTU协议解析
                                 if(i != 0)//错误处理
                                 {
                                          TX1_Buffer= SL_ADDR;   //站号地址
                                          TX1_Buffer= i;                //错误代码
                                          crc =MODBUS_CRC16(TX1_Buffer, 2);
                                          TX1_Buffer= (u8)crc;       //CRC是小端模式, 先发低字节,后发高字节。
                                          TX1_Buffer= (u8)(crc>>8);
                                          B_TX1_Busy= 1;         //标志发送忙
                                          TX1_cnt    = 0;         //发送字节计数
                                          TX1_number= 4;         //要发送的字节数
                                          TI =1;                        //启动发送
                                 }
                            }
                     }
                     ydsx= modbus_reg;
      ydxx=modbus_reg;
            ydjz=modbus_reg;
                     RX1_cnt = 0;
                     B_RX1_OK = 0;
            }
      Test();          //按键查询处理
    // delay_ms(500);    //延时300ms
            if(TIM_Flag)//TIME0中断10000次(1秒)读一次温度
            {
               ADC_CONTR|=0x40; //启动AD
      _nop_();
      _nop_();
      while(!(ADC_CONTR&0x20)) ;   //查询ADC完成标志
      ADC_CONTR &= ~0x20;         //清完成标志
      //ADCCFG = 0x00;                  //设置结果左对齐(会出问题原因不详)
                ADCCFG = 0x20;                  //设置结果右对齐
      Temp=(ADC_RES << 8) |ADC_RESL;   //读取ADC结果
            TempVal = Temp_Cal(Temp)+ydjz; //ADC结果计算成温度值并加上校准值
               //TempVal = Temp_Cal(Temp);   //ADC结果计算成温度值
               modbus_reg= TempVal;//温度值写入xdata1003
               //TempVal = Temp;      //ADC结果计算成温度值
            if(Run_Flag==0)   //如果是制冷模式
            {   
                  if(TempVal<= ydxx)//实际温度低于温度下限
                {
                        Relay=1;       //关闭继电器(关闭制冷)
               }
            if(TempVal>= ydsx) //实际温度高于温度上限
                {
                         Relay=0;      //打开继电器(启动制冷)
               }
             }
          else                     //否则是制热模式
         {
               if(TempVal<= ydxx)    //实际温度低于温度下限
               {
                        Relay=0;         //打开继电器(启动加热)
               }
               if(TempVal>= ydsx)    //实际温度高于温度上限
                   {
                         Relay=1;      //关闭继电器(关闭加热)
                   }      
            }
                                     modbus_reg= Relay;   ////////继电器状态写入xdata1004                                          
         if(TempVal>= 0) //温度在0度以上
            {
                   SEG0 = TempVal/1000%10;   //温度千位
                              if (SEG0==0)
                              SEG0=23;            //千位为0时,消隐不显      
                      SEG1 = TempVal/100%10;      //温度百位
                      SEG2 = TempVal/10%10;       //温度十位
                      SEG3 = TempVal/1%10;      //温度个位
                      DspTemp();               //显示温度   
                }
         else            //温度在0度以下
             {   
                     TempValb=abs(TempVal); //取温度绝对值
                     SEG0 = 22;                   //千位显示“-”
                     SEG1 = TempValb/100%10;          //温度百位
                     SEG2 = TempValb/10%10;       //温度十位
                     SEG3 = TempValb/1%10;      //温度个位
                     DspTemp();
               }
                                 TIM_Flag=0;
       }
      }
}
//==========================================================
// 函数: void UART1_ISR (void) interrupt UART1_VECTOR
// 描述: 串口1中断函数
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-2
// 备注:
//==========================================================
voidUART1_ISR (void) interrupt UART1_VECTOR
{
       if(RI)
       {
            RI = 0;
            if(!B_RX1_OK) //接收缓冲空闲
            {
                     if(RX1_cnt >=RX1_Length)RX1_cnt = 0;
                     RX1_Buffer =SBUF;
                     RX1_TimeOut = 36;      //接收超时计时器, 35个位时间
            }
       }
       if(TI)
       {
            TI = 0;
            if(TX1_number != 0)   //有数据要发
            {
                     SBUF =TX1_Buffer;
                     TX1_number--;
            }
            else B_TX1_Busy = 0;
       }
}
voidDspTemp()
{
      write_byte(0x48);//数码显示模式
    tm1650_ack();
    write_byte(0x11);//1级亮度,开显示。这里的指令数据 详情参阅TM1650的datasheet
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x68);
    tm1650_ack();
    write_byte(Num_Buff[ SEG0]);//显示千位
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6a);
    tm1650_ack();
    write_byte(Num_Buff[ SEG1]);//显示百位
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6c);
    tm1650_ack();
    write_byte(Num_Buff[ SEG2]+0x80);//显示十位加小数点
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6e);
    tm1650_ack();
    write_byte(Num_Buff[ SEG3]);//显示个位
    tm1650_ack();
    tm1650_end();      
}

soma 发表于 2025-1-16 23:40:25

大夏龙雀的蓝牙模块

zhang_yg188 发表于 2025-5-8 17:36:43

楼主,压缩包下载下来,编译时 can't open file 'config.h',麻烦给下。谢谢!

waqich 发表于 2025-5-8 23:13:42

解压后在COMM文件夹内

waqich 发表于 2025-5-9 00:39:09

整理了一下,重新上传,请重新下载测试。

waqich 发表于 2025-5-9 01:10:04

安卓手机测试APP,不同手机要设置相应权限,仅供学习测试。

zhang_yg188 发表于 2025-5-9 08:48:39

麻烦问下,功能说明是11.0592MHz,定义的是221184,请问哪个是对的?

waqich 发表于 2025-5-9 11:48:48

221184

xxkj2010 发表于 2025-5-9 14:09:20

谢谢分享!先下载了

zhang_yg188 发表于 2025-5-9 15:49:36

waqich 发表于 2025-5-9 11:48
221184

好的,多谢!
页: [1] 2
查看完整版本: 基于8G单片机的手机蓝牙温控程序