EmbeddedRelated.com
Forums
Memfault Beyond the Launch

lpc2138 + DS18b20

Started by ziya_erdemir December 16, 2009
I am newbie on lpc21xx and have a problem with delay function (I have uploaded the compressed code into Files area of the list, http://tech.groups.yahoo.com/group/lpc2000/files/Temporary/06_ds18x20.rar)

My problem is:
Attached LPC2138+DS18b20 code reads -0.5 oC from the DS18b20 (Schematics of the board I used is shown in Proteus ISIS model DS18B20.DSN, btw, isis can not simulate it). Program should read initially 85 oC at initial run, and should read environment temperature approximately 24 oC).

DS18b20 power pin at Vcc (5 V), single drop.

LPC2138 clock frequency: 12 MHz crystal, with PLL x5 60 MHz, Peripheral 15 MHz.

UART 0 boud rate: 4800 bps.

Compiler: Keil uVision4

delay_us () function in the delay.h adds extra 4 us, so in the onewire read and write functions I used timer1 and M1, M2, and M3 match register of lpc2138 to get more precise time periods.

Can anyone help me to find the problem?

Regards

Ziya

An Engineer's Guide to the LPC2100 Series

in 1wire.h, read function is:

#define Presc 15
...
//-------------------------- 16 bit read ----------------------------

short int onewire_read(short int bayt) // 6, 9, 55
{
short int count, data, bits;
bits = bayt * 8;
#define AA 2
#define EE 9
#define FF 120
#define M0_i 1 // Bit <2:0> i = interrupt
#define M1_i 1<<3 // Bit <5:3> r = reset
#define M2_irs 7<<6 // Bit <8:6> s = stop
T1PR = Presc; // Prescale 15 60 MHz CClock, 15 MHz PCOLCK
T1MR0 = AA; // Wait this long
T1MR1 = AA+EE; // Wait this long
T1MR2 = AA+EE+FF ; // Wait this long
T1MCR = M0_i | M1_i | M2_irs; // Interrupt,stop and reset

T1TCR = 0x02; // Reset timer1
data = 0;
for (count=0; count {
data >>=1;
output_low();
T1TCR = 0x01; // timer1 starts
while(!(T1IR & 1)); // Wait for int flag
output_float(); // now let 1-wire float (high by pullup resistor)
while(!(T1IR & 2)); // Wait for int flag for master sampling
if( input() != 0 ) {data |= 0x8000;}
while(!(T1IR & 4)); // Wait for int flag

T1IR = T1IR; //0x07; // Clear M2, M1, M0 interrupts
}
return( data );
}

Is the any improper code order in this function that cause problems e.g. rmw (read, modify, write), ... Or should I seek the source in another place such as Startup.S.

Ziya

--- In l..., "ziya_erdemir" wrote:
> I am newbie on lpc21xx and have a problem with delay function (I have uploaded the compressed code into Files area of the list, http://tech.groups.yahoo.com/group/lpc2000/files/Temporary/06_ds18x20.rar)
>
> My problem is:
> Attached LPC2138+DS18b20 code reads -0.5 oC from the DS18b20 (Schematics of the board I used is shown in Proteus ISIS model DS18B20.DSN, btw, isis can not simulate it). Program should read initially 85 oC at initial run, and should read environment temperature approximately 24 oC).
>
> DS18b20 power pin at Vcc (5 V), single drop.
>
> LPC2138 clock frequency: 12 MHz crystal, with PLL x5 60 MHz, Peripheral 15 MHz.
>
> UART 0 boud rate: 4800 bps.
>
> Compiler: Keil uVision4
>
> delay_us () function in the delay.h adds extra 4 us, so in the onewire read and write functions I used timer1 and M1, M2, and M3 match register of lpc2138 to get more precise time periods.
>
> Can anyone help me to find the problem?
>
> Regards
>
> Ziya
>

Dear Ziya,

Here you can find a sample code written for DS1820 for LPC2106 in C:
http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/

Also may be it will be better to disable all the interrupts during accessing the one-wire bus and adjusting the necessary delays with NOPs, instead of timers. Then analyse the pulse durations with an oscilloscope to meet the timing requirements.

Hope this help,

Ertan

_________________________________________________________________
Your E-mail and More On-the-Go. Get Windows Live Hotmail Free.
http://clk.atdmt.com/GBL/go/171222985/direct/01/
Dear Ertan,

thank for your reply. I am new on ARM7 and if I understand correctly, I didn't activate any interrupts and write ISR, just enabled the timer1 match registers interrupt to poll their ie flags.

The link you have given is written with WinARM and I use Keil MDK4. At this moment it is more difficult for me to convert its syntax to Keil.

In the files area, there is a software delay routin and delay loop is written with assembly. Keil didn't like this form :)
static __inline__ void Delay4(uint32_t loops)
{
asm volatile
( \
"\n\t" \
"LOOP_%=: \n\t" \
"subs %0, %0, #1 @ 1 cycle \n\t" \
"bne LOOP_%= @ 3 cycles (true), 1 cycle (false) \n\t" \
"\n\t" \
: "=r" (loops) \
: "0" (loops) \
: "cc" \
);
}

Regards,,

Ziya
--- In l..., ertan balaban wrote:
> Dear Ziya,
>
> Here you can find a sample code written for DS1820 for LPC2106 in C:
> http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/
>
> Also may be it will be better to disable all the interrupts during accessing the one-wire bus and adjusting the necessary delays with NOPs, instead of timers. Then analyse the pulse durations with an oscilloscope to meet the timing requirements.
>
> Hope this help,
>
> Ertan
>
> _________________________________________________________________
> Your E-mail and More On-the-Go. Get Windows Live Hotmail Free.
> http://clk.atdmt.com/GBL/go/171222985/direct/01/
>

Dear Ziya,
if the 'bayt' has a different value other than 2 then this statement will produce a wrong value:
if( input() != 0 ) {data |= 0x8000;}

Think of that if bayt = 3 you must or-logic the the 'data' variable with 0x800000 instead of 0x8000.
And also when you read a 'zero' from the sensor you must shift it into the 'data' variable.
So you should change this part as follows:

data = 0;
for (count=0; count {
data = data << 1;
output_low();
T1TCR = 0x01; // timer1 starts
while(!(T1IR & 1)); // Wait for int flag
output_float(); // now let 1-wire float (high by pullup resistor)
while(!(T1IR & 2)); // Wait for int flag for master sampling
if( input() )
data = data | 1;
else
data = data & 0xFFFE; //shift the zero input

while(!(T1IR & 4)); // Wait for int flag
T1IR = T1IR; //0x07; // Clear M2, M1, M0 interrupts
}
return( data );

After burning your code into flash, check the timing of the pulses with an oscilloscope. To verify the timing requirements.

regards,

Ertan

To: l...
From: z...@ttnet.net.tr
Date: Thu, 17 Dec 2009 09:14:55 +0000
Subject: [lpc2000] Re: lpc2138 + DS18b20

Dear Ertan,

thank for your reply. I am new on ARM7 and if I understand correctly, I didn't activate any interrupts and write ISR, just enabled the timer1 match registers interrupt to poll their ie flags.

The link you have given is written with WinARM and I use Keil MDK4. At this moment it is more difficult for me to convert its syntax to Keil.

In the files area, there is a software delay routin and delay loop is written with assembly. Keil didn't like this form :)

static __inline__ void Delay4(uint32_t loops)

{

asm volatile

( \

"\n\t" \

"LOOP_%=: \n\t" \

"subs %0, %0, #1 @ 1 cycle \n\t" \

"bne LOOP_%= @ 3 cycles (true), 1 cycle (false) \n\t" \

"\n\t" \

: "=r" (loops) \

: "0" (loops) \

: "cc" \

);

}

Regards,,

Ziya

--- In l..., ertan balaban wrote:

>

>

> Dear Ziya,

>

> Here you can find a sample code written for DS1820 for LPC2106 in C:

> http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/

>

> Also may be it will be better to disable all the interrupts during accessing the one-wire bus and adjusting the necessary delays with NOPs, instead of timers. Then analyse the pulse durations with an oscilloscope to meet the timing requirements.

>

> Hope this help,

>

> Ertan

>

> __________________________________________________________

> Your E-mail and More On-the-Go. Get Windows Live Hotmail Free.

> http://clk.atdmt.com/GBL/go/171222985/direct/01/

>

_________________________________________________________________
Hotmail: Trusted email with powerful SPAM protection.
http://clk.atdmt.com/GBL/go/177141665/direct/01/
Dear Ertan,

variable bayt will be 1 or 2 depending on how many bytes (1 or 2) I want to get. if I prefer 1 bayt transfer, then the transferred byte will be placed at MSB of 16 bit variable data.

Your modification reverses the transfer order. DS18B20 data transfer is bigendian (LSbit and LSByte must be transferred first).

I am not sure if I have problem with circuit design. DS18B20 is powered by 5V, lpc21380 is powered by 3.3V and there is 10k pullup (to 5V) resistor at dataline. In datasheet pull up resistor is shown as 4.7k for multidrop connection. Code works with Pic16F877A.

Thanks and regards,

Ziya

PS: Ankaradayim. Siz?

--- In l..., ertan balaban wrote:
> Dear Ziya,
> if the 'bayt' has a different value other than 2 then this statement will produce a wrong value:
> if( input() != 0 ) {data |= 0x8000;}
>
> Think of that if bayt = 3 you must or-logic the the 'data' variable with 0x800000 instead of 0x8000.
> And also when you read a 'zero' from the sensor you must shift it into the 'data' variable.
> So you should change this part as follows:
>
> data = 0;
> for (count=0; count > {
> data = data << 1;
> output_low();
> T1TCR = 0x01; // timer1 starts
> while(!(T1IR & 1)); // Wait for int flag
> output_float(); // now let 1-wire float (high by pullup resistor)
> while(!(T1IR & 2)); // Wait for int flag for master sampling
> if( input() )
> data = data | 1;
> else
> data = data & 0xFFFE; //shift the zero input
>
> while(!(T1IR & 4)); // Wait for int flag
> T1IR = T1IR; //0x07; // Clear M2, M1, M0 interrupts
> }
> return( data );
>
> After burning your code into flash, check the timing of the pulses with an oscilloscope. To verify the timing requirements.
>
> regards,
>
> Ertan
>

Dear Ertan,

problem has been solved. Now code works as expected (only one new bug raised). I uploaded to the group file area:
http://tech.groups.yahoo.com/group/lpc2000/files/lpc2138_ds18x20.rar

for() loop was stupidly modified from a while loop while coding, so index increment remained as before whic was not correct. ++count changed to count++ :)

I simplified read and write routines for one byte reading and writing. Now, previously working reset function doesn't detect presence signal, however resets ds18b20.

I don't like interrupt routines very much. But instead, hardware interrupt flags are very useful for me to poll, doing so multiple hardware task can be initiated simultaneously. Bad habit remained from 16f... coding.

Best regards,

Ziya

--- In l..., "ziya_erdemir" wrote:
>
> Dear Ertan,
>
> thank for your reply. I am new on ARM7 and if I understand correctly, I didn't activate any interrupts and write ISR, just enabled the timer1 match registers interrupt to poll their ie flags.


Memfault Beyond the Launch