Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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.
 
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.

Latest threads

New Articles From Microcontroller Tips

Back
Top