⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 temperature.c

📁 c8051f020使用18B20采集数据
💻 C
字号:
#include "c8051f020.h"
#include "stdio.h"
#include "intrins.h"
#define READ_ROM 0x33         //读ROM
#define MATCH_ROM 0x55        //匹配ROM
#define SKIP_ROM 0xcc         //跳过ROM
#define SEARCH_ROM 0xf0       //搜索ROM
#define ALARM_SEARCH 0xec     //ROM发出警告
#define CONVERT_T 0x44        //启动温度转化
#define READ_SRAM 0xbe        //读暂存存储器
#define WRITE_SRAM 0x4e       //写暂存存储器
#define COPY_SRAM 0x48        //拷贝暂存存储器内容
#define RECALL_E2RAM 0xb8     //重新调用E2RAM
#define READ_POWER 0xb4       //读电源方式
#define SYSCLK	25000000	
#define BAUDRATE 9600			//波特率默认为9600
#define BUFSIZE 256
#define RX0BUFSIZE	256		//缓冲区默认为256字节
#define TX0BUFSIZE	256

bit symbol=0;                 //温度的正负号 symbol=0 为正;symbol=1 为负
sbit Ds18b20_DQ=P0^4;
unsigned char SN[8];




unsigned char Rx0Buf[RX0BUFSIZE],Tx0Buf[TX0BUFSIZE];//串口0接收和发送缓冲区
int Rx0In, Rx0Out, Tx0In, Tx0Out;	//循环缓冲区指针
int Tx0Count;	//已发送的字节数


void Close_WDG(void);
void SYSCLK_Init(void);
void UART_Init(void);
void DispLED(char *DispBuf,char ShowDot); 
void startConvertT(void);
unsigned int getT_matchDs18b20(char ID);
bit getSymbol();
void readSN(unsigned char SN[]);
void UART0_Init(void);
int ReadCom(char * buf, int num);
int WriteCom(char * buf, int num);


/*****************************************
*串口0读取函数
*第一个参数:指向读回的字符串存放的位置的指针
*第二个参数:要读取的字符个数
*返回成功读取的字符个数
*****************************************/
int ReadCom(unsigned char * buf, int num)
{
	int count = 0;
	while ((Rx0In != Rx0Out) && (count != num))
	{
        buf[count] = Rx0Buf[Rx0Out];
		Rx0Out = (Rx0Out + 1) % RX0BUFSIZE;
		count ++;
	}
	return count;
}

/*****************************************
*串口0发送函数
*第一个参数:要发送的字符串的首地址(指向要发送的字符串的指针)
*第二个参数:要发送的字节个数
*返回成功读取的字符个数
*****************************************/
int WriteCom(unsigned char * buf, int num)
{
	int count = 0;
	long i = 0;
	if(num != 0)
	{
 		 for (count = 0; count < num; count ++)
		{        
			Tx0Buf[Tx0In] = buf[count];

			if((Tx0In + 1) % TX0BUFSIZE == Tx0Out)	//the buffer is full
				Tx0Out = (Tx0Out + 1) % TX0BUFSIZE;	//replace the oldest data
			Tx0In = (Tx0In + 1) % TX0BUFSIZE;
	 	}
//begin to transmit
		REN0 = 0;

		TI0 = 1;
		Tx0Count = 0;
		while((Tx0In != Tx0Out) && (i < 60000000))	//wait for all the datas in transmit buffer sent out; or overtime 
			i ++;	
	
//transmit has completed	

		REN0 = 1;
	}
	else{}
	
	return Tx0Count;
}

//串口0中断服务程序
void UART0_ISR(void) interrupt 4
{

	if (RI0 == 1) 				// handle receive function
	{                     
 		RI0 = 0;               // clear RX complete indicator
		Rx0Buf[Rx0In] = SBUF0;

		if((Rx0In + 1) % RX0BUFSIZE == Rx0Out) //如果满 则覆盖以前的数据 
			Rx0Out = (Rx0Out + 1) % RX0BUFSIZE; //保证有效数据的位数
		Rx0In = (Rx0In + 1) % RX0BUFSIZE;
	}
	else if(TI0 == 1)
	{
   		TI0 = 0;
   		if( Tx0Out != Tx0In )		//Transmit Buffer is not empty	
   		{
   			SBUF0 = Tx0Buf[Tx0Out];
   			Tx0Out = (Tx0Out + 1) % TX0BUFSIZE;
			Tx0Count ++;		//calculate the number of the bytes having been sent
   		}
   		else{}					//Transmit buffer is empty, do nothing
   	}   
}



