CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DS18b20 PIC16F84A and 4x7-segment LED problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

DS18b20 PIC16F84A and 4x7-segment LED problem
PostPosted: Thu Feb 24, 2011 7:45 am     Reply with quote

Hello, trying to write a program to the old thermometer. And I have no idea to get it to work. The display is working properly now only has a problem with the DS18B20 is connected to the port of A4. Below is my code.
Schematic :
Code:

#include <16f84a.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */

#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No Power-up Timer */

#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */
byte CONST LED_MAP[12] = {0x24,0xe7,0x4c,0x45,0x87,0x15,0x14,0x67,0x04,0x05,0xfb,0xdf};
byte CONST LED_POZ[4] = {0x04,0x02,0x01,0x08};
unsigned int mask(unsigned int num);
unsigned int minus, ulamek, cyfra, dziesiatka;
int8 i;
signed int16 temperature;
int8 scratch[9];
#define DQ   PIN_A4

//-------------------------------------
void ow_reset(void)
{
output_low(DQ);
delay_us(500);          // Min. 480uS
output_float(DQ);
delay_us(500);          // Wait for end of timeslot
}

//-------------------------------------
// Read bit on one wire bus

int8 read_bit(void)
{
output_low(DQ);
delay_us(1);
output_float(DQ);
delay_us(12);        // Read within 15uS from start of time slot
return(input(DQ));
}

//-------------------------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;

for(i=0 ; i<8 ; i++)
   {
    if(read_bit()) val |= (0x01 << i);
       delay_us(120);  // To finish time slot
   }

return val;
}

//-------------------------------------
void write_byte(int8 val, int8 power_on)
{
int i;

for(i=0; i<8; i++)
   {
    output_low(DQ);
    delay_us( 2 );
    output_bit(DQ, shift_right(&val,1,0));

    delay_us(60);

    if((i == 7) && (power_on == 1))
      {
       output_high(DQ);
      }
    else
      {
       output_float(DQ);
       delay_us( 2 );
      }
   }

}


void wyswietl_xy(int poz, int cyfra)
{
port_a=LED_POZ[poz];
port_b=LED_MAP[cyfra];
}

main(){
disable_interrupts ( GLOBAL );
setup_timer_0 ( RTCC_DIV_1 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts ( GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;


output_float(DQ);

while(1)
  {
   ow_reset();
   write_byte(0xCC, 0); // Skip Rom command
   write_byte(0x44, 1); // Temperature Convert command

   delay_ms(750);    // Max. time for conversion is 750mS

   ow_reset();
   write_byte(0xCC, 0); // Skip Rom command
   write_byte(0xBE, 0); // Read scratch pad command

   // Get the data bytes
   for(i=0; i < 8; i++)
      {
       scratch[i] = read_byte();
      }

   ow_reset();

   temperature = (signed int16) make16(scratch[1],scratch[0]);

   if(temperature >= 0)
      temperature = (temperature + 8)/16;
   else
      temperature = (temperature - 8)/16;

   cyfra=temperature;
   }
  }

#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus==1) {wyswietl_xy(3,11);}
delay_us(330);
if(dziesiatka!=0) {wyswietl_xy(2,dziesiatka);}
delay_us(330);
wyswietl_xy(1,cyfra);
delay_us(330);
wyswietl_xy(1,10);
delay_us(330);
wyswietl_xy(0,ulamek);
delay_us(330);
}
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Feb 24, 2011 8:08 am     Reply with quote

Is this real hardware or a Proteus project ?
Proteus is full of 'bugs' but you can see and touch hardware!

Divide and conquer !
Since you say the display is working, I'd write new code, just to test the DS chip.
Basically read the DS chip and send the result to a PC using RS232.That way you can be sure the timings for the DS chip are correct.
The pullup should be 4K7 on the DQ pin.

Once that works, 'merege' the two working programs into a third.
Be sure to save backups of working code !
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Thu Feb 24, 2011 8:58 am     Reply with quote

Yes it's real project and it's works with old software but the software has a bug so I decide to write my own and the display work fine but I can't retrive information from ds Crying or Very sad probably it is a stupid mistake. This is my first program for the PIC , I always write for atmega

is it ok for my schematic ?

Code:

#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */
#define DQ   PIN_A4

And it ?
Code:

disable_interrupts ( GLOBAL );
setup_timer_0 ( RTCC_DIV_1 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts ( GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */
port_b = 0; /* ZERO port_a & port_b */
port_a = 0;
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Thu Feb 24, 2011 10:55 am     Reply with quote

I found probably a bug in comparison with the original software on the 5V line RA4 in my program that is not: (. How does it solve?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 24, 2011 4:05 pm     Reply with quote

Pin A4 is an open drain pin. Your code was from this 2-page thread
http://www.ccsinfo.com/forum/viewtopic.php?t=40106
and it was tested with Pin A0. Try using pin A0. It's not open drain.
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 1:53 am     Reply with quote

Ok ds18b20 now is working but I have problem again with multiplexing, can anybody help how to set ok delays between segments in the timer ?
Code:

#include <16f84a.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */

#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No Power-up Timer */

#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */

byte CONST LED_MAP[12] = {0x24,0xe7,0x4c,0x45,0x87,0x15,0x14,0x67,0x04,0x05,0xfb,0xdf};
byte CONST LED_POZ[4] = {0x04,0x02,0x01,0x08};
unsigned int minus, ulamek, cyfra, dziesiatka;
/*
 * One wire (1-wire) driver for CCS C compiler. Suitable for use with devices
 * such as the DS18B20 1-wire digital temperature sensor.
 */
float value = 0.0;
float temp;
#define ONE_WIRE_PIN PIN_A4

/*
 * onewire_reset()
 * Description: Initiates the one wire bus.
 */
// OK if just using a single permanently connected device
void onewire_reset() {
    output_low(ONE_WIRE_PIN);       // pull the bus low for reset
    delay_us(500);
    output_float(ONE_WIRE_PIN);     // float the bus high
    delay_us(500);                  // wait-out remaining initialisation window
    output_float(ONE_WIRE_PIN);
}


/*
 * onewire_write(int8 data)
 * Arguments: a byte of data.
 * Description: writes a byte of data to the device.
 */
void onewire_write(int8 data) {
    int8 count;

    for(count = 0; count < 8; ++count) {
        output_low(ONE_WIRE_PIN);
        delay_us(2);                // pull 1-wire low to initiate write time-slot.
        output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
        delay_us(60);               // wait until end of write slot.
        output_float(ONE_WIRE_PIN); // set 1-wire high again,
        delay_us(2);                // for more than 1us minimum.
    }
}

/*
 * onewire_read()
 * Description: reads and returns a byte of data from the device.
 */
int onewire_read() {
    int count, data;

    for(count = 0; count < 8; ++count) {
        output_low(ONE_WIRE_PIN);
        delay_us(2);                // pull 1-wire low to initiate read time-slot.
        output_float(ONE_WIRE_PIN); // now let 1-wire float high,
        delay_us(8);                // let device state stabilise,
        shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
        delay_us(120);              // wait until end of read slot.
    }
    return data;
}
/*
 * ds1820_read()
 * Description: reads the ds18x20 device on the 1-wire bus and returns
 *              the temperature
 */

float ds1820_read() {
    int8 busy=0, temp1, temp2;
    signed int16 temp3;
    float result;

    //ds1820_configure(0x00, 0x00, 0x00);     //9 bit resolution

    onewire_reset();
    onewire_write(0xCC);            //Skip ROM, address all devices
    onewire_write(0x44);            //Start temperature conversion

    while(busy == 0)                //Wait while busy (bus is low)
        busy = onewire_read();

    onewire_reset();
    onewire_write(0xCC);            //Skip ROM, address all devices
    onewire_write(0xBE);            //Read scratchpad
    temp1 = onewire_read();
    temp2 = onewire_read();
    temp3 = make16(temp2, temp1);

    //result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution
    result = (float) temp3 / 16.0;    //Calculation for DS18B20

    delay_ms(200);
    return(result);
}

/*
 * ds1820_configure(int8 TH, int8 LH, int8 config)
 * Description: writes configuration data to the DS18x20 device
 * Arguments: alarm trigger high, alarm trigger low, configuration
 */

void ds1820_configure(int8 TH, int8 TL, int8 config) {
    onewire_reset();
    onewire_write(0xCC);            //Skip ROM, address all devices
    onewire_write(0x4E);            //Write to scratchpad
    onewire_write(TH);
    onewire_write(TL);
    onewire_write(config);
}

void wyswietl_xy(int poz, int cyfra)
{
port_a=LED_POZ[poz];
port_b=LED_MAP[cyfra];
}

main(){
setup_timer_0 ( RTCC_DIV_256 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts (GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */

port_b = 0; /* ZERO port_a & port_b */
port_a = 0;

while(1)
  {
   value = ds1820_read();
   if(value<0)
   {
   minus=0;
   value=value*-1;
   }
   else minus=1;
   cyfra= (int)value%10;
   dziesiatka=(int)value/10;
   //temp=value-(int)value;
//   delay_ms(100);
   }
  }

#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus!=1) {wyswietl_xy(3,11);}
delay_us(2640);
if(dziesiatka!=0) {wyswietl_xy(2,dziesiatka);}
delay_us(2640);
wyswietl_xy(1,cyfra);
delay_us(2640);
wyswietl_xy(1,10);
delay_us(2640);
wyswietl_xy(0,ulamek);
delay_us(2640);
}
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 6:57 am     Reply with quote

In your original post you said the display was OK...

I suggest you eliminate the Dallas code and used a fixed reading, say -12.3, to test your code for the display. This way you know what it should be and can figure it out.

Your code for the display is not in English ,makes hard for me to tell what is going on, but I can't see how it could work

Also I don't see where variable 'ulamek' has data put in.
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 7:54 am     Reply with quote

Code:
#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus!=1) {show_xy(3,11);}
delay_us(2640);
if(hundred!=0) {show_xy(2,tens);}
delay_us(2640);
show_xy(1,number);
delay_us(2640);
show_xy(1,10);
delay_us(2640);
show_xy(0,less_than_one);
delay_us(2640);
}
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 8:38 am     Reply with quote

you'll have to show the whole program, as you've made changes including variables that we can't see as well as a new function show_xy...
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 9:21 am     Reply with quote

Code:

#include <16f84a.h>

#USE DELAY( CLOCK=4000000 ) /* Using a 4 Mhz clock */

#FUSES XT,NOWDT,NOPROTECT,NOPUT
/* Use XT mode, No Watch Dog, No Code Protect, No Power-up Timer */

#byte port_b=6 /* define the location of register port_b */
#byte port_a=5 /* define the location of register port_b */

byte CONST LED_MAP[12] = {0x24,0xe7,0x4c,0x45,0x87,0x15,0x14,0x67,0x04,0x05,0xfb,0xdf};
byte CONST LED_POSITION[4] = {0x04,0x02,0x01,0x08};
unsigned int minus, less_than_one, single_number, tens;
/*
 * One wire (1-wire) driver for CCS C compiler. Suitable for use with devices
 * such as the DS18B20 1-wire digital temperature sensor.
 */
float value = 0.0;
float temp;
#define ONE_WIRE_PIN PIN_A4

/*
 * onewire_reset()
 * Description: Initiates the one wire bus.
 */
// OK if just using a single permanently connected device
void onewire_reset() {
    output_low(ONE_WIRE_PIN);       // pull the bus low for reset
    delay_us(500);
    output_float(ONE_WIRE_PIN);     // float the bus high
    delay_us(500);                  // wait-out remaining initialisation window
    output_float(ONE_WIRE_PIN);
}


/*
 * onewire_write(int8 data)
 * Arguments: a byte of data.
 * Description: writes a byte of data to the device.
 */
void onewire_write(int8 data) {
    int8 count;

    for(count = 0; count < 8; ++count) {
        output_low(ONE_WIRE_PIN);
        delay_us(2);                // pull 1-wire low to initiate write time-slot.
        output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire
        delay_us(60);               // wait until end of write slot.
        output_float(ONE_WIRE_PIN); // set 1-wire high again,
        delay_us(2);                // for more than 1us minimum.
    }
}

/*
 * onewire_read()
 * Description: reads and returns a byte of data from the device.
 */
int onewire_read() {
    int count, data;

    for(count = 0; count < 8; ++count) {
        output_low(ONE_WIRE_PIN);
        delay_us(2);                // pull 1-wire low to initiate read time-slot.
        output_float(ONE_WIRE_PIN); // now let 1-wire float high,
        delay_us(8);                // let device state stabilise,
        shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result.
        delay_us(120);              // wait until end of read slot.
    }
    return data;
}
/*
 * ds1820_read()
 * Description: reads the ds18x20 device on the 1-wire bus and returns
 *              the temperature
 */

float ds1820_read() {
    int8 busy=0, temp1, temp2;
    signed int16 temp3;
    float result;

    //ds1820_configure(0x00, 0x00, 0x00);     //9 bit resolution

    onewire_reset();
    onewire_write(0xCC);            //Skip ROM, address all devices
    onewire_write(0x44);            //Start temperature conversion

    while(busy == 0)                //Wait while busy (bus is low)
        busy = onewire_read();

    onewire_reset();
    onewire_write(0xCC);            //Skip ROM, address all devices
    onewire_write(0xBE);            //Read scratchpad
    temp1 = onewire_read();
    temp2 = onewire_read();
    temp3 = make16(temp2, temp1);

    //result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution
    result = (float) temp3 / 16.0;    //Calculation for DS18B20

    delay_ms(200);
    return(result);
}

/*
 * ds1820_configure(int8 TH, int8 LH, int8 config)
 * Description: writes configuration data to the DS18x20 device
 * Arguments: alarm trigger high, alarm trigger low, configuration
 */

void ds1820_configure(int8 TH, int8 TL, int8 config) {
    onewire_reset();
    onewire_write(0xCC);            //Skip ROM, address all devices
    onewire_write(0x4E);            //Write to scratchpad
    onewire_write(TH);
    onewire_write(TL);
    onewire_write(config);
}

void show_xy(int position, int single_number)
{
port_a=LED_POSITION[position];
port_b=LED_MAP[single_number];
}

main(){
setup_timer_0 ( RTCC_DIV_256 | RTCC_INTERNAL );
set_timer0 (0);
enable_interrupts (GLOBAL );
enable_interrupts (INT_RTCC);
set_tris_b(0); /* set port_b as outputs */
set_tris_a(0); /* set port_a as output */

port_b = 0; /* ZERO port_a & port_b */
port_a = 0;

while(1)
  {
   value = ds1820_read();
   if(value<0)
   {
   minus=0;
   value=value*-1;
   }
   else minus=1;
   single_number= (int)value%10;
   tens=(int)value/10;
   //temp=value-(int)value;
//   delay_ms(100);
   }
  }

#INT_RTCC
TIMER_INTERRUPT ( )
{
if(minus!=1) {show_xy(3,11);}
delay_us(2640);
if(tens!=0) {show_xy(2,tens);}
delay_us(2640);
show_xy(1,single_number);
delay_us(2640);
show_xy(1,10);
delay_us(2640);
show_xy(0,less_than_one);
delay_us(2640);
}
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 12:45 pm     Reply with quote

The principle is very simple, the main loop reads DS18B20 and enter the number of different global variables, and the timer global variables are displayed. The problem is only when the timer accordingly to multiplex the digits on the display
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 1:48 pm     Reply with quote

Have you created a program that just cycle through the numbers 0 to 9, at say the 'ones digit' to confirm your decode table is correct?
The port pin to display segment isn't 'nice', ie: it isn't B.0 = a,B.1=b,etc.
Makes it very difficult to see if it is correct for the common anode display I assume you're using.
Depending on the multiplex rate,you'll need to increase the current to the display but go too far and the PIC may blowup.

You can of course for test purposes not use the timer interrupt and just run the code in 'main'

Be sure to disable all interrupts first though.

I'd still 'force' the value to be displayed to say -123 for test purposes, as you could have incorrect wiring but think it's a code problem.
woser



Joined: 24 Feb 2011
Posts: 8

View user's profile Send private message

PostPosted: Fri Feb 25, 2011 3:25 pm     Reply with quote

I don't know why when I change DIV_256 to another DS18b20 doesn't work ??
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group