Hi, I've a problem with one wire comunication and 7 seg display..
i have EasyPic4 + mkroicd
I must show temperature read from ds1820 into a four display 7 segment..
I have both one wire comunication routine both 7 seg multplexing routing..
i don't know how trasform data from ds1820 to 7 segment format data...
can't Nobody help me?
ds1820 temperature to 7 segment display
Why don't it Work?
I use this code but display show always 0000...
I'need to finish this very simple project...
help me please...
And why icd debugger say me :Debug Error: pc out of scope?
program display3
dim zz, c3,j, v as byte
dim por as byte[8]
dim i,temp,ww as word
const TEMP_RESOLUTION as byte = 9
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
end select 'case end
end sub
sub procedure interrupt
PORTA = 0
PORTD = por[v]
PORTA = zz ' turn on appropriate 7seg. display
Inc(v)
zz = zz >> 1
if zz = 0 then
zz = 8 ' prepare mask for digit
end if
if v > 3 then
v = 0 ' turn on 1st, turn off 2nd 7seg.
end if
TMR0 = 0
INTCON = $20
end sub
main:
OPTION_REG = 0 ' Timer0 settings
j = 0
v = 0
zz = 8
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
TRISE = 0
PORTE = 0
PORTA = 0
i = 1234
while true
Ow_Reset(PORTE,2) ' Onewire reset signal
Ow_Write(PORTE,2,0xCC) ' Issue command SKIP_ROM
Ow_Write(PORTE,2,0x44) ' Issue command CONVERT_T
Delay_us(120)
Ow_Reset(PORTE,2)
Ow_Write(PORTE,2,0xCC) ' Issue command SKIP_ROM
Ow_Write(PORTE,2,0xBE) ' Issue command READ_SCRATCHPAD
Delay_ms(400)
c3 = OW_Read(PORTE,2) ' Get temperature LSB
temp = OW_Read(PORTE,2) ' Get temperature MSB
temp = temp << 8
temp = temp + c3
i=temp
j = i div 1000 ' prepare digits for diplays
por[0] = Mask(j)
j = i div 100 mod 10
por[1] = Mask(j)
j = i div 10 mod 10
por[2] = Mask(j)
j = i mod 10
por[3] = Mask(j)
'Delay_ms(1000)
'Inc(i) ' increment counter
'if i > 9999 then
'i = 0
'end if
wend
end.
I'need to finish this very simple project...
help me please...
And why icd debugger say me :Debug Error: pc out of scope?
program display3
dim zz, c3,j, v as byte
dim por as byte[8]
dim i,temp,ww as word
const TEMP_RESOLUTION as byte = 9
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
end select 'case end
end sub
sub procedure interrupt
PORTA = 0
PORTD = por[v]
PORTA = zz ' turn on appropriate 7seg. display
Inc(v)
zz = zz >> 1
if zz = 0 then
zz = 8 ' prepare mask for digit
end if
if v > 3 then
v = 0 ' turn on 1st, turn off 2nd 7seg.
end if
TMR0 = 0
INTCON = $20
end sub
main:
OPTION_REG = 0 ' Timer0 settings
j = 0
v = 0
zz = 8
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
TRISE = 0
PORTE = 0
PORTA = 0
i = 1234
while true
Ow_Reset(PORTE,2) ' Onewire reset signal
Ow_Write(PORTE,2,0xCC) ' Issue command SKIP_ROM
Ow_Write(PORTE,2,0x44) ' Issue command CONVERT_T
Delay_us(120)
Ow_Reset(PORTE,2)
Ow_Write(PORTE,2,0xCC) ' Issue command SKIP_ROM
Ow_Write(PORTE,2,0xBE) ' Issue command READ_SCRATCHPAD
Delay_ms(400)
c3 = OW_Read(PORTE,2) ' Get temperature LSB
temp = OW_Read(PORTE,2) ' Get temperature MSB
temp = temp << 8
temp = temp + c3
i=temp
j = i div 1000 ' prepare digits for diplays
por[0] = Mask(j)
j = i div 100 mod 10
por[1] = Mask(j)
j = i div 10 mod 10
por[2] = Mask(j)
j = i mod 10
por[3] = Mask(j)
'Delay_ms(1000)
'Inc(i) ' increment counter
'if i > 9999 then
'i = 0
'end if
wend
end.
i don't know
I disabled anlogs inputs and something work .
But pic show a lot of number that are not temperature bytes...
I don't know what data pic displaying...
Here is source that a i use..
program display
dim zz, j,j1,j2, v as byte
dim i,n,temp as word
dim por as byte[4]
dim cc as boolean
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
end select 'case end
end sub
sub procedure interrupt
PORTD = por[v] ' Send the appropriate mask to PORTB
PORTA = zz ' Turn on appropriate 7seg. display
Inc(v)
zz = zz << 1 ' Prepare for next digit
if zz > 8 then
zz = 1
end if
if v > 3 then
v = 0
end if
TMR0 = 0
' Reset timer
INTCON = $20
' Clear TMR0IF and set TMR0IE
end sub
main:
OPTION_REG = 0 '$80
adcon1 = 255
j = 0
v = 0
zz = 1
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
PORTA = 0
while true
ow_reset(PORTA, 5) ' onewire reset signal
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $44) ' issue command to DS1820
delay_us(120)
cc = ow_reset(PORTA, 5)
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $BE) ' issue command to DS1820
j1 = ow_read(PORTA, 5) ' get result
j2 = ow_read(PORTA, 5) ' get result (assuming the temperature is positive)
if j2 = $FF then
'tmp_sign = "-" ' temperature sign
j1= j1 or $FF ' complement of two
j1= j1 + $01
'else
'tmp_sign = "+"
end if
j2 = (j1 and $01) * 5 ' Get decimal value
j1 = j1 >> 1 ' Form the 2byte variable
i= (j1*10) + j2
delay_ms(500)
j = i div 1000 ' prepare digits for diplays
por[3] = Mask(j)
j = i div 100 mod 10
por[2] = Mask(j)
j = i div 10 mod 10
por[1] = Mask(j)
j = i mod 10
por[0] = Mask(j)
wend
But pic show a lot of number that are not temperature bytes...
I don't know what data pic displaying...
Here is source that a i use..
program display
dim zz, j,j1,j2, v as byte
dim i,n,temp as word
dim por as byte[4]
dim cc as boolean
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
end select 'case end
end sub
sub procedure interrupt
PORTD = por[v] ' Send the appropriate mask to PORTB
PORTA = zz ' Turn on appropriate 7seg. display
Inc(v)
zz = zz << 1 ' Prepare for next digit
if zz > 8 then
zz = 1
end if
if v > 3 then
v = 0
end if
TMR0 = 0
' Reset timer
INTCON = $20
' Clear TMR0IF and set TMR0IE
end sub
main:
OPTION_REG = 0 '$80
adcon1 = 255
j = 0
v = 0
zz = 1
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
PORTA = 0
while true
ow_reset(PORTA, 5) ' onewire reset signal
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $44) ' issue command to DS1820
delay_us(120)
cc = ow_reset(PORTA, 5)
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $BE) ' issue command to DS1820
j1 = ow_read(PORTA, 5) ' get result
j2 = ow_read(PORTA, 5) ' get result (assuming the temperature is positive)
if j2 = $FF then
'tmp_sign = "-" ' temperature sign
j1= j1 or $FF ' complement of two
j1= j1 + $01
'else
'tmp_sign = "+"
end if
j2 = (j1 and $01) * 5 ' Get decimal value
j1 = j1 >> 1 ' Form the 2byte variable
i= (j1*10) + j2
delay_ms(500)
j = i div 1000 ' prepare digits for diplays
por[3] = Mask(j)
j = i div 100 mod 10
por[2] = Mask(j)
j = i div 10 mod 10
por[1] = Mask(j)
j = i mod 10
por[0] = Mask(j)
wend
Hi,
You must disable interrupt when use 1-Wire function !!!
You must wait minimum 200 - 500 ms after send convert command $44.
Try this code :
You must disable interrupt when use 1-Wire function !!!
You must wait minimum 200 - 500 ms after send convert command $44.
Try this code :
Code: Select all
program display
dim zz, j,j1,j2, v as byte
dim i,n,temp as word
dim por as byte[4]
dim cc as boolean
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
end select 'case end
end sub
sub procedure interrupt
INTCON.TMR0IF = 0 ' Clear TMR0IF
PORTD = por[v] ' Send the appropriate mask to PORTB
PORTA = zz ' Turn on appropriate 7seg. display
Inc(v)
zz = zz << 1 ' Prepare for next digit
if zz > 8 then
zz = 1
end if
if v > 3 then
v = 0
end if
TMR0 = 0' Reset timer
end sub
main:
OPTION_REG = 0 '$80
adcon1 = 255
j = 0
v = 0
zz = 1
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
PORTA = 0
while true
INTCON.GIE = 0
ow_reset(PORTA, 5) ' onewire reset signal
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $44) ' issue command to DS1820
INTCON.GIE = 1
delay_ms(500) 'wait for conversion complete
INTCON.GIE = 0
cc = ow_reset(PORTA, 5)
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $BE) ' issue command to DS1820
j1 = ow_read(PORTA, 5) ' get result
j2 = ow_read(PORTA, 5) ' get result (assuming the temperature is positive)
INTCON.GIE = 1
if j2 = $FF then
'tmp_sign = "-" ' temperature sign
j1= j1 or $FF ' complement of two
j1= j1 + $01
'else
'tmp_sign = "+"
end if
j2 = (j1 and $01) * 5 ' Get decimal value
j1 = j1 >> 1 ' Form the 2byte variable
i= (j1*10) + j2
delay_ms(500)
j = i div 1000 ' prepare digits for diplays
por[3] = Mask(j)
j = i div 100 mod 10
por[2] = Mask(j)
j = i div 10 mod 10
por[1] = Mask(j)
j = i mod 10
por[0] = Mask(j)
wend
end.
Best regards, Florin Andrei Medrea.
http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/
mail : florin@microelemente.ro
http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/
mail : florin@microelemente.ro
last trick
Your help it was fantastic: thank you so much...
But now i wan't to know the last thing:
Can I remove display blinking? If yes, what parameter i must adjust?
And, Why there is a shadow on every 7 segment display?
Torn off the light and look with attection all 4 displays (7 segment)...
IE : if display show 125, you can see , on 3th display the decimal number "5" ... back of number "1" you can note number"2",back of ...
Here there my code...
program display
dim zz, j,j1,j2,j3,js, v as byte
dim i as word
dim por as byte[4]
dim cc as boolean
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
case $A result = $40
case $B result = 0
end select 'case end
end sub
sub procedure interrupt
INTCON.TMR0IF = 0 ' Clear TMR0IF
PORTD = por[v] ' Send the appropriate mask to PORTB
PORTA = zz ' Turn on appropriate 7seg. display
Inc(v)
zz = zz << 1 ' Prepare for next digit
if zz > 8 then
zz = 1
end if
if v > 3 then
v = 0
end if
TMR0 = 0' Reset timer
end sub
main:
OPTION_REG = 0 '$80
adcon1 = 255
j = 9999
v = 0
zz = 1
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
PORTA = 0
while true
INTCON.GIE = 0
ow_reset(PORTA, 5) ' onewire reset signal
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $44) ' issue command to DS1820
INTCON.GIE = 1
delay_ms(1000) 'wait for conversion complete
INTCON.GIE = 0
cc = ow_reset(PORTA, 5)
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $BE) ' issue command to DS1820
j1 = ow_read(PORTA, 5) ' get result
j2 = ow_read(PORTA, 5) ' get result (assuming the temperature is positive)
if j2 = $FF then
js = $a ' temperature sign
j3= 0 - j1 ' convert byte from negative to positive
i= (j3*10) div 2 'format temperature on right value
else
js = $b ' temperature sign
j2 = (j1 and $01) * 5 ' Get decimal value
j1 = j1 >> 1 ' Form the 2byte variable
i= (j1*10) + j2
end if
INTCON.GIE = 1
'delay_ms(500)
por[3] = Mask(js)
j = i div 100 mod 10
por[2] = Mask(j)
j = i div 10 mod 10
por[1] = Mask(j)
j = i mod 10
por[0] = Mask(j)
wend
end.
But now i wan't to know the last thing:
Can I remove display blinking? If yes, what parameter i must adjust?
And, Why there is a shadow on every 7 segment display?
Torn off the light and look with attection all 4 displays (7 segment)...
IE : if display show 125, you can see , on 3th display the decimal number "5" ... back of number "1" you can note number"2",back of ...
Here there my code...
program display
dim zz, j,j1,j2,j3,js, v as byte
dim i as word
dim por as byte[4]
dim cc as boolean
sub function Mask(dim num as byte) as byte ' this function returns masks
select case num ' for common cathode 7-seg. display
case 0 result = $3F
case 1 result = $06
case 2 result = $5B
case 3 result = $4F
case 4 result = $66
case 5 result = $6D
case 6 result = $7D
case 7 result = $07
case 8 result = $7F
case 9 result = $6F
case $A result = $40
case $B result = 0
end select 'case end
end sub
sub procedure interrupt
INTCON.TMR0IF = 0 ' Clear TMR0IF
PORTD = por[v] ' Send the appropriate mask to PORTB
PORTA = zz ' Turn on appropriate 7seg. display
Inc(v)
zz = zz << 1 ' Prepare for next digit
if zz > 8 then
zz = 1
end if
if v > 3 then
v = 0
end if
TMR0 = 0' Reset timer
end sub
main:
OPTION_REG = 0 '$80
adcon1 = 255
j = 9999
v = 0
zz = 1
TMR0 = 0
INTCON = $A0 ' Disable PEIE,INTE,RBIE,T0IE
TRISA = 0
TRISD = 0
PORTD = 0
PORTA = 0
while true
INTCON.GIE = 0
ow_reset(PORTA, 5) ' onewire reset signal
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $44) ' issue command to DS1820
INTCON.GIE = 1
delay_ms(1000) 'wait for conversion complete
INTCON.GIE = 0
cc = ow_reset(PORTA, 5)
ow_write(PORTA, 5, $CC) ' issue command to DS1820
ow_write(PORTA, 5, $BE) ' issue command to DS1820
j1 = ow_read(PORTA, 5) ' get result
j2 = ow_read(PORTA, 5) ' get result (assuming the temperature is positive)
if j2 = $FF then
js = $a ' temperature sign
j3= 0 - j1 ' convert byte from negative to positive
i= (j3*10) div 2 'format temperature on right value
else
js = $b ' temperature sign
j2 = (j1 and $01) * 5 ' Get decimal value
j1 = j1 >> 1 ' Form the 2byte variable
i= (j1*10) + j2
end if
INTCON.GIE = 1
'delay_ms(500)
por[3] = Mask(js)
j = i div 100 mod 10
por[2] = Mask(j)
j = i div 10 mod 10
por[1] = Mask(j)
j = i mod 10
por[0] = Mask(j)
wend
end.
Re: ds1820 temperature to 7 segment display
Hello Everybody,
I am almost new in program and I tried to use the given code on EasyPic4 with 16F877A 8MHz Xstal and a DS1820, however the given code doesn't work.
I have find a working code with LCD but no one with 7 seg. display. By merging 2 working codes I have created the below code with MicroC which is the translated version of Microbasic and its doesn't work .
This project should be an easy task but actually it make me crazy! perhaps the interrupt routine cause the mising reads of sensor value.
Is there someone able to help me?
/*
* Project name: Digital termometer on 4x 7seg. display
Onewire_Test (Interfacing the DS18x20 temperature sensor - all versions)
* Description:
After reset, PIC reads temperature from the sensor and shows on display
The display format of the temperature is 'xxx.xC'.
To obtain correct results, the 18x20's temperature resolution has to be adjusted
(constant TEMP_RESOLUTION)
* Test configuration:
MCU: PIC16F877A
Dev.Board: EasyPIC4 -
Oscillator: HS, 08.0000 MHz
Ext. Modules: DS18x20 connected to RE2 pin, 4x 7seg DSP
SW: mikroC v6.0.0
* NOTES:
- JP24 su N.C., SW2 PORTA/E OFF, Pull up and turning off diode on pin used for one wire bus may be required
(in this example PORTE)
Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:
18S20: 9 (default setting; can be 9,10,11,or 12)
18B20: 12
*/
// prova modifica da LCD a 7seg . segna 00.0
const unsigned short TEMP_RESOLUTION = 9; // 9 x DS1820, DS18S20; 12 per DS18B20
unsigned temp;
unsigned short Tdigit0, Tdigit1, Tdigit2, Tdigit3; // 0 a DX
unsigned int digit, temp_whole, temp_fraction, temp_value;
unsigned short TempH, TempL ;
signed int tempinC;
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned short shifter, portd_index;
unsigned short portd_array[4];
void interrupt() {
PORTA = 0; // Turn off all 7seg displays
PORTD = portd_array[portd_index]; // bring appropriate value to PORTD
PORTA = shifter; // turn on appropriate 7seg. display
// move shifter to next digit
shifter <<= 1;
if (shifter > 8u)
shifter = 1;
// increment portd_index
portd_index++ ;
if (portd_index > 3u)
portd_index = 0; // turn on 1st, turn off 2nd 7seg.
TMR0IF_bit = 0;
TMR0 = 236;
}
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F; // 0
case 1 : return 0x06; // 1
case 2 : return 0x5B; // 2
case 3 : return 0x4F; // 3
case 4 : return 0x66; // 4
case 5 : return 0x6D; // 5
case 6 : return 0x7D; // 6
case 7 : return 0x07; // 7
case 8 : return 0x7F; // 8
case 9 : return 0x6F; // 9
case 10: return 0x40; // -
case 11: return 0x00; // blank
case 12: return 0x61; // c high position
case 13: return 0x80; // dp .
} //case end
}
void Display_Temperature()
{
//--- perform temperature reading
INTCON.GIE = 0; // need to stop interrupt
Ow_Reset(&PORTE,2); // Onewire reset signal
Ow_Write(&PORTE,2,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTE,2,0x44); // Issue command CONVERT_T
INTCON.GIE = 1; // need to start interrupt
Delay_ms(100);
INTCON.GIE = 0; // need to stop interrupt
Ow_Reset(&PORTE,2);
Ow_Write(&PORTE,2,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTE,2,0xBE); // Issue command READ_SCRATCHPAD
tempL = Ow_Read(&PORTE,2);
tempH = Ow_Read(&PORTE,2);
temp_value= (TempH << + tempL; //
// check if temperature is negative
if (temp_value & 0x8000) //temp2write
{
Tdigit3 = 10; // menus sign
temp_value = ~temp_value + 1;
}
else
Tdigit3 = 11; // blank digit
// extract temp_whole
temp_whole = temp_value >> RES_SHIFT ;
if (temp_value & 0x0001) {
temp_fraction = 5;
}
else temp_fraction = 0;
tempinC =temp_whole *10+ temp_fraction;
// convert temp_whole to characters
//if (temp_whole/100)
Tdigit2 = (tempinC/100)%10;
Tdigit1 = (tempinC/10)%10;
Tdigit0 = tempinC%10;
//Tdigit2 = 3; //this work
//Tdigit1 = 2; //this work
//Tdigit0 = 5; //this work
// show temperature: 32.5
INTCON.GIE = 1;
portd_array[0] = mask(Tdigit0); // fraction
portd_array[1] = mask(Tdigit1)+ mask(13); //unit
portd_array[2] = mask(Tdigit2) ; // tens
portd_array[3] = mask(Tdigit3); // blank or -
}
void main()
{
ADCON1 = 0; // Set AN pins to Digital I/O;
TRISA = 0; // Configure PORTA as output
PORTA = 0; // Clear PORTA
TRISD = 0; // Configure PORTD as output
PORTD = 0; // Clear PORTD
OPTION_REG = 0x88; // 1usec
TMR0 = 236; // 1usec
INTCON = 0xA0;
digit = 0;
portd_index = 0;
shifter = 1;
GIE_bit = 1;
TMR0IE_bit = 1;
//--- main loop
while (1)
{
Display_Temperature();
}
}
I am almost new in program and I tried to use the given code on EasyPic4 with 16F877A 8MHz Xstal and a DS1820, however the given code doesn't work.
I have find a working code with LCD but no one with 7 seg. display. By merging 2 working codes I have created the below code with MicroC which is the translated version of Microbasic and its doesn't work .
This project should be an easy task but actually it make me crazy! perhaps the interrupt routine cause the mising reads of sensor value.
Is there someone able to help me?
/*
* Project name: Digital termometer on 4x 7seg. display
Onewire_Test (Interfacing the DS18x20 temperature sensor - all versions)
* Description:
After reset, PIC reads temperature from the sensor and shows on display
The display format of the temperature is 'xxx.xC'.
To obtain correct results, the 18x20's temperature resolution has to be adjusted
(constant TEMP_RESOLUTION)
* Test configuration:
MCU: PIC16F877A
Dev.Board: EasyPIC4 -
Oscillator: HS, 08.0000 MHz
Ext. Modules: DS18x20 connected to RE2 pin, 4x 7seg DSP
SW: mikroC v6.0.0
* NOTES:
- JP24 su N.C., SW2 PORTA/E OFF, Pull up and turning off diode on pin used for one wire bus may be required
(in this example PORTE)
Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:
18S20: 9 (default setting; can be 9,10,11,or 12)
18B20: 12
*/
// prova modifica da LCD a 7seg . segna 00.0
const unsigned short TEMP_RESOLUTION = 9; // 9 x DS1820, DS18S20; 12 per DS18B20
unsigned temp;
unsigned short Tdigit0, Tdigit1, Tdigit2, Tdigit3; // 0 a DX
unsigned int digit, temp_whole, temp_fraction, temp_value;
unsigned short TempH, TempL ;
signed int tempinC;
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned short shifter, portd_index;
unsigned short portd_array[4];
void interrupt() {
PORTA = 0; // Turn off all 7seg displays
PORTD = portd_array[portd_index]; // bring appropriate value to PORTD
PORTA = shifter; // turn on appropriate 7seg. display
// move shifter to next digit
shifter <<= 1;
if (shifter > 8u)
shifter = 1;
// increment portd_index
portd_index++ ;
if (portd_index > 3u)
portd_index = 0; // turn on 1st, turn off 2nd 7seg.
TMR0IF_bit = 0;
TMR0 = 236;
}
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0x3F; // 0
case 1 : return 0x06; // 1
case 2 : return 0x5B; // 2
case 3 : return 0x4F; // 3
case 4 : return 0x66; // 4
case 5 : return 0x6D; // 5
case 6 : return 0x7D; // 6
case 7 : return 0x07; // 7
case 8 : return 0x7F; // 8
case 9 : return 0x6F; // 9
case 10: return 0x40; // -
case 11: return 0x00; // blank
case 12: return 0x61; // c high position
case 13: return 0x80; // dp .
} //case end
}
void Display_Temperature()
{
//--- perform temperature reading
INTCON.GIE = 0; // need to stop interrupt
Ow_Reset(&PORTE,2); // Onewire reset signal
Ow_Write(&PORTE,2,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTE,2,0x44); // Issue command CONVERT_T
INTCON.GIE = 1; // need to start interrupt
Delay_ms(100);
INTCON.GIE = 0; // need to stop interrupt
Ow_Reset(&PORTE,2);
Ow_Write(&PORTE,2,0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTE,2,0xBE); // Issue command READ_SCRATCHPAD
tempL = Ow_Read(&PORTE,2);
tempH = Ow_Read(&PORTE,2);
temp_value= (TempH << + tempL; //
// check if temperature is negative
if (temp_value & 0x8000) //temp2write
{
Tdigit3 = 10; // menus sign
temp_value = ~temp_value + 1;
}
else
Tdigit3 = 11; // blank digit
// extract temp_whole
temp_whole = temp_value >> RES_SHIFT ;
if (temp_value & 0x0001) {
temp_fraction = 5;
}
else temp_fraction = 0;
tempinC =temp_whole *10+ temp_fraction;
// convert temp_whole to characters
//if (temp_whole/100)
Tdigit2 = (tempinC/100)%10;
Tdigit1 = (tempinC/10)%10;
Tdigit0 = tempinC%10;
//Tdigit2 = 3; //this work
//Tdigit1 = 2; //this work
//Tdigit0 = 5; //this work
// show temperature: 32.5
INTCON.GIE = 1;
portd_array[0] = mask(Tdigit0); // fraction
portd_array[1] = mask(Tdigit1)+ mask(13); //unit
portd_array[2] = mask(Tdigit2) ; // tens
portd_array[3] = mask(Tdigit3); // blank or -
}
void main()
{
ADCON1 = 0; // Set AN pins to Digital I/O;
TRISA = 0; // Configure PORTA as output
PORTA = 0; // Clear PORTA
TRISD = 0; // Configure PORTD as output
PORTD = 0; // Clear PORTD
OPTION_REG = 0x88; // 1usec
TMR0 = 236; // 1usec
INTCON = 0xA0;
digit = 0;
portd_index = 0;
shifter = 1;
GIE_bit = 1;
TMR0IE_bit = 1;
//--- main loop
while (1)
{
Display_Temperature();
}
}