// 串口初始化函数
void UART0_Init()
{
	//初始化缓冲区
	Rx0In = Rx0Out = 0;
	Tx0In = Tx0Out = 0;		
	//波特率初始化 使用timer1,两个串口波特率相同
	TMOD |= 0x20;				// timer1, mode2, 8-bit reload
	TH1 = -(SYSCLK/BAUDRATE/16);// set Timer1 reload value for baudrate
    //TL1 = TH1;
	CKCON |= 0x10;		// Timer1 uses SYSCLK as time base
	PCON |= 0x80;		// SMOD0 = 1;禁止UART0波特率/2功能
	TR1 = 1;				// start Timer1

 	//交叉开关分配
 	XBR0 |= 0x04; //UART0允许 RX0,TX0连到两端口上
 	XBR2 |= 0x40; //交叉开关允许
	P0MDOUT |= 0x03;
	P0 = 0;
  
	SCON0 = 0x50;   //UART0为方式1:8位,波特率由定时器1决定
	T2CON &= ~(0x30);	// use timer1 as bautrate generator 

	ES0 	= 1;        //允许串口0中断
	
}




void main(void)
{
  long temperature=0;
  unsigned int feedbackT;
  unsigned char led[6];
  bit sign;
  int i;

  int count;
//	unsigned char getchar[256];  

  Close_WDG();//关闭看门狗
  SYSCLK_Init();//系统时钟初始化
  UART0_Init(); 		// 串口初始化函数
	EA = 1;

  UART_Init();//串口初始化
  readSN(SN); //读取DS18B20序列号,写入SN[]
  while(1)
	{
		temperature=0;
   	for(i=0;i<40;i++)
   	{
  	startConvertT(); //开始温度转换
  	feedbackT=getT_matchDs18b20(0);//获取温度值
		sign =getSymbol();//获取温度的正、负
		if(sign)
      temperature -=feedbackT;
		else 
	    temperature +=feedbackT;
		}
 		sprintf(led,"%6d",(int)(temperature/40));
				count = WriteCom(led, sizeof(led));
		DispLED(led,3);

 	}

}

void Delay1us(int us)    //延时us毫秒
{
	while (us)
	{
	  _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
	  --us;
	}
}

//发复位脉冲
//返回: 0-有设备连接    1-无设备连接
bit resetDs18b20(void)  
{
    unsigned char i;
    bit RstFlag;
	RstFlag=1;	
	Ds18b20_DQ=0;
	Delay1us(600);
	Ds18b20_DQ=1;
	Delay1us(60);	//15us-60us
	for (i=0;i<16;i++)	//60us-240us
	{
		Delay1us(15);
		if (Ds18b20_DQ==0) RstFlag=0;
	}
	Delay1us(240);	//240us
	return RstFlag;	
}

//向DS18b20写一个字节ch 
void writeByteToDs18b20(unsigned char ch)
{
    unsigned char i;
	Ds18b20_DQ=1;
	Delay1us(1);
	for (i=0;i<8;i++)
	{
		Ds18b20_DQ=0;
		Delay1us(15);
		Ds18b20_DQ=ch&0x1;

		Delay1us(45);
		Ds18b20_DQ=1;
		ch=ch>>1;
		Delay1us(1);
	}	
}

//接收DS18b20传送来的一个字节并返回
unsigned char readByteFromDs18b20(void)
{
    unsigned char i,ch;
	ch=0;
	Ds18b20_DQ=1;
	Delay1us(1);
	for (i=0;i<8;i++)
	{
		Ds18b20_DQ=0;
		Delay1us(10);
		Ds18b20_DQ=1;
		Delay1us(2);
		ch=ch>>1;
		if (Ds18b20_DQ==1)
		{
			ch=ch+0x80;
		}
		Delay1us(45);
	}	
	return ch;
}

//跳过ROM区
void skipROMCode(void)
{
	resetDs18b20();
	writeByteToDs18b20(SKIP_ROM); 
}

//启动DS18b20的温度转化功能
void startConvertT(void)
{

	resetDs18b20();		//复位
	writeByteToDs18b20(SKIP_ROM);  //广播
	writeByteToDs18b20(CONVERT_T); 	//启动AD转换12bit700ms
}

//读取DS18b20的序列号,更新SN[]
void readSN(unsigned char SN[])
{
  char i;
  while(resetDs18b20());
  writeByteToDs18b20(READ_ROM);  //读取ROM
  for(i=0;i<8;i++)
  {
   SN[i]=readByteFromDs18b20();
  } 
}

//发送序列号并匹配
void matchDs18b20(char ID)
{
  unsigned char i;
  writeByteToDs18b20(MATCH_ROM);  //匹配ROM
  for ( i = 0; i < 8; i++ ) 
    writeByteToDs18b20(SN[i]);
}

//获取温度值
unsigned int getTempValue(void)
{
    unsigned char low,high;
    unsigned int T;

	writeByteToDs18b20(READ_SRAM);
	low=readByteFromDs18b20();
	high=readByteFromDs18b20();
    
    T =low+high*256;
    if((high & 0xf8)!=0)
	  symbol=1;
	else symbol=0;
	if(symbol)      //温度为负
      T =-T;
    T =T&0x07ff;
    T =(T/16.0)*100;
	return T;
}

//读取与指定的DS18b20相匹配的温度值
unsigned int getT_matchDs18b20(char ID)
{
  unsigned int T;
  int i;
  
  for(i=0;i<30000;i++);//延时等待转换结束

  resetDs18b20();      //复位
  skipROMCode();
  writeByteToDs18b20(CONVERT_T);
  Delay1us(2);         //2us
  
  resetDs18b20();      //复位
  matchDs18b20(ID);
  T=getTempValue();
  return(T);
}

//返回温度的正负号
bit getSymbol()
{
  return symbol;
}
void UART_Init(void)
{
  //初始化缓冲区
	Rx0In = Rx0Out = 0;
	Tx0In = Tx0Out = 0;		
	//波特率初始化 使用timer1,两个串口波特率相同
	TMOD |= 0x20;				// timer1, mode2, 8-bit reload
	TH1 = -(SYSCLK/BAUDRATE/16);// set Timer1 reload value for baudrate
    //TL1 = TH1;
	CKCON |= 0x10;		// Timer1 uses SYSCLK as time base
	PCON |= 0x80;		// SMOD0 = 1;禁止UART0波特率/2功能
	TR1 = 1;				// start Timer1


  XBR0=0x04;
  XBR2=0x44;
  SCON1=0x00;
  P0MDOUT=0xFF;

  SCON0 = 0x50;   //UART0为方式1:8位,波特率由定时器1决定
	T2CON &= ~(0x30);	// use timer1 as bautrate generator 

	ES0 	= 1;        //允许串口0中断
}
/*********************************************************
           功能:在六位数码管显示要求的字符串 含标点
       *DispBuf:要显示的字符串,长度为6
        ShowDot:标点的位置
              0:不显示
           1~6:标点显示在数码管的对应位 
*********************************************************/
unsigned char code table[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,
0xf6,0xee,0x3e,0x9a,0x7c,0x9e,0x8e,0x04,0x00};
void DispLED(char *DispBuf,char ShowDot)//ShowDot 显示小数点位 
{
    char ch;
	int i=0,j;
	ShowDot=6-ShowDot;       //显示小数点
	SCON1=0x20;
	for(i=5;i>=0;i--)
	{
	    ch=DispBuf[i]; 
		if ((ch>='a') && (ch<='f'))  //转换ASCII码为对应段码
		{  ch-='a';ch+=10;}
		else if ((ch>='A') && (ch<='F'))
		{  ch-='A';ch+=10;}
		else if ((ch>='0') && (ch<='9'))
	       ch-='0';
		else if (ch=='-')            //显示负号
		   ch=16;
		else 
		   ch=17;   
		if (i==ShowDot)           //显示小数点
		   SBUF1=table[ch]+1;
		else
		   SBUF1=table[ch];
	    for(j=0;j<255;j++);    //延时
		if(i==0)                //清除串口中断
		   SCON1=0;
	} 
}

/*****************************************
	Function:initiate the system clock
*****************************************/
void SYSCLK_Init(void)
{
	int i;
	OSCXCN=0x67;           // start external oscillator with 22.1184MHz crystal
 	for(i=0;i<256;i++);    // XTLVLD blanking interval (>1ms)
	while(!(OSCXCN&0x80)); // Wait for crystal osc. to settle
	OSCICN=0x88;           // select external oscillator as SYSCLK 
							// source and enable missing clock
}
void Close_WDG()
{      
  WDTCN=0xde;        // disable watchdog timer
  WDTCN=0xad;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -