[PIC] ds18B20 and PIC18F4550

Status
Not open for further replies.

K33rg4t3

Full Member level 3
Joined
Aug 2, 2015
Messages
165
Helped
7
Reputation
14
Reaction score
7
Trophy points
1,298
Activity points
2,607
Hey guys
I am going to use it in weather station.
I use pIC18F4550 and DS18B20
Can anyone tell me few things?
1. Do I have to write One-wire code myself or is there a library in MikroC ?
2. Can I use any digital pin for communication or does it have to be a specific one like with TX/RX ?
Thanks in advance!
 

I have a copy but do not use it for programming. It appears there is a library with reset, write and read functions and it can be used on any pin.

Brian.
 
I have searched and found library with OW_Read, OW_Reset, OW_Write... but I need to use those functions myself to communicate with ds18B20?
 

Well, you don't HAVE to use them, you can write your own routines if you like, 1-Wire isn't difficult to program. If they are there already in the library you might as well use them though. There is no other way to use a DS18B20 than through a 1-Wire interface.

Brian.
 

It edoes not work - output is always a zeros string.
I have connected VCC to VCC, GND TO GND, and signal to port D2 with 4.7k pullup to VCC.

Code:
Code:
        OW_Reset(&PORTD, 2); // 'Reset command to initialize One-Wire
         OW_Write(&PORTD, 2, 0xCC); // 'Skip ROM Command
         OW_Write(&PORTD, 2, 0x44); // 'Convert_T command
         delay_ms(1200); // 'Provide delay for conversion


         OW_Reset(&PORTD, 2); // 'Reset command to initialize One-Wire
         OW_Write(&PORTD, 2, 0xCC); // 'Skip ROM Command
         OW_Write(&PORTD, 2, 0xBE); // 'Read Scratchpad Command
         TempL = OW_Read(&PORTD,2); //Read Temperature low byte
         TempH = OW_Read(&PORTD,2); //Read Temperature high byte
         DP = TempL & 0x01; // 'Check if Temperature is integer or fractional
         if (TempH){ //If reading is negative
            vDisp[0] = '-';
            TempL = ((~TempL) + 1) >> 1;
         }
         else{
             vDisp[0] = '+';
             TempL = TempL >> 1; // 'Shift one position right (divide by 2) to get integer reading and get rid of decimal point
         }
         vDisp[1] = (TempL / 100) + 48; // 'Get hundreds and convert to ASCII
         vDisp[2] = ((TempL / 10) % 10) + 48; // 'Get tens and convert to ASCII
         vDisp[3] = (TempL % 10) + 48; // 'Get units and convert to ASCII
         if (DP){ // 'If reading is fractional, ie has 0.5 at end
            vDisp[5] = '5';
         }
         else{ // 'If reading is a whole number
            vDisp[5] = '0';
         }

Please help...
 

This code work 100%. I wrote it few years ago and used many times in different project based on STM8 and STM32.
Header for 1-wire
Code:
#define Time_Pulse_Delay_Low	        10      //10
#define Time_Pulse_Delay_High	        40      //40
#define Time_Reset_Low			500
#define Time_After_Reset		350
#define Time_Hold_Down			10

#define One_Wire_Read_ROM		0x33
#define One_Wire_Skip_ROM		0xCC
#define One_Wire_Search_ROM		0xF0
#define One_Wire_Match_ROM		0x55

#define One_Wire_Success		0x00
#define One_Wire_Error_No_Echo	        0x01
#define One_Wire_Bus_Low_Error	        0x02
#define One_Wire_Device_Busy	        0x03
#define One_Wire_CRC_Error		0x04

unsigned int One_Wire_Reset(void);
void One_Wire_Write_Byte(unsigned char Byte);
unsigned char One_Wire_Read_Byte(void);
unsigned char One_Wire_Read_Bit (void);
void One_Wire_Write_Bit (unsigned char Bit);
Low level routines:
Code:
unsigned int One_Wire_Reset(void)								
{
	unsigned int tmp;
	if ((PIN_SYG(One_Wire_RX)))	return One_Wire_Bus_Low_Error;
	PIN_OFF(One_Wire_TX);
	delay_us(250);
        delay_us(250);
	PIN_ON(One_Wire_TX);
	delay_us(Time_Pulse_Delay_High);
	if ((PIN_SYG(One_Wire_RX))) tmp = One_Wire_Success;
		else tmp = One_Wire_Error_No_Echo;
	delay_us(250);
        delay_us(200);
	return tmp;
}

void One_Wire_Write_Byte(unsigned char Byte)
{
	unsigned char cnt;
	for (cnt=0;cnt!=8;cnt++) One_Wire_Write_Bit(Byte&(1<<cnt));
}

void One_Wire_Write_Bit (unsigned char Bit)
{
	PIN_OFF(One_Wire_TX);
	if (Bit==0)
	{
		delay_us(Time_Pulse_Delay_High);
		PIN_ON(One_Wire_TX);
		delay_us(Time_Pulse_Delay_Low);
	}
	else
	{
		delay_us(Time_Pulse_Delay_Low);
		PIN_ON(One_Wire_TX);
		delay_us(Time_Pulse_Delay_High);
	}
} 

unsigned char One_Wire_Read_Byte(void)
{
	unsigned char tmp=0;
	unsigned char cnt;
	for (cnt=0;cnt!=8;cnt++)
		if (One_Wire_Read_Bit()!=0)	tmp|=(1<<cnt);
	delay_us(Time_Pulse_Delay_High);
	return tmp;
}

unsigned char One_Wire_Read_Bit (void)
{
		unsigned char tmp;
		PIN_OFF(One_Wire_TX);
		delay_us(Time_Hold_Down);
		PIN_ON(One_Wire_TX);
		delay_us(Time_Pulse_Delay_Low);
		if ((PIN_SYG(One_Wire_RX))!=0)	tmp = 0;
			else tmp = 1;
		delay_us(Time_Pulse_Delay_High);
		return tmp;
}
DS18b20 communication:
Code:
unsigned char DS1822_Start_Conversion_Skip_Rom (void)			 
{	
	unsigned char tmp; 											
	tmp=One_Wire_Reset();
	if (tmp!=One_Wire_Success) return tmp;												
	One_Wire_Write_Byte(One_Wire_Skip_ROM);
	One_Wire_Write_Byte(DS1822_CONVERT_T_CMD);
	if (One_Wire_Read_Byte()==0)	return One_Wire_Success;
		else	return One_Wire_Device_Busy;
}
and reading values after conversion:
Code:
unsigned char DS1822_Read_Temp_NoCRC_Skip_Rom (unsigned int * temperatura)				 
{
	unsigned char tmp; 											
	tmp=One_Wire_Reset();
	if (tmp!=One_Wire_Success) return tmp;
	One_Wire_Write_Byte(One_Wire_Skip_ROM);
	One_Wire_Write_Byte(DS1822_READ_STRATCHPAD_CMD);
	* temperatura = One_Wire_Read_Byte()|(One_Wire_Read_Byte()<<8);
	return One_Wire_Success;
}
 

What is PIN_ON, PIN_SYG, PIN_OFF?
 

Why are there two pins?
One_Wire_RX
One_Wire_TX
?
My DS18B20 has only one data bi-directional pin.
 

Good notice! That was made for optical isolated 1-wire.
For single wire use this code:
Code:
unsigned int One_Wire_Reset(void)								
{
	unsigned int tmp;
        PIN_ON(One_Wire_Pin);
        PIN_OUT_OD(One_Wire_Pin);
	if ((PIN_SYG(One_Wire_Pin)==0))	return One_Wire_Bus_Low_Error;
        PIN_OFF(One_Wire_Pin);       	
	delay_us(250);
        delay_us(250);
        PIN_ON(One_Wire_Pin);
	delay_us(Time_Pulse_Delay_High);
	if ((PIN_SYG(One_Wire_Pin))) tmp = One_Wire_Error_No_Echo;
		else tmp = One_Wire_Success;
	delay_us(250);
        delay_us(200);
	return tmp;
}

void One_Wire_Write_Byte(unsigned char Byte)
{
	unsigned char cnt;
	for (cnt=0;cnt!=8;cnt++) One_Wire_Write_Bit(Byte&(1<<cnt));
}

void One_Wire_Write_Bit (unsigned char Bit)
{                
        PIN_OFF(One_Wire_Pin);
	if (Bit==0)
	{
		delay_us(Time_Pulse_Delay_High);
		PIN_ON(One_Wire_Pin);
		delay_us(Time_Pulse_Delay_Low);
	}
	else
	{
		delay_us(Time_Pulse_Delay_Low);
		PIN_ON(One_Wire_Pin);
		delay_us(Time_Pulse_Delay_High);
	}
} 

unsigned char One_Wire_Read_Byte(void)
{
	unsigned char tmp=0;
	unsigned char cnt;
	for (cnt=0;cnt!=8;cnt++)
		if (One_Wire_Read_Bit()!=0)	tmp|=(1<<cnt);
	delay_us(Time_Pulse_Delay_High);
	return tmp;
}

unsigned char One_Wire_Read_Bit (void)
{
		unsigned char tmp;              
		//PIN_OUT_PP(One_Wire_Pin);
                PIN_OFF(One_Wire_Pin);
		delay_us(Time_Hold_Down);
		PIN_ON(One_Wire_Pin);
		delay_us(Time_Pulse_Delay_Low);
		if ((PIN_SYG(One_Wire_Pin))!=0)	tmp = 1;
			else tmp = 0;
		delay_us(Time_Pulse_Delay_High);
		return tmp;
}
 

what is
DS1822_CONVERT_T_CMD
?
and
DS1822_READ_STRATCHPAD_CMD
?
Can you check my code?
Code:
// Easyrider83's code
           #define Time_Pulse_Delay_Low	        10      //10
#define Time_Pulse_Delay_High	        40      //40
#define Time_Reset_Low			500
#define Time_After_Reset		350
#define Time_Hold_Down			10

#define One_Wire_Read_ROM		0x33
#define One_Wire_Skip_ROM		0xCC
#define One_Wire_Search_ROM		0xF0
#define One_Wire_Match_ROM		0x55

#define One_Wire_Success		0x00
#define One_Wire_Error_No_Echo	        0x01
#define One_Wire_Bus_Low_Error	        0x02
#define One_Wire_Device_Busy	        0x03
#define One_Wire_CRC_Error		0x04
        #define One_Wire_Pin 0
void PIN_ON(int ignoreme)
{   // IS IT OK?                            //
        TRISD = 0xFF;
        PORTD.B2 = 1;
}
void PIN_OFF(int ignoreme)
{     // IS IT OK?
        TRISD = 0xFF;
        PORTD.B2 = 0;
}
void PIN_OUT_OD(int ignoreme)
{     // IS IT OK?
        TRISD = 0x00;
}
int PIN_SYG(int ignoreme)
{    // IS IT OK?
    return PORTD.B2;
}
     unsigned int One_Wire_Reset(void)
{
	unsigned int tmp;
        PIN_ON(One_Wire_Pin);
        PIN_OUT_OD(One_Wire_Pin);
	if ((PIN_SYG(One_Wire_Pin)==0))	return One_Wire_Bus_Low_Error;
        PIN_OFF(One_Wire_Pin);
	delay_us(250);
        delay_us(250);
        PIN_ON(One_Wire_Pin);
	delay_us(Time_Pulse_Delay_High);
	if ((PIN_SYG(One_Wire_Pin))) tmp = One_Wire_Error_No_Echo;
		else tmp = One_Wire_Success;
	delay_us(250);
        delay_us(200);
	return tmp;
}


void One_Wire_Write_Bit (unsigned char Bit)  ;

void One_Wire_Write_Byte(unsigned char Byte)
{
	unsigned char cnt;
	for (cnt=0;cnt!=8;cnt++) One_Wire_Write_Bit(Byte&(1<<cnt));
}

void One_Wire_Write_Bit (unsigned char Bit)
{
        PIN_OFF(One_Wire_Pin);
	if (Bit==0)
	{
		delay_us(Time_Pulse_Delay_High);
		PIN_ON(One_Wire_Pin);
		delay_us(Time_Pulse_Delay_Low);
	}
	else
	{
		delay_us(Time_Pulse_Delay_Low);
		PIN_ON(One_Wire_Pin);
		delay_us(Time_Pulse_Delay_High);
	}
}

unsigned char One_Wire_Read_Bit (void)
{
		unsigned char tmp;
		//PIN_OUT_PP(One_Wire_Pin);
                PIN_OFF(One_Wire_Pin);
		delay_us(Time_Hold_Down);
		PIN_ON(One_Wire_Pin);
		delay_us(Time_Pulse_Delay_Low);
		if ((PIN_SYG(One_Wire_Pin))!=0)	tmp = 1;
			else tmp = 0;
		delay_us(Time_Pulse_Delay_High);
		return tmp;
}
unsigned char One_Wire_Read_Byte(void)
{
	unsigned char tmp=0;
	unsigned char cnt;
	for (cnt=0;cnt!=8;cnt++)
		if (One_Wire_Read_Bit()!=0)	tmp|=(1<<cnt);
	delay_us(Time_Pulse_Delay_High);
	return tmp;
}

unsigned char DS1822_Start_Conversion_Skip_Rom (void)
{
	unsigned char tmp;
	tmp=One_Wire_Reset();
	if (tmp!=One_Wire_Success) return tmp;
	One_Wire_Write_Byte(One_Wire_Skip_ROM);
	One_Wire_Write_Byte(DS1822_CONVERT_T_CMD);
	if (One_Wire_Read_Byte()==0)	return One_Wire_Success;
		else	return One_Wire_Device_Busy;
}

           unsigned char DS1822_Read_Temp_NoCRC_Skip_Rom (unsigned int * temperatura)
{
	unsigned char tmp;
	tmp=One_Wire_Reset();
	if (tmp!=One_Wire_Success) return tmp;
	One_Wire_Write_Byte(One_Wire_Skip_ROM);
	One_Wire_Write_Byte(DS1822_READ_STRATCHPAD_CMD);
	* temperatura = One_Wire_Read_Byte()|(One_Wire_Read_Byte()<<8);
	return One_Wire_Success;
}
 

Simpler MikroC project attached.

Most of the code is for GLCD - what is left is simple use of one-wire library

oops - this is DS1820 code - change resolution to 12 for DS18B20

Code:
const unsigned short TEMP_RESOLUTION = 12;
 

Attachments

  • DS1820.zip
    49.8 KB · Views: 64

Sorry, forgot
Code:
#define DS1822_CONVERT_T_CMD				0x44
#define DS1822_WRITE_STRATCHPAD_CMD			0x4E
#define DS1822_READ_STRATCHPAD_CMD			0xBE
#define DS1822_COPY_STRATCHPAD_CMD			0x48
#define DS1822_RECALL_E_CMD					0xB8
#define DS1822_READ_POWER_SUPPLY_CMD		0xB4

#define DS1822_STRATCHPAD_SIZE				0x09
#define DS1822_SERIAL_NUM_SIZE				0x08

- - - Updated - - -


Fixed something
 
Last edited:

it returns "One_Wire_Error_No_Echo"....
 

Does it give any pulse at all? Can you replace sensor with led? You should see how it blinks.
 

Yes it blinks a bit.
I have no idea what's wrong.
I have also tried several other examples and none of them works.
 

Code:
unsigned char One_Wire_Reset(void)
{
	unsigned char tmp;
        TRISD.B2 = 1; //switch for input
	if (PORTD.B2 == 0)	return One_Wire_Bus_Low_Error;
        TRISD.B2 = 0; //switch for output
        PORTD.B2 = 0; //force to low
	delay_us(500);        
        TRISD.B2 = 1; //switch for input
	delay_us(Time_Pulse_Delay_High);
[COLOR="#00FF00"]	if (PORTD.B2) tmp = One_Wire_Error_No_Echo;[/COLOR]
		else tmp = One_Wire_Success;
	delay_us(450);
	return tmp;
}
One_Wire_Error_No_Echo comes from marked green section. I think that means that delays are working wrong - incorrect oscillator configuration is used.
Try to implement 1s led blinking based on delay_ms(1000) function. Does it blinks each second?
 

Are you 100% sure?

This chip is using USB and USB is working OK.
Can USB work OK with wrong timings?

BTW: I've tested both normal DS18B20 and PAR version, and they don't work. They don't work with your code, don't work with sample code, nor any other code....
\

 

Try to switch off usb temporary. 1-wire communication requere very precicly time slots, which can be extended during interrupt routine being used.
 

Then I'd have no way to communicate out the result, wouldn't I?

But I did something like this:

Code:
main()
{
      --- WAIT A WHILE
     --- READ TEMPERATURE RIDERS METHOD TWICE
     --- INIT USB
      --- SEND DATA

}

but it still's returns that error of yours on in case of other code garbage data - something like 0.00064
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…