资讯详情

国信长天单片机竞赛训练之DS18B20温度报警实验(三)

目标要求:板载DS18B20获取温度,并在数字管上保留4位小数显示,温度超过25.蜂鸣器报警小于25000度.0000度,所有LED间隔闪烁2秒,温度超过25秒.0000度,通过串口发送 temp high字符串;低于等于25.实时温度通过串口上传。

ds18b数据中提供了20例程的代码(基于stc89c52),而国信是长天的stc15k60s2.由于芯片工作频率不同,需要修改相关代码。需要注意的是,DS18B存取16位数据,分为高八位和低八位,高八位高四位为符号位,低八位低四位为小数位,其余为整数位,另外ds18b从低位读取20数据代码中读取的采样数据。

附上本次训练的代码:

main.c文件

#include <STC15F2K60S2.h> #include "onewire.h" #include "uart.h" #include "time.h" #include "seg.h"  static bit flag=1; static bit flag2=1;///灯是否翻转的标志 unsigned int count=0;//计数 void Init_all(void); #define ON  1 #define OFF 0    sbit relay =P0^4; sbit buzzer=P0^6; void buff(bit sw ){//蜂鸣器控制  if(sw){      P2=(P2&0x1f)|0xa0.//开蜂鸣器  1010    buzzer=1;relay=1;   P2&=0x1f;  }  else {   P2=(P2&0x1f)|0xa0;//关蜂鸣器     buzzer=0;relay=0;   P2&=0x1f;  }  } void led(bit sw){//led toggle  if(sw){  if(flag){       P2=(P2&0x1f)|0x80;   P0=0x00;   P2=(P2&0x1f);    flag=0;  }  else {    flag=1;   P2=(P2&0x1f)|0x80;   P0=0xff;   P2=(P2&0x1f);  } }  else{  P2=(P2&0x1f)|0x80;   P0=0xff;   P2=(P2&0x1f);//关led灯 } }  void alarm(float temp,char *temp_str){///温度报警函数    if(temp>25.0000){   buff(ON);//开蜂鸣器   led(OFF);//关灯   flag2=1;   send_string("temp high!\r\n");//串口发送高温 high temp     }  else if(temp<25.0000){   flag2=0;   buff(OFF);//关蜂鸣器      send_string(temp_str);//上传实时温度   send_string("\r\n");  }   } void main(void) {  float temperature=0.0;  unsigned  long temp=0;  unsigned char temp_str[8]="\0";  Init_all();  Timer0Init();  UartInit();///初始化串口发送函数  while (1)  {   /*通过数字管显示,显示温度保留2位小数*/   temperature=rd_temperature();   temp=temperature*10000;//123456   segbuff[0]=temp/100000;   segbuff[1]=temp0000/10000   11.//让它带小数数字   segbuff[2]=temp000/1000;   segbuff[3]=temp00/100;   segbuff[4]=temp0/10;   segbuff[5]=temp;      /*将数字转换成字符   加上一个0x30将将数字转换成字符*/                        //200000   temp_str[0]=temp/100000 0x30;   temp_str[1]=temp0000/10000 0x30;   temp_str[2]='.';   temp_str[3]=temp000/1000 0x30;   temp_str[4]=temp00/100 0x30;   temp_str[5]=temp0/10;   temp_str[6]=temp;   /*温度通过串口发送,执行指令*/          alarm(temperature,temp_str);     }   }  void time0() interrupt 1 /*根据初始设置,1毫秒执行一次*/ {  segplay();      if(!flag2){   count  ;     if(count==2000){    led(ON);    count=0;    }    } }    void Init_all(void) {  P2=0xa0.//关闭蜂鸣器继电器  P0=0x00;    P2=0x80;//关闭LED  P0=0xff; }   

time.c

#include "time.h"    void Timer0Init(void) //1毫秒@11.0592MHz {  AUXR |= 0x80; //定时器时钟1T模式  TMOD &= 0xF0; //设置定时器模式 16位自动重载  TL0 = 0xCD;   ///设定时初值  TH0 = 0xD4;   ///设定时初值  TF0 = 0;   //清除TF0标志  TR0 = 1;   ///定时器0开始计时  ET0 = 1;  EA = 1; //这两个启动必须加,否则不生效 }

onewire.c

#include "onewire.h"    void Delay_OneWire(unsigned int t) {  /*传统的8051单片机是12T,而15单片机是1T,理论上,延迟应扩大到12倍,其实8-12倍可以*/  unsigned char i;  while (t--)  {   for (i = 0; i < 8; i  )    ;  } }    void Write_DS18B20(unsigned char dat) {  unsigned char i;  for (i = 0; i < 8; i  )  {   DQ = 0;   DQ = dat & 0x01;   Delay_OneWire(5);   DQ = 1;   dat >>= 1;  }  Delay_OneWire(5); }    unsigned char Read_DS18B20(void) {  unsigned char i;  unsigned char dat;   for (i = 0; i < 8; i  )  {   DQ = 0;   dat >>= 1;   DQ = 1;//采样信号   if (DQ)   {    dat |= 0x80;   }   Delay_OneWire(5);  }  return dat; }    bit init_ds18b20(void) {  bit initflag = 0;   DQ = 1;  Delay_OneWire(12);  DQ = 0;  Delay_OneWire(80);  DQ = 1;  Delay_OneWire(10);  initflag = DQ;  Delay_OneWire(5);   return initflag; }    float rd_temperature(void) {  unsigned char low,high;/*用于存储暂存器的值*/  unsigned int temp;/*取整数*/  float result;  init_ds18b20();  Write_DS18B20(0xcc);/*跳过rom搜索*/  Write_DS18B20(0x44);/*打开温度转换*/   init_ds18b20(); Write_DS18B20(0xcc);/*跳过rom搜索*/ Write_DS18B20(0xbe);/*告诉总线准备读取暂存器*/     //DS18B20 16位 低四位和低八位的高四位是整数  low=Read_DS18B20()   high=Read_DS18B20();/高八位  temp =(high&0x0f);  temp<<=8;  temp|=low;  result =temp*0.0625;   return result;             } 

uart.c

#include "uart.h"  unsigned char xdata com0_buf[32]; unsigned char com0cnt = 0;    void UartInit(void) //9600bps@11.0592MHz {  SCON = 0x50;  //8位数据,可变波特率  AUXR |= 0x40;  ///定时器1时钟Fosc,即1T  AUXR &= 0xFE;  //串口1选择定时器1波特率发生器  TMOD &= 0x0F;  ///设定时间16位自动重新安装  TL1 = 0xE0;  ///设定时的初始值  TH1 = 0xFE;  ///设定时的初始值  ET1 = 0;  //禁止定时器1中断  TR1 = 1;  ///启动定时器1     }    void send_char(unsigned char chr) {      SBUF=chr;/*没有完成TI=0 完成以后TI=1 单片机自动置1*/   while(!TI);   TI=0;   }    void send_string(unsigned char *str)//发送符串
{
while(*str)
{
	send_char(*str);
	str++;
}
	
}

time.c

#include "time.h"

 
void Timer0Init(void) //1毫秒@11.0592MHz
{
	AUXR |= 0x80; //定时器时钟1T模式
	TMOD &= 0xF0; //设置定时器模式 16位自动重载
	TL0 = 0xCD;	  //设置定时初值
	TH0 = 0xD4;	  //设置定时初值
	TF0 = 0;	  //清除TF0标志
	TR0 = 1;	  //定时器0开始计时
	ET0 = 1;
	EA = 1; //这两个启动一定要加,否则不生效
}

seg.c

#include "seg.h"

unsigned char code segtab[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xc0 & 0x7f, 0xf9 & 0x7f, 0xa4 & 0x7f, 0xb0 & 0x7f, 0x99 & 0x7f, 0x92 & 0x7f, 0x82 & 0x7f, 0xf8 & 0x7f, 0x80 & 0x7f, 0x90 & 0x7f,0x7f}; //共阳极7段数码管数据编码,自己可以加一些特殊符号,注意每个符号在数组中的位置
unsigned char segbuff[] = {10, 10, 10, 10, 10, 10, 10, 10};																																											//显示的数据,加一级缓存的好处是更新数据时只要改此缓存,定时刷新会自动将数据输出
unsigned char segaddr = 0;

 
void segplay(void)
{
	P2 = (P2 & 0x1f) | 0xe0; //消影
	P0 = 0xff;
	P2 &= 0x1f;

	P2 = (P2 & 0x1f) | 0xc0; //选管
	P0 = 1 << segaddr;
	P2 &= 0x1f;

	P2 = (P2 & 0x1f) | 0xe0; //送选中管子数据
	P0 = segtab[segbuff[segaddr]];
	P2 &= 0x1f;

	if (++segaddr == 8)
		segaddr = 0;
}

       最后附上工程的下载链接:

链接:https://pan.baidu.com/s/1_JT0biT4lbQoT9SE0M_Kig  提取码:yzh1

标签: tr200温度变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台