PIC16F628A + DS18B20 + 7 segment [MikroC]

Status
Not open for further replies.

ducu

New Member
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) with 0,1 degree Celsius rezolution . I am using the MCU P16F628A, temperature sensor DS18B20 and 4 digit (7 segment) with common cathode.
Language used is MikroC.
Now, I have made some research and I create this code:
Code:
/*
'*******************************************************************************
' Description:
'    The temperature most be displayed on the digits (7 segments) in this
'    method (00,0C) with 0,1degree C resolution.
' 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, J3;
unsigned int value;
unsigned CC;

void interrupt_routine() org 0x04
{
 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(700);              // Wait for conversion complete;
                                          // If this delay is less than 500ms, you
                                          // Will see the first reading on LCD, 85'C
                                          // Which is a power on reset value.
              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;                   // Complement of two;
              J1 = J1 + 1;

              J2 = ((J1 & 0x01)* 5);      // Get decimal value;
              J1 = J1 >> 1;               // From the 2byte variable;
              value = ((J1*10) + J2);     // ((J1*10) + J2)
              Delay_ms(500);
              }


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();

    //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);
}

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);
At this moment all four digits varies between 0000 and 0260. I think the issue begin when transform in decimal value.
Does anyone have any idea to fix this problem?

Kind Regards,
ducu
 
Last edited:
What do you mean by 'force to a specified value'? Can you show how you did that? And, is void interrupt_routine() org 0x04 a right way to define ISR in mikroC?
Besides, if(J2 = 0xFF) must be if(J2 == 0xFF).
 
Hello Raj,
This is how i made the program so it can display a value set by me:
Code:
/*
'*******************************************************************************
' Description:
'    The temperature most be displayed on the digits (7 segments) in this
'    method (00,0C) with 0,1degree C resolution.
' 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, J3;
unsigned int value;
unsigned CC;

void interrupt_routine() org 0x04
{
 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(700);              // Wait for conversion complete;
                                          // If this delay is less than 500ms, you
                                          // Will see the first reading on LCD, 85'C
                                          // Which is a power on reset value.
              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);

              
              if(J2 == 0xFF)
              J1 = ~J1;                   // Complement of two;
              J1 = J1 + 1;

              J2 = ((J1 & 0x01)* 5);      // Get decimal value;
              J1 = J1 >> 1;               // From the 2byte variable;
              //value = ((J1*10) + J2);     // ((J1*10) + J2)
              
              INTCON.GIE = 1;             // Enable interrupt;
              Delay_ms(500);
              }


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
 value = 1234;             // <<<<< value set by me
do {
    sensor();
    //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);
}

I do not know if it is the best choice to use "void interrupt_routine () org 0x04", but if you know a better choice to do that please share with me.
I changed, as you suggested, this line "if (0xFF == J2)" and on my display appears value 25?!
Thanks for suggestions and I will wait for other opinions.
 
I understand, but I don't have DS18B20. The point was to demonstrate the technique, not to do others project exactly the way they want.
 
Raj,
Thanks a lot for your support, your demonstration was helpful, clever thinking when you avoid using interrupts. Now I have to figure out how to change into the 12-bit resolution, because the sensor used by me, does not like this program.

Don't be upset on mvs sarma, just made the humble observation .
I will keep you posted with events.

Kind Regards,
ducu.
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…