Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem with DS18B20 + 8051

Status
Not open for further replies.

Musketeer

Newbie level 6
Joined
Oct 11, 2016
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
144
Hello everyone.

I'm trying to make a 8051 (AT89C51) to read temperature from DS18B20 and send it to a PC through the serial port (FT232).
I'm almost done, have the code alraedy, and it actually works in Proteus simulation.
sTRJmf.jpg
this is my code:

Code:
# include<reg51.h>

sbit dq = P3^5; // connect with DS1820 Data pin

sbit rs=P3^0;
sbit en=P3^1;

void delay_ms(int j)
{
	unsigned char i;

	for(;j;j--)
		for(i=122;i<=0;i--);
}

void delayus(int us)
{
	int i;
	for (i=0; i<us; i++);
}

bit reset(void)
{
	bit presence;
	dq = 0;
	delayus(29);
	dq = 1;
	delayus(3);
	presence = dq;
	delayus(25);
	return(presence);
}

bit readbit(void)
{
	unsigned char i=0;
	dq = 0;
	dq=1;
	for (i=0; i < 3; i++);
	return(dq);
}


void writebit(bit Dbit)
{
	unsigned char i=0;
	dq=0;
	dq = Dbit?1:0;
	delayus(5);
	dq = 1;
}

unsigned char readbyte(void)
{
	unsigned char i;
	unsigned char din = 0;
	for (i=0;i<8;i++)
	{
		din|=readbit()? 0x01<<i:din;
		delayus(6);
	}
	return(din);
}

void writebyte(unsigned char dout)
{
	unsigned char i;
	for (i=0; i<8; i++)
	{
		writebit((bit)(dout & 0x1));
		dout = dout >> 1;
	}
	delayus(5);
}

unsigned char * ReadTemp()
{
	unsigned char n;
	unsigned char buff[2]=0;
	reset();

	writebyte(0xcc);
	writebyte(0x44);

	while (readbyte()==0xff);
	delay_ms(500);

	reset();

	writebyte(0xcc);
	writebyte(0xbe);


	for (n=0; n<9; n++)
	buff[n]=readbyte();

	return buff;
}

void delay_ms110(unsigned int k)
{
	unsigned int i,j;
	for (i=0;i<=k;i++)
		for(j=0;j<110;j++);
}

void Serial_TX(char *str)
{
	unsigned int j;
	TMOD=0x20;
	TH1=0xFD;
	SCON=0x50;
	TR1=1;
	
	for(j=0;str[j]!=0;j++)
	{
		SBUF=str[j];
		while(TI==0)
		{}
		TI=0;
	}
	delay_ms110(500);
}

void Serial_TX_temp(char tp)
{
	unsigned int j;
	TMOD=0x20;
	TH1=0xFD;
	SCON=0x50;
	TR1=1;

	SBUF=tp;
	while(TI==0)
	{}
	TI=0;
	
	delay_ms110(500);
}


void main()
{
unsigned char tp,*temp,t=0x00;

	while(1)
	{
		dq = 0;
		temp=ReadTemp();
			
		temp[1]=temp[1]&0x07;
		tp=temp[0]>>4;
		temp[1]=temp[1]<<4;
		tp=tp+temp[1];

		P1 = tp;
		
		Serial_TX(" tempis: ");
		Serial_TX_temp(tp);
			
	}
}

when I make the actual board, it doesn't work. I mean it doesn't send anything to serial port, and I guess it's not reading anything from DS18B20 either. because I send the temp to P1 for diagnostic reasons, and when I test it P1 is just FFh (all the P1 are set to 1). I have tested simpler code, and I know this code can send data to serial port, it just doesn't work when I try to read the temperature.
So what am I missing? Any suggestion?

Thanks in advance.
 
Last edited by a moderator:

