基于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();
}
大夏龙雀的蓝牙模块 楼主,压缩包下载下来,编译时 can't open file 'config.h',麻烦给下。谢谢! 解压后在COMM文件夹内 整理了一下,重新上传,请重新下载测试。 安卓手机测试APP,不同手机要设置相应权限,仅供学习测试。 麻烦问下,功能说明是11.0592MHz,定义的是221184,请问哪个是对的?
221184
谢谢分享!先下载了 waqich 发表于 2025-5-9 11:48
221184
好的,多谢!
页:
[1]
2