727|6

34

帖子

2

TA的资源

一粒金砂(中级)

楼主
 

基于STC8H8K64U和DS18B20的温度采集和LabVIEW上位机显示 [复制链接]

 

之前通过 STC 单片机和 DS18B20 实现了环境温度采集并串口显示,后面进一步想要实现温度的实时监测和数据记录保存,因此编写了 LabVIEW 程序,修改了部分单片机程序代码。经过实验验证,该项目可以实现 LabVIEW 上位机对 MCU 发送指令,MCU 通过 DS18B20 温度传感器获取环境温度,并通过串口将数据反馈给上位机,上位机实时记录数据,并将日期和各个时刻的温度数据保存至文件。

 

LabVIEW上位机前面板设置如图所示

 

程序面板如下图所示

 

需要注意的是单片机发送字符串给上位机、上位机接收均是一位一位传递,因此需要考虑判定截止符号,并将字符串转化为一定精度的数值才能显示到 LabVIEW 图表。

实物连接如下图所示

51代码如下

/*--------- DS18B20 -----------
Function: Display temperature by UART
Board: STC8H8K64U
Main Fosc: 22.1184 MHz
Baud rate: 9600 bps
Connect: DQ --> P20
Author: Jin-Lei Li
Email: lijinlei0907@163.com
Date: June 28, 2024
Ref: https://www.stcaimcu.com/forum.php?mod=viewthread&tid=323&extra=page%3D1
Ref: UART section in STC32 series datasheet
------------------------------*/

#include "STC8H.h"
#include "intrins.h"

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long int u32;

#define MAIN_Fosc     22118400UL
#define Baudrate      9600
#define BRT           (65536 - (MAIN_Fosc/Baudrate + 2)/4)

sbit DQ = P2^0;

/*-- UART --*/
bit busy;
u8 wptr;//write put string
u8 rptr;//receive put string
u8 buffer; // 缓冲
u8 comdata[3]={0};      //定义数组数据(8位),存放串口命令数据
u8 recv_flag=0; // 串口收到信息标记
/*---------*/
bit MinusFlag;		//温度正负  0:正数  1:负数
//u16 Temper; // temperature
void GPIO_Init();
void UartInit();
void UartSend(u8 dat);
void UartSendStr(u8 *p);
void Display();
void Delay_ms(u16 ms);
void receive_data(void);      //接收串口数据
void test_do_data(void);      //测试串口数据是否正确,并更新数据
/*----------- Main Program ----------------*/
void main(void)
{
	P_SW2 |= 0x80; //扩展寄存器(XFR)访问使能
	
	GPIO_Init();
  UartInit();
	ES = 1;
  EA = 1;
  while(1)
  {
		if(recv_flag==1)
		{
			recv_flag=0;
			receive_data();
			test_do_data();
			//Delay_ms(500);
		}
  }
}
/*-------------- GPIO initialize ------------------*/
void GPIO_Init()
{
	P0M1 = 0x00;   P0M0 = 0x00;
  P1M1 = 0x00;   P1M0 = 0x00;
  P2M1 = 0x00;   P2M0 = 0x00;
  P3M1 = 0x00;   P3M0 = 0x00;
  P4M1 = 0x00;   P4M0 = 0x00;
  P5M1 = 0x00;   P5M0 = 0x00;
	P6M1 = 0x00;   P6M0 = 0x00;
  P7M1 = 0x00;   P7M0 = 0x00;
}
/*----------- Delay time ----------------*/
void Delay1us(void)	//@22.1184MHz
{
	u8 data i;

	_nop_();
	i = 5;
	while (--i);
}

void Delay60us(void)	//@22.1184MHz
{
	u8 data i, j;

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

void Delay480us(void)	//@22.1184MHz
{
	u8 data i, j;

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

void Delay_ms(u16 ms)
{
	u16 i;
  do{
      i = MAIN_Fosc / 10000;
      while(--i);
    }while(--ms);
}
/*-------------- UART Send byte ------------------*/
void UartSend(u8 dat)
{
    //while (busy);
    //busy = 1;
    SBUF = dat;
	while(!TI); // 相当于 TI==0
		TI=0;
}
/*-------------- UART Send string ------------------*/
void UartSendStr(u8 *p)
{
    while (*p!='\0')//字符串发送检测是否发完
    {
        UartSend(*p++);
    }
}
/*-------------- UART isr ------------------*/
void UartIsr() interrupt 4
{
    if (RI)
    {
        RI = 0;
        buffer = SBUF; // 缓冲
				recv_flag=1;//增加一个标志,看是否接收完毕,在主函数中实现功能
    }
}
/*---------------- UART initial -----------------*/
void UartInit()
{
  SCON = 0x50;
	TMOD = 0x00;
	TL1 = BRT;
	TH1 = BRT>>8;
	TR1 = 1;
  AUXR = 0x40;
  wptr = 0x00;
  rptr = 0x00;
  busy = 0;
	//ET1 = 0;		//禁止定时器%d中断
	//ES=1;               //串口中断打开
	//EA=1;
}
/*----------- Initialize DS18B20 ----------------*/
void Init_DS18B20(void)//初始化ds1820
{
  bit flag = 1;
  while( flag )
	{
		DQ = 0;				//输出低电平
		Delay480us();
		DQ = 1;				//输出高电平
		Delay60us();
		flag = DQ;			//读取当前电平
		Delay480us();	
	}
}
void DS18b20_Write_0(void)		//写逻辑0码
{
	DQ = 0;				//输出低电平
	Delay60us();
	DQ = 1;				//输出高电平
	Delay1us();		
	Delay1us();	
}

void DS18b20_Write_1(void)		//写逻辑1码
{
	DQ = 0;				//输出低电平
	Delay1us();	
	Delay1us();	
	DQ = 1;				//输出高电平
	Delay60us();	
}
/*----------- Read level ----------------*/
bit DS18b20_Read(void)		//读取电平
{
	bit state ;
	
	DQ = 0;				//输出低电平
	Delay1us();	
	Delay1us();	
	DQ = 1;				//输出低电平
	Delay1us();	
	Delay1us();	
	state = DQ;			//读取当前电平

	Delay60us();

	return 	state;
}
/*----------- Write byte ----------------*/
void WriteOneChar(u8 dat)//写一个字节
{
  u8 i;
	for( i=0;i<8;i++ )		//循环八次
	{
		if( dat & 0x01 )
			DS18b20_Write_1();
		else
			DS18b20_Write_0();
		dat >>=1;
	}
}
/*----------- Read byte ----------------*/
u8 ReadOneChar(void)//读一个字节
{
    u8 i = 0;
    u8 dat = 0;
    for (i=8;i>0;i--)
    {
      DQ = 0; // 给脉冲信号
      dat >>= 1;
      DQ = 1; // 给脉冲信号
      if( DS18b20_Read() )	//如果读取到的是1,
			dat |= 0x80;
    }
    return dat;
}

/*----------- Start ----------------*/
void Start_Convert()
{
	Init_DS18B20();
	WriteOneChar(0xcc);
	WriteOneChar(0x44);
}
/*----------- Read Temperature ----------------*/
u16 Readtemp(void)
{
  u8 Low = 0;
  u8 High = 0;
  u16 Temper = 0; // temperature
  float Tt = 0;
	
	Start_Convert();
	while(!DQ);				//4.等待DQ变成高电平
	
	Init_DS18B20();
	WriteOneChar(0xCC); //跳过读序号列号的操作
	WriteOneChar(0xBE); //读取温度寄存器
	
	Low = ReadOneChar();   //连续读两个字节数据   //读低8位
	High = ReadOneChar();                          //读高8位
	
	if( High & 0XF8 )							//有1出现就是负数
	{
		MinusFlag = 1;							//标志位负数
		Temper = (High<<8) | Low;		//将温度换算成16位
		Temper = (~Temper) +1; 			//按位取反+1
		Tt = Temper*0.0625;		//得到真实十进制温度值,因为DS18B20可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度
		Temper = Tt*10 + 0.5; //放大十倍,以便保留一位小数,并四舍五入
	}
	else
	{
		MinusFlag = 0;							//标志位正数
		Temper = (High<<8) | Low;		//将温度换算成16位
		Tt = Temper*0.0625;		//最终温度保留一位小数
		Temper = Tt*10 + 0.5;
	}
	return Temper;
}
/*----------- Display temperature ----------------*/
void Display()
{
    u16 val;
    u16 shi,ge,xiaoshu;
    val = Readtemp();
    shi = val/100+48;
    ge = val/10%10+48;
    xiaoshu = val%10+48;
	if( MinusFlag==1 ) // negtive
	{
		//UartSendStr("Temperature: ");
		UartSend('-');
    UartSend(shi);
    UartSend(ge);
    UartSend('.');
    UartSend(xiaoshu);
		UartSendStr("\r\n");
	}
	else // MinusFlag==0, positive
	{
		//UartSendStr("Temperature: ");
    UartSend(shi);
    UartSend(ge);
    UartSend('.');
    UartSend(xiaoshu);
		UartSendStr("\r\n");
	}
}

/*--------------------- 数据接收与测试 ----------------------------*/
void receive_data(void)       
{
  int i ;
  for(i=0;i<3;i++)
  {
    comdata[i] = buffer; // 将缓冲的数据赋值给数组
    Delay_ms(2); // 延时一会,让串口缓存准备好下一个字节,不延时可能会导致数据丢失
  }
}

void test_do_data(void) // 测试并执行命令
{
  if(comdata[0] == 0x55) //0x55和0xAA均为判断是否为有效命令
  {
    if(comdata[1] == 0xAA)
    {
      if(comdata[2] == 0xFF)
      {
        Display();
      }
    }
  }
}

LabVIEW和程序代码见附件。

C51_DS18B20_LabVIEW.zip

26.74 KB, 下载次数: 5

此帖出自51单片机论坛

最新回复

你的这个串口接收程序: [attach]823833[/attach]  从字面来理解,这读都是一个数据,我在想,这程序跑下来,能不能实现你说所的功能呀?   详情 回复 发表于 2024-7-15 07:29
点赞 关注
 

回复
举报

6773

帖子

2

TA的资源

版主

沙发
 

程序面板是LabView上位机的吗?

此帖出自51单片机论坛

点评

是的,上位机为LabVIEW图形编程软件,包含前面板和程序面板  详情 回复 发表于 2024-7-9 11:11
 
 
 

回复

222

帖子

3

TA的资源

一粒金砂(高级)

板凳
 

这个作品再优化就可以做成一个产品了


此帖出自51单片机论坛

点评

后续会考虑集成、小型化和器件化;但是仅温度采集其功能太过单一,可以适当拓展,丰富功能可以增大市场和受众,也更加吸引消费者。  详情 回复 发表于 2024-7-9 11:14
 
 
 

回复

34

帖子

2

TA的资源

一粒金砂(中级)

4
 
wangerxian 发表于 2024-6-29 14:41 程序面板是LabView上位机的吗?

是的,上位机为LabVIEW图形编程软件,包含前面板和程序面板

此帖出自51单片机论坛
 
个人签名

MCU 开发者和爱好者

 
 

回复

34

帖子

2

TA的资源

一粒金砂(中级)

5
 
Maker_kun 发表于 2024-6-29 17:35 这个作品再优化就可以做成一个产品了

后续会考虑集成、小型化和器件化;但是仅温度采集其功能太过单一,可以适当拓展,丰富功能可以增大市场和受众,也更加吸引消费者。

此帖出自51单片机论坛
 
个人签名

MCU 开发者和爱好者

 
 

回复

6841

帖子

11

TA的资源

版主

6
 

你的这个串口接收程序:

  从字面来理解,这读都是一个数据,我在想,这程序跑下来,能不能实现你说所的功能呀?

此帖出自51单片机论坛

点评

可以实现功能  详情 回复 发表于 2024-7-16 05:05
 
 
 

回复

34

帖子

2

TA的资源

一粒金砂(中级)

7
 
lugl4313820 发表于 2024-7-15 07:29 你的这个串口接收程序:   从字面来理解,这读都是一个数据,我在想,这程序跑下来,能不能实现你 ...

可以实现功能

此帖出自51单片机论坛
 
个人签名

MCU 开发者和爱好者

 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表