I just took a very closer look at the sensor, the text on it says "ds1820" and not ds18b20 (I've ordered ds18b20 though). Is that something that needs to be noticed?
 

I whould say, that it is almost impossible to figure out what it the problem without any measuring equipment like logic analyzer or at least oscilloscope. Your functions also not returning any error, you can't manage interface issues anyhow. It is just a lotery - will work or not.
 
I got a DS18B20 and changed the code a little, I used maxim instructions and it's working now.
However, It's for using single sensor. What if I want to use multiple sensors? Maxim website doesn't provide the code to use multiple sensors. Is there by any chance some code for multiple DS18B20 sensors using 8051?
 

I can give you a link to my topic on another forum where I posted complete code for DS18B20 supporting multisensors connection and search sensor routines. But it is on russian language. Hopefully, you will able to translate it.
 
thank you so much Easyrider83, much appreciated.

a few questions;
Is this code compatible with DS18B20? because in the attachment i found files named DS1822. donno if it's the same.
Is this compatible with 8051? because i looked a little and i found too many GPIO declarations which looked like arduino or something to me.
if not compatible, how can i make use of ur codes and integrate it with my project?

Cheers.
 

DS18B20 is equal to DS1822. I have no idea which of thouse I'm currently using even.
Code written on C. So it is compatible with any mcu. You can define GPIO yourself or just replace low level layer - 1-wire.c
If you already have low level functions like 1-wire reset, read byte, write byte - you can just connect them to DS1822.c file and it will work the same way.
 
ty Easyrider83. I tried to integrate ur code, but i couldn't. mostly due to my lack of C knowledge.

I worked on my code and some code i found here, and I wrote this:

Code:
#include <reg51.h>
#include <INTRINS.h>
unsigned char readdata[2];
sbit DQ=P2^0;
sbit MM=P1^0;
sbit NN=P1^1;

unsigned char bdata busyflag;
unsigned char datn,count;
unsigned char dat[9];
 
unsigned char word1[16]={" T= "};

#define FALSE 0
#define TRUE 1

#define PERIOD 10

unsigned char ROM[8]; // ROM Bit
unsigned char lastDiscrep = 0; // last discrepancy
unsigned char doneFlag = 0; // Done flag
unsigned char FoundROM[2][8]; // table of found ROM codes
unsigned char numROMs;
unsigned char dowcrc;
int time = 101;
int i,numDev;
int scratch[9];

unsigned char code dscrc_table[] = {
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};

/////////////////end of variable////////////

void Serial_TX(char *str);
///////////////ds18b20/////////////////////
//Delay function
void delay(unsigned int i)
{
    while(i--);
}
 
void delay_ms(int j)
{
	unsigned char i;

	for(;j;j--)
for(i=122;i<=0;i--);
}

void delay_us(int us)
{
	int i;
	for (i=0; i<us; i++);
}


// OW_RESET - performs a reset on the one-wire bus and
// returns the presence detect. Reset is 480us, so delay
// value is (480-24)/16 = 28.5 - we use 29. Presence checked
// another 70us later, so delay is (70-24)/16 = 2.875 - we use 3.
//
unsigned int ow_reset(void)
{
	unsigned int presence;
	DQ = 0; //pull DQ line low
	delay_us(29); // leave it low for 480us
	DQ = 1; // allow line to return high
	delay_us(3); // wait for presence
	presence = DQ; // get presence signal
	delay_us(25); // wait for end of timeslot
	return(presence); // presence signal returned
} // 0=presence, 1 = no part

//Initialization function
void Init_DS18B20(void)
{
    unsigned char x=0;
    DQ = 1;    //DQ reset
    delay(8);  //Slight delay
    DQ = 0;    //SCM will be pulled down DQ
    delay(80); //Accurate than 480us delay
    DQ = 1;    //Pulled the bus
    delay(14);
    x=DQ;      //After slight delay is initialized if x = 0 x = 1 is initialized successfully defeat
    delay(20);
}
 
//Reading a byte
unsigned char ReadOneChar(void)
{
    unsigned char i=0;
    unsigned char dat = 0;
    for (i=8;i>0;i--)
    {
      DQ = 0; // To the pulse signal
      dat>>=1;
      DQ = 1; // To the pulse signal
      if(DQ)
      dat|=0x80;
      delay(4);
    }
    return(dat);
}

// READ_BIT - reads a bit from the one-wire bus. The delay
// required for a read is 15us, so the DELAY routine won't work.
// We put our own delay function in this routine in the form of a
// for() loop.
//
unsigned char read_bit(void)
{
	unsigned char i;
	DQ = 0; // pull DQ low to start timeslot
	DQ = 1; // then return high
	for (i=0; i<3; i++); // delay 15us from start of timeslot
	return(DQ); // return value of DQ line
}

void write_bit(char bitval)
{
	DQ = 0; // pull DQ low to start timeslot
	if(bitval==1) DQ =1; // return DQ high if write 1
	delay_us(5); // hold value for remainder of timeslot
	DQ = 1;
}// Delay provides 16us per loop, plus 24us. Therefore delay(5) = 104us



//Write a byte
void WriteOneChar(unsigned char dat)
{
    unsigned char i=0;
    for (i=8; i>0; i--)
    {
      DQ = 0;
      DQ = dat&0x01;
      delay(5);
      DQ = 1;
      dat>>=1;
    }
    delay(4);
}
 

// ONE WIRE CRC
//
unsigned char ow_crc( unsigned char x)
{
	dowcrc = dscrc_table[dowcrc^x];
	return dowcrc;
}

// NEXT
// The Next function searches for the next device on the 1-Wire bus. If
// there are no more devices on the 1-Wire then false is returned.
//
unsigned char Next(void)
{
	unsigned char m = 1; // ROM Bit index
	unsigned char n = 0; // ROM Byte index
	unsigned char k = 1; // bit mask
	unsigned char x = 0;
	unsigned char discrepMarker = 0; // discrepancy marker
	unsigned char g; // Output bit
	unsigned char nxt; // return value
	int flag;
	nxt = FALSE; // set the next flag to false
	dowcrc = 0; // reset the dowcrc
	flag = ow_reset(); // reset the 1-Wire
	if(flag||doneFlag) // no parts -> return false
	{
		lastDiscrep = 0; // reset the search
		return FALSE;
	}
	WriteOneChar(0xF0); // send SearchROM command
	do
	// for all eight bytes
	{
		x = 0;
		if(read_bit()==1) 
			x = 2;
		delay_us(6);
		if(read_bit()==1) 
			x |= 1; // and its complement
		if(x ==3) // there are no devices on the 1-Wire
			break;

		else
		{
			if(x>0) // all devices coupled have 0 or 1
				g = x>>1; // bit write value for search
			else
			{
				// if this discrepancy is before the last
				// discrepancy on a previous Next then pick
				// the same as last time
				if(m<lastDiscrep)
					g = ((ROM[n]&k)>0);
				else // if equal to last pick 1
					g = (m==lastDiscrep); // if not then pick 0
				// if 0 was picked then record
				// position with mask k
				if (g==0) discrepMarker = m;
			}
			if(g==1) // isolate bit in ROM[n] with mask k
				ROM[n] |= k;
			else
				ROM[n] &= ~k;
			write_bit(g); // ROM search write
			m++; // increment bit counter m
			k = k<<1; // and shift the bit mask k
			if(k==0) // if the mask is 0 then go to new ROM
			{ // byte n and reset mask
				ow_crc(ROM[n]); // accumulate the CRC
				n++; k++;
			}
		}
	}while(n<8); //loop until through all ROM bytes 0-7
	if(m<65||dowcrc) // if search was unsuccessful then
		lastDiscrep=0; // reset the last discrepancy to 0
	else
	{
		// search was successful, so set lastDiscrep,
		// lastOne, nxt
		lastDiscrep = discrepMarker;
		doneFlag = (lastDiscrep==0);
		nxt = TRUE; // indicates search is not complete yet, more
		// parts remain
	}
	return nxt;
}

// FIRST
// The First function resets the current state of a ROM search and calls
// Next to find the first device on the 1-Wire bus.
//
unsigned char First(void)
{
	lastDiscrep = 0; // reset the rom search last discrepancy global
	doneFlag = FALSE;
	return Next(); 
}

// FIND DEVICES
int FindDevices(void)
{
	
	unsigned char m;
	int count = 0;
	Serial_TX(" start of find");
	if(!ow_reset()) //Begins when a presence is detected
	{
		Serial_TX(" ow_reset");
		if(First()) //Begins when at least one part is found
		{
			numROMs=0;
			do
			{
				numROMs++;
				count++;
				for(m=0;m<8;m++)
				{
					FoundROM[numROMs][m]=ROM[m]; //Identifies ROM
					// number on found device
				} 
			}while (Next()); 
		}
	}
	else
	{
		Serial_TX(" else ow_reset");
	}
	return count;
}

/*
void Read_ROMCode(void)
{
	int n;

	ow_reset();
	WriteOneChar(0x33);
	for (n=0;n<8;n++){dat[n]=ReadOneChar();}
	
}
*/
// Perform Match ROM
unsigned char Send_MatchRom(void)
{
	unsigned char i;
	if(ow_reset()) return 0;
		WriteOneChar(0x55); // match ROM
	for(i=0;i<8;i++)
	{
		WriteOneChar(FoundROM[numROMs][i]); //send ROM code
	}
	return 1;
}

/*
void Read_ScratchPad(void)
{
	int j;
	char pad[9];
	WriteOneChar(0xBE);
	for (j=0;j<9;j++)
	{
		pad[j]=ReadOneChar();
	}
}
*/

/*
//Read temperature
void  ReadTemperature(void)
{
    Init_DS18B20();
    WriteOneChar(0xCC); // Skip read serial number column number of operations
    WriteOneChar(0x44); // Start temperature conversion
    Init_DS18B20();
    WriteOneChar(0xCC); //Skip read serial number column number of operations
    WriteOneChar(0xBE); //Read the temperature register, etc. (a total of 9 registers readable) is the temperature of the first two
    readdata[0]=ReadOneChar();
    readdata[1]=ReadOneChar();
   
}
*/

void Tempprocess() //Temperature Conversion
{
    unsigned int t;
    float tt;
    unsigned char temp;
    if((readdata[1]&0x80)!=0)
    {
        word1[3]='-';
        t=readdata[1];
        t<<=8;
        t=t|readdata[0];
        t=t-1;
        t=~t;
        t>>=4;
        word1[4]=t/100+48;
        word1[5]=((t/10)%10)+48;
        word1[6]=t%10+48;
        temp=readdata[0];
        temp=temp-1;
        temp=~temp;
        temp=temp&0x0f;
        tt=temp*0.0625;
        word1[7]='.';
        word1[8]=(unsigned char )(tt*10);
        word1[9]=(unsigned char )(tt*100-word1[8]*10);
        word1[10]=(unsigned char )(tt*1000-word1[8]*100-word1[9]*10);
        word1[11]=(unsigned char )(tt*10000-word1[8]*1000-word1[9]*100-word1[10]*10);
        word1[8]+=48;
        word1[9]+=48;
        word1[10]+=48;
        word1[11]+=48;
        word1[12]='C';
 
    }
    else
    {
        word1[3]='+';
        t=readdata[1];
        t<<=8;
        t=t|readdata[0];
        t>>=4;
        word1[4]=t/100+48;
        word1[5]=((t/10)%10)+48;
        word1[6]=t%10+48;
        temp=readdata[0];
        temp=temp&0x0f;
        tt=temp*0.0625;
        word1[7]='.';
        word1[8]=(unsigned char )(tt*10);
        word1[9]=(unsigned char )(tt*100-word1[8]*10);
        word1[10]=(unsigned char )(tt*1000-word1[8]*100-word1[9]*10);
        word1[11]=(unsigned char )(tt*10000-word1[8]*1000-word1[9]*100-word1[10]*10);
        word1[8]+=48;
        word1[9]+=48;
        word1[10]+=48;
        word1[11]+=48;
        word1[12]='C';
    }
}
/////////////////////end  of ds18b20//////////////////

/////////////////////Serial//////////////////
void delay_ms110(unsigned int k)
{
	unsigned int i,j;
	for (i=0;i<=k;i++)
		for(j=0;j<110;j++);
}

void Serial_TX(char *str)
{
	unsigned int j;
	TMOD=0x20;
	TH1=0xFD;
	SCON=0x50;
	TR1=1;
	
	for(j=0;str[j]!=0;j++)
	{
		SBUF=str[j];
		while(TI==0)
		{}
		TI=0;
	}
	delay_ms110(500);
}

/*
void Serial_TX_temp(char tp)
{
	TMOD=0x20;
	TH1=0xFD;
	SCON=0x50;
	TR1=1;

	SBUF=tp;
	while(TI==0)
	{}
	TI=0;
	
	delay_ms110(1500);
}
*/
/////////////////////end  of serial//////////////////

void main()
{
	
	MM = 0;
	NN = 1;
	
	Init_DS18B20();
	Serial_TX("start ");
	// Find devices on the bus 
	numDev = FindDevices(); 

	
	for(i=1; i<=numDev; i++) 
	{ 
		Serial_TX("Device: "); 
	}
	while(1)
	{
		if ((!ow_reset()))     // If a device is present and it's time to send string 
		{ 
			 time = 0; 
			 WriteOneChar(0xCC); // Skip Rom command 
			 WriteOneChar(0x44); // Temperature convert command 
			 DQ = 1;
			 delay_ms(750);    // Max. conv. time is 750mS for 12 bit 
			 ow_reset(); 
				
			 // read all devices on bus 
			 for (numROMs=1; numROMs <= numDev; numROMs++) 
			 { 
					if (Send_MatchRom()) 
					{ 
						 WriteOneChar(0xBE); // Read scratch pad command                
						 for(i=0; i<2; i++) 
						 { 
								readdata[i]= ReadOneChar(); 

						 }            
								if(numROMs == 1)
								{
									Serial_TX(" Sensor #1: ");
									Tempprocess();						
									Serial_TX(word1);
								}
								if(numROMs == 2)
								{
									Serial_TX(" Sensor #2: ");
									Tempprocess();						
									Serial_TX(word1);
								}

						 							
					}     // if (Send_MatchRom()) 
			 }     // for (numRoms=1; numRoms <= numDev; numRoms++)  
		}     // if ((!ow_reset())&&(time > PERIOD)) 
		
	/*		ReadTemperature();
			Tempprocess();

			P1 = (readdata[0]>>4);
			Serial_TX(word1);
	*/


	}
}

it works fine with Proteus simulation. when I program it on an actual uC tho, it doesn't work. kinda crashes and sets all output ports to 1. I tested the hardware and it's working with other codes, so can't be a hardware failure.
what can cause such problem?

- - - Updated - - -

it also worth mentioning that as you can see i've put some serial messege transmit codes for diagnostic reasons. even the start of the main function doesn't work.
 

for what it's worth, i found what cause the problem. apparently the compiled hex was too big for the microcontroller. i couldn't manage to make it work until i reduced the program size to < 2k. i mean ((Program Size: data=81.0 xdata=0 code=1930))
I thought it might help some1 someday.

cheers.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top