Page 1 of 1
PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 04 Aug 2010 16:00
by ducu
Hello people,
After I set up the LCD temperature display, I want to show temperature on the digits (7 segments) in this method (00,0C). I am using the MCU P16F628A, temperature sensor DS18B20 and 4 digit (7 segment) with common cathode. I read different documents and I noticed that we need to use interrupts so will take it easy.
Now can anyone help me getting the program from MikroBasic to MikroC. I started to learn MikroC language and it is easier to understand.
Code: Select all
SW:MikroBasic
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.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 04 Aug 2010 16:29
by underworldman
MikroBasic is still a prog language, so just as you learnt it, you'll have to learn MikroC as well. Its very easy when you start writing small programs. But i belive if you ever coded in C (which anyone in world know), you will easily know it. Thanks.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 04 Aug 2010 16:36
by braus
Hello ducu. In order to get your project working you have to have clear two things it will based on;
1- Controlling at least three 7 seven digits using multiplexing method and
2- To stablish a communication between the PIC MCU and temperature sensor.
I understand you are beginner in C language programming but I can tell you that the language is not as important as the programmer analizes and understands how he/she is going to implement the solution. I can tell you that you can find at least one example of these terms in mikroC manual, only thing you have to do is to integrate them according your needs.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 05 Aug 2010 12:16
by tihomir.losic
ducu wrote:Now can anyone help me getting the program from MikroBasic to MikroC. I started to learn MikroC language and it is easier to understand.
Hello,
here is your code converted to
mikroC PRO for PIC.
I hope that it will help you.
Code: Select all
unsigned char zz, j, j1, j2, v, result;
unsigned int i, n, temp;
char por[4];
unsigned cc;
char Mask(unsigned char num) { // this function returns masks
switch (result)
{ // for common cathode 7-seg. display
case 0: result = 0x3F;
case 1: result = 0x06;
case 2: result = 0x5B;
case 3: result = 0x4F;
case 4: result = 0x66;
case 5: result = 0x6D;
case 6: result = 0x7D;
case 7: result = 0x07;
case 8: result = 0x7F;
case 9: result = 0x6F;
}
}
void interrupt(){
INTCON = 0; // Clear TMR0IF
PORTB = por[v]; // Send the appropriate mask to PORTB
PORTA = zz; // Turn on appropriate 7seg. display
v++;
zz = zz << 1; // Prepare for next digit
if (zz > 8)
zz = 1;
else if (v > 3)
v = 0;
TMR0 = 0; // Reset timer
}
void main(){
OPTION_REG = 0; // 0x80
CMCON = 0x07;
j = 0;
v = 0;
zz = 1;
TMR0 = 0;
INTCON = 0xA0; // Disable PEIE,INTE,RBIE,T0IE
TRISA = 0;
TRISB = 0;
PORTB = 0;
PORTA = 0;
while(1){
INTCON.GIE = 0;
Ow_Reset(PORTA, 5); // One wire reset signal
Ow_Write(PORTA, 5, 0xCC); // Issue command to DS1820
Ow_Write(PORTA, 5, 0x44); // 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, 0xCC); // Issue command to DS1820
Ow_Write(PORTA, 5, 0xBE); // 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 = 0xFF)
j1 = j1 | 0xFF; // Complement of two
j1 = j1 + 1;
j2 = ((j1 & 0x01) * 5); // Get decimal value
j1 = j1 >> 1; // Form the 2byte variable
i = ((j1*10) + j2);
delay_ms(500);
j = i / 1000; // Prepare digits for diplays
por[3] = Mask(j);
j = i / 100 % 10;
por[2] = Mask(j);
j = i / 10 % 10;
por[1] = Mask(j);
j = i % 10;
por[0] = Mask(j);
}
}
Best regards,
Losic Tihomir
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 05 Aug 2010 20:01
by ducu
Thanks for advices, braus and underworldman.
Mr.
tihomir.losic, thank you for the program, it's a very good way to continue my research.
EDIT:
Now, I have made some research and I create this code:
Code: Select all
/*
'*******************************************************************************
' Description:
The temperature most be displayed on the digits (7 segments) in this method (00,0C)
' Test configuration:
' MCU: PIC16F628A
' Configuration Word
' Oscillator: INTOSC:I/O on RA.6, I/O on RA.7
' Watchdog Timer: OFF
' Power up Timer: Disabled
' Master Clear Enable: Enabled
' Browun Out Detect: Enabled
' Low Voltage Program: Disabled
' Data EE Read Protect: Disabled
' Code Protect: OFF
'*******************************************************************************
*/
//***********Declared mask*************/
unsigned short mask(unsigned short num){
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
}
}
/*******Endless mask***********/
unsigned short shifter, portb_index;
unsigned short portb_array[4];
unsigned char digit, J1, J2;
unsigned int value;
unsigned cc;
void interrupt()
{
PORTA = 0; // Turn off all 7seg. displays;
PORTB = portb_array[portb_index]; // Bring appropriate value to PORTB;
PORTA = shifter; // Turn on appropriate 7seg. display;
//move shifter to next digit;
shifter <<= 1;
if(shifter > 8u)
shifter = 1;
//increment portb_index;
portb_index ++ ;
if (portb_index > 3u)
portb_index = 0; //turn on 1st, turn off 2nd 7 seg.;
TMR0 = 0; //reset TIMER0 value;
INTCON = 0x20; //clear T0IF, Bit T0IF=0, T0IE=1;
}
void main()
{
CMCON |= 7; // Set AN pins to Digital I/O;
OPTION_REG = 0x80; // Set timer TMR0;
digit = 0;
portb_index = 0;
shifter = 1;
TMR0 = 0;
INTCON = 0xA0; // Disable interrupt PEIE,INTE,RBIE,T0IE
PORTA = 0; // Turn off both displays
TRISA = 0; // All port A pins are configured as outputs
PORTB = 0; // Turn off all display segments
TRISB = 0; // All port D pins are configured as outputs
while(1) {
INTCON.GIE = 0; //Disable interrupt;
Ow_Reset (PORTA, 4); //one wire reset signal;
Ow_Write (PORTA, 4, 0xCC); //Issue command to DS18B20;
Ow_Write (PORTA, 4, 0X44); //Issue command to DS18B20;
INTCON.GIE = 1; //Enable interrupt;
Delay_ms(500); //Wait for conversion complete;
INTCON.GIE = 0; //Disable interrupt;
CC = Ow_Reset(PORTA ,4);
Ow_Write(PORTA, 4, 0XCC); //Issue command to DS18B20;
Ow_Write(PORTA, 4, 0XBE); //Issue command to DS18B20;
J1 = Ow_Read(PORTA ,4); //Get result;
J2 = Ow_Read(PORTA ,4); //Get result (assuming the temperature is positive);
INTCON.GIE = 1; //Enable interrupt;
if(J2 = 0xFF)
J1 = J1 | 0XFF; //Complement of two;
J1 = J1 + 1;
J2 = ((J1 & 0x01)* 5); //Get decimal value;
J1 = J1 >> 1; //From the 2byte variable;
value = ((J1*10) + J2);
Delay_ms(500);
//Prepare digits for display;
digit = value % 10u; //extract ones digit;
portb_array[0] = mask(digit); //and store it to PORTB array;
digit = (value / 10u) % 10u; //extract tens digit;
portb_array[1] = mask(digit); //and store it to PORTB array;
digit = (value / 100u) % 10u; //extract hundreds digit;
portb_array[2] = mask(digit); //and store it to PORTB array;
digit = value / 1000u; //extract thousands digit;
portb_array[3] = mask(digit); //and store it to PORTB array;
Delay_ms(500); // 0,5s delay;
}
}
I got a build succeded and on 7-segment display goes blank, but I am still optimistic that someone can give me a helping hand, to solve the issue.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 08 Aug 2010 03:47
by MR2010
try this code get your 7seg working 1st then do your next jib, hope this helps
Code: Select all
//Display_utils.h /// header file
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 63;
case 1 : return 6;
case 2 : return 91;
case 3 : return 79;
case 4 : return 102;
case 5 : return 109;
case 6 : return 125;
case 7 : return 7;
case 8 : return 127;
case 9 : return 111;
}
}
Code: Select all
#include "Display_utils.h"
unsigned short dcurr,digitt[4],digit;
unsigned int i;
int temp;
void interrupt() {
if(INTCON.T0IF)
{
dcurr++;
PORTB = digitt[dcurr];
PORTA <<=1;
}
if(dcurr >= 4)
{
PORTB= digitt[0];
PORTA=0b00000001 ;
dcurr = 0 ;
}
TMR0 = 0;
INTCON = 0x20;
}
void main() {
OPTION_REG = 0x80;
CMCON |= 7;
TRISA=0x00;
TRISB=0x00;
i =0000;
do {
i++;
digit = i % 10u;
digitt[0] = mask(digit);
digit = (i / 10u)%10u;
digitt[1] = mask(digit);
digit = (i / 100u) % 10u;
digitt[2] = mask(digit);
digit = i /1000u;
digitt[3] = mask(digit);
delay_ms(200);
if (i ==9999)i = 0000;
} while (1);
}
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 08 Aug 2010 15:34
by ducu
Thanks a lot MR2010, I've tested my code before placing the sensor reading, so I made count to 9999, and work flawlessly. We made modifications for the sensor and displaying on digits and here I am at this moment, but the display staying blank.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 08 Aug 2010 23:36
by MR2010
yw ducu, 1st check ur sensor and try to use portb and ur code to read from OW to portb use LEDS to see if there any data coming out from the sensor i never used it but just test everythings and, try to put ur sensor code out of the main loop,and i think GIE is cuzing troubles try to check it ,
ex:
Code: Select all
/*
'*******************************************************************************
' Description:
The temperature most be displayed on the digits (7 segments) in this method (00,0C)
' Test configuration:
' MCU: PIC16F628A
' Configuration Word
' Oscillator: INTOSC:I/O on RA.6, I/O on RA.7
' Watchdog Timer: OFF
' Power up Timer: Disabled
' Master Clear Enable: Enabled
' Browun Out Detect: Enabled
' Low Voltage Program: Disabled
' Data EE Read Protect: Disabled
' Code Protect: OFF
'*******************************************************************************
*/
//***********Declared mask*************/
unsigned short mask(unsigned short num){
switch (num) {
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
}
}
/*******Endless mask***********/
unsigned short shifter, portb_index;
unsigned short portb_array[4];
unsigned char digit, J1, J2;
unsigned int value;
unsigned cc; correct this ????????????????????
void interrupt()
{
PORTA = 0; // Turn off all 7seg. displays;
PORTB = portb_array[portb_index]; // Bring appropriate value to PORTB;
PORTA = shifter; // Turn on appropriate 7seg. display;
//move shifter to next digit;
shifter <<= 1;
if(shifter > 8u)
shifter = 1;
//increment portb_index;
portb_index ++ ;
if (portb_index > 3u)
portb_index = 0; //turn on 1st, turn off 2nd 7 seg.;
TMR0 = 0; //reset TIMER0 value;
INTCON = 0x20; //clear T0IF, Bit T0IF=0, T0IE=1;
}
void sensor(){
INTCON.GIE = 0; //Disable interrupt;
Ow_Reset (PORTA, 4); //one wire reset signal;
Ow_Write (PORTA, 4, 0xCC); //Issue command to DS18B20;
Ow_Write (PORTA, 4, 0X44); //Issue command to DS18B20;
INTCON.GIE = 1; //Enable interrupt;
Delay_ms(500); //Wait for conversion complete;
INTCON.GIE = 0;
CC = Ow_Reset(PORTA ,4);
Ow_Write(PORTA, 4, 0XCC); //Issue command to DS18B20;
Ow_Write(PORTA, 4, 0XBE); //Issue command to DS18B20;
J1 = Ow_Read(PORTA ,4); //Get result;
J2 = Ow_Read(PORTA ,4); //Get result (assuming the temperature is positive);
INTCON.GIE = 1; //Enable interrupt;
if(J2 = 0xFF)
J1 = J1 | 0XFF; //Complement of two;
J1 = J1 + 1;
J2 = ((J1 & 0x01)* 5); //Get decimal value;
J1 = J1 >> 1; //From the 2byte variable;
value = ((J1*10) + J2);
}
void main()
{
CMCON |= 7; // Set AN pins to Digital I/O;
OPTION_REG = 0x80; // Set timer TMR0;
digit = 0;
portb_index = 0;
shifter = 1;
TMR0 = 0;
INTCON = 0xA0; // Disable interrupt PEIE,INTE,RBIE,T0IE
PORTA = 0; // Turn off both displays
TRISA = 0; // All port A pins are configured as outputs
PORTB = 0; // Turn off all display segments
TRISB = 0; // All port D pins are configured as outputs
do {
sensor();
Delay_ms(500);
//Prepare digits for display;
digit = value % 10u; //extract ones digit;
portb_array[0] = mask(digit); //and store it to PORTB array;
digit = (value / 10u) % 10u; //extract tens digit;
portb_array[1] = mask(digit); //and store it to PORTB array;
digit = (value / 100u) % 10u; //extract hundreds digit;
portb_array[2] = mask(digit); //and store it to PORTB array;
digit = value / 1000u; //extract thousands digit;
portb_array[3] = mask(digit); //and store it to PORTB array;
}while(1);
}
hope this help,
regard
Code: Select all
unsigned cc; //correct this variable sorry didnt se it before
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 13 Aug 2010 20:22
by ducu
Thanks Mr. MR2010 for the support, I took the tests that you've suggested and I was able to advance a little with this project, currently the 4 digits are displaying "0000" and it can be observed the multiplexing.
With another few ideas maybe we will finish the project.
EDIT:
Could anyone test this code with any microcontrollers
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 20 Aug 2010 07:34
by ducu
No opinion?
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 02 Sep 2010 02:07
by MR2010
ducu wrote:No opinion?
hi, i have not got (DS18B20) to test here im sorry but ijust got proteus i will try to test your code and see whats wrong with it, hope someone has any ideas to help you.
Regards.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 02 Sep 2010 15:50
by ducu
Hello MR2010,
Thanks so much for help.
Until this moment I changed the line: J1 = J1 | 0xFF; with this: J1 = ~ J1; and the four digits varies between 0000 and 0260.
If i force to a specific value, that value is displayed on digits, but also have to do this line commented: //value = ((J1*10) + J2);
I think the issue begin when transform in decimal value.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 11 Dec 2011 12:47
by ducu
Perseverance always lead to a favorable result. We have completed the desired software version, I will post the result below.
Code: Select all
/*
'*******************************************************************************
' Project name: Digital thermometer with DS18B20 and 7-Segments.
' Description:
' In this experiment we will work with one-wire communication.
' The thermal sensor used is "DS18B20" and measured value is displayed
' on the 7-segment digits. PORTB will be used for character
' (RB0=a,RB1=b...RB6=g,RB7=dp)and for digits RA0=digit1...RA3=digit4.
' Data wire from DS18B20 is conected to RC7.
' The value will be displayed as follows: max: 125,9 "*C" min -55,9 "*C"
' Written by:
' Aureliu Raducu Macovei, 2011.
' Test configuration:
' MCU: PIC16F876A;
' Test.Board: WB-106 Breadboard 2420 dots;
' SW: MikroC PRO for PIC 2011 (version v4.60);
' Configuration Word:
' Oscillator: HS (8Mhz)on pins 9 and 10;
' Watchdog Timer: Disabled;
' Power up Timer: Disabled;
' Browun Out Reset: Enabled;
' Low Voltage Program: Disabled;
' Data EE Read Protect: Disabled;
' Flash Program Write: Disabled;
' In Circuit Debugger Mode: Disabled;
' Code Protect: Disabled.
'*******************************************************************************
*/
// Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:
// 18S20: 9 (default setting; can be 9,10,11,or 12)
// 18B20: 12
const unsigned short TEMP_RESOLUTION = 12;
unsigned short DD0,DD1,DD2,DD3;
unsigned temp;
//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num)
{
switch (num)
{
case 0 : return 0x3F;
case 1 : return 0x06;
case 2 : return 0x5B;
case 3 : return 0x4F;
case 4 : return 0x66;
case 5 : return 0x6D;
case 6 : return 0x7D;
case 7 : return 0x07;
case 8 : return 0x7F;
case 9 : return 0x6F;
case 10 : return 0x40; // Symbol '-'
case 11 : return 0x00; // Blank
case 12 : return 0x80; // Comma "," symbol
} //case end
}
void ds18b20(unsigned int temp2write)
{
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
unsigned temp_whole;
unsigned int temp_fraction;
unsigned short isNegative = 0x00;
// Check if temperature is negative
if (temp2write & 0x8000)
{
temp2write = ~temp2write + 1;
isNegative = 1;
}
// Extract temp_whole
temp_whole = temp2write >> RES_SHIFT ;
// Extract temp_fraction and convert it to unsigned int
temp_fraction = temp2write << (4-RES_SHIFT);
temp_fraction &= 0x000F;
temp_fraction *= 625;
DD0 = temp_fraction /1000;
DD0 = mask(DD0);
DD1 = temp_whole%10; // Extract Ones Digit
DD1 = mask(DD1)+mask(12);
DD2 = (temp_whole/10)%10; // Extract Tens Digit
DD2 = mask(DD2);
DD3 = temp_whole/100; // Extract Hundred digit
if (isNegative == 1) DD3=10;
else if (DD3 == 0) DD3 = 11 ;
DD3 = mask(DD3) ;
}
void display_temp(short DD0, short DD1, short DD2, short DD3)
{
PORTB = DD0;
RA0_bit = 1; // Select Thousands Digit of Fraction
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 0;
delay_ms(3);
PORTB = DD1;
RA0_bit = 0;
RA1_bit = 1; // Select Ones Digit
RA2_bit = 0;
RA3_bit = 0;
delay_ms(3);
PORTB = DD2;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 1; // Select Tens Digit
RA3_bit = 0;
delay_ms(3);
PORTB = DD3;
RA0_bit = 0;
RA1_bit = 0;
RA2_bit = 0;
RA3_bit = 1; // Select +/- Digit
delay_ms(3);
}
void main() {
ADCON1 = 0x87; // all portA are digital
CMCON |= 7; // Disable Comparators
TRISB = 0x00; // Set PORTB direction to be output
PORTB = 0x00; // Turn OFF LEDs on PORTB
TRISA0_bit = 0; // RA.0 Output
TRISA1_bit = 0; // RA.1 Output
TRISA2_bit = 0; // RA.2 Output
TRISA3_bit = 0; // RA.3 Output
do //--- main loop
{
//--- perform temperature reading
Ow_Reset(&PORTC, 7); // Onewire reset signal
Ow_Write(&PORTC, 7, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTC, 7, 0x44); // Issue command CONVERT_T
Ow_Reset(&PORTC, 7);
Ow_Write(&PORTC, 7, 0xCC); // Issue command SKIP_ROM
Ow_Write(&PORTC, 7, 0xBE); // Issue command READ_SCRATCHPAD
// Next Read Temperature
// Read Byte 0 from Scratchpad
temp = Ow_Read(&PORTC, 7);
// Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
temp = (Ow_Read(&PORTC, 7) << 8) + temp;
ds18b20(temp);
display_temp(DD0, DD1, DD2, DD3);
}while(1);
}
And some pictures that emphasize the good working in reality:
EDIT: Thank you for appreciation, Yako.
Re: PIC16F628A + DS18B20 + 7 segment [MikroC]
Posted: 13 Dec 2011 04:02
by Yako
That's a very nice website that you have.
You're a wizard with those breadboards.