Menu

all about electronic and microcontrollers
Showing posts with label 7Segment. Show all posts
Showing posts with label 7Segment. Show all posts

Tuesday, November 11, 2014

DS1307 [ RTC with Set Functions] & DS18B20 & MAX7219 [8 Digits]

Today I will show you how to display the values of RTC DS1307 and DS18B20 on six digits with seven segments driven by MAX7219. Obviously I designed a sort of menu (helped by three buttons) to be able to change the values on IC DS1307.
We have already explained, in previous projects, how works and communicate the IC DS1307 and MAX7219, so we will proceed further by developing electronic schematic and the software model.

Hardware setup:
I intend to display the clock and room temperature, on six digits with seven segment. The time will be displayed on digits for 5 seconds then for another 5 second it will be displayed the temperature and so on.
In my case, the clock and max7219 circuit are mounted separately on pcb.
Clock circuit is designed separately by me, but max7219 circuit is acquired from Mikroelektronika.
Electrical schematic is designed to include the complete circuit.
Physical realization is carried out on the breadboard with 2420 dots.




Video:

Circuit Diagram:
This schematic has a low difficulty level. Microcontroller used is PIC16F876A.
S1 is the master reset button, R1 is the resistor of pull-up button.
Crystal quartz used has 8Mhz.
ICSP connector is used to program the microcontroller (I use PICKIT2).
R1, R3, R5, R10 are pull-up resistors.
Diode D1 has a protective role.
All three buttons are part of: incrementing hour, incrementing minute and enter.
Communication between DS1307 and circuit board "breadboard" is established by five pins as follow (GND, SQW, SCL, SDA, 5VDC). SQW pin is not used in this project.
We used a battery of 3vcc to ensure the functioning of the internal clock of DS1307 IC's, even if it is disconnected from 5 VDC.
Communication between max7219 circuit and microcontroller is set by pins RC0 (CS), RC1 (CLK) and RC2 (MOSI) used for software SPI protocol.
IF you are planning to use the "Serial 7-Seg 8-Digit Board" from mikroelektronika, it is necessary to set the appropriate switches on the DIP switch SW1 to the ON position:
  • Switch 1- MOSI 
  • Switch 4 - SCK 
  • Switch 7 - CS 
Port RC7 ensure communication with DS18B20 sensor.
The capacitors C8-C11 serve as power filtering. Preferably is that the capacitors filters to be as near by ICs.


Electronic schematic is built in Eagle Cad, free version.

Software:
The program is written in mikroC Pro for PIC (version v6.4.0).
Below is my software version:
/*
'*******************************************************************************
'  Project name: Real Time Clock [DS1307 with Set Functions] & DS18B20 & max7219
'  Description:
'          With this experiment we wish to succed the next task:
'          Display on 6 digits with 7 segment leds, the clock and the room 
'          temperature (in Celsius Degree).
'          Setting the time helped by three buttons: hours, minutes and enter.
'
'          The sign "-" to the negative temperature and the hundreds for the
'          temperature value are displayed just if are used.
'          The time is displayed 5 second then he display the temperature value 
'          in Celsius Degrees for other 5 seconds and the loop goes to infinite.
'          Our clock, displays as shown below(but just in display time,
'          not in set mode).
'          Ex. of viewing in 7 segment display,6 digits :
'          Display time, mode:             Display temperature mode:
'               __________                         _________
'              |__24.59.59|     ~5 sec delay      |____23.6C|
'
'          Hardware configuration is:
'             IC ds1307 is connected with our microcontroller trough RC3=SCL,
'             RC4=SDA (I2C Connections), 
'             max7219 as follow:(CS at RC0, CLK at RC1 and MOSI(SDO) at RC2)
'             DS18B20 is assigned to RC7,
'             RB0,RB1 and RB3 are assigned to the buttons
'             Buttons Menu: RB0= Enter,  (It goes to set functions or exit from set functions)
'                           RB1= Minutes,
'                           RB2= Hours,
'
'  Written by:
'          Aureliu Raducu Macovei, 2014.
'  Test configuration:
'    MCU:                        PIC16F876A;
'    Test.Board:                 WB-106 Breadboard 2420 dots;
'    SW:                         MikroC PRO for PIC 2013 (version v6.4.0);
'  Configuration Word:
'    Oscillator:                 HS (8Mhz)on pins 9 and 10;
'    Watchdog Timer:             OFF;
'    Power up Timer:             OFF;
'    Browun Out Detect:          ON;
'    Low Voltage Program:        Disabled;
'    Data EE Read Protect:       OFF;
'    Flash Program Write:        Write Protection OFF;
'    Background Debug:           Disabled;
'    Code Protect:               OFF
'*******************************************************************************
*/

// Software SPI module connections for max7219
sbit SoftSpi_SDI at RC6_bit;
sbit SoftSpi_SDO at RC2_bit;                   // MOSI
sbit SoftSpi_CLK at RC1_bit;
sbit Chip_Select at RC0_bit;

sbit SoftSpi_SDI_Direction at TRISC6_bit;
sbit SoftSpi_SDO_Direction at TRISC2_bit;
sbit SoftSpi_CLK_Direction at TRISC1_bit;
sbit Chip_Select_Direction at TrisC0_bit;
// End Software SPI module connections for max7219

const unsigned short TEMP_RESOLUTION = 12;     //This is resolution for ds18b20
unsigned temp;

unsigned sec, min1, hr, week_day, day, mn, year;
unsigned short mask(unsigned short num)
{
 switch (num)               // Define switch cases
 {
  case  0 : return 0x7E;    // 0 for those values please study the datasheet max7219
  case  1 : return 0x30;    // 1
  case  2 : return 0x6D;    // 2
  case  3 : return 0x79;    // 3
  case  4 : return 0x33;    // 4
  case  5 : return 0x5B;    // 5
  case  6 : return 0x5F;    // 6
  case  7 : return 0x70;    // 7
  case  8 : return 0x7F;    // 8
  case  9 : return 0x7B;    // 9
  case 10 : return 0x01;    // Symbol '-'
  case 11 : return 0x00;    // Blank
  case 12 : return 0x80;    // Comma "," symbol
  case 13 : return 0x43;    // C
  } //case end
}

void max7219_init()
{
 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x09);      // Decode-Mode Register
 Soft_Spi_write(0x00);      // No decode for digits 7–0
 Chip_Select = 1;           // DESELECT MAX
 
 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x0A);      // Intensity Register Format
 Soft_Spi_write(0x01);      // Segment luminosity intensity set to 3/32
 Chip_Select = 1;           // DESELECT MAX

 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x0B);      // Scan-Limit Register Format
 Soft_Spi_write(0x05);      // Display digits 0 1 2 3 4 5
 Chip_Select = 1;           // DESELECT MAX

 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x0C);      // Shutdown Register Format
 Soft_Spi_write(0x01);      // Normal Operation
 Chip_Select = 1;           // DESELECT MAX

 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x00);      // No-Op
 Soft_Spi_write(0xFF);      // No test
 Chip_Select = 1;           // DESELECT MAX
}

char minute2,hour2;
void max7219_display_set_mode(unsigned minute2, unsigned hour2)
{
 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(6);                              // digit 6
 Soft_Spi_write(mask((hour2/10)%10));            // assign tens of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(5);                              // digit 5
 Soft_Spi_write ((mask(hour2%10))+ mask(12));    // assign units of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(4);                              // digit 4
 Soft_Spi_write(mask((minute2/10)%10));          // assign tens of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(3);                              // digit 3
 Soft_Spi_write((mask(minute2%10))+mask(12));    // assign units of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;           // select max7219
 Soft_Spi_write(2);         // digit 2
 Soft_Spi_write (0);        // set as blank
 Chip_Select = 1;           // deselect max7219

 Chip_Select = 0;           // select max7219
 Soft_Spi_write(1);         // digit 1
 Soft_Spi_write (0);        // set as blank
 Chip_Select = 1;           // deselect max7219
}

void max7219_display (unsigned sec, unsigned min, unsigned hr)
{
 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(6);                              // digit 6
 Soft_Spi_write(mask((hr/10)%10));               // assign tens of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(5);                              // digit 5
 Soft_Spi_write ((mask(hr%10))+ mask(12));       // assign units of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(4);                              // digit 4
 Soft_Spi_write(mask((min/10)%10));              // assign tens of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(3);                              // digit 3
 Soft_Spi_write((mask(min%10))+mask(12));        // assign units of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(2);                              // digit 2
 Soft_Spi_write (mask((sec/10)%10));             // assign tens of seconds
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(1);                              // digit 1
 Soft_Spi_write (mask(sec%10));                  // assign units of seconds
 Chip_Select = 1;                                // deselect max7219
}

//-----Reads time and date information from RTC (DS1307)
void Read_Time(unsigned *sec, unsigned *min, unsigned *hr, unsigned *week_day, 
               unsigned *day, unsigned *mn, unsigned *year)
{
 I2C1_Start();
 I2C1_Wr(0xD0);
 I2C1_Wr(0);
 I2C1_Repeated_Start();
 I2C1_Wr(0xD1);
 *sec =I2C1_Rd(1);
 *min =I2C1_Rd(1);
 *hr =I2C1_Rd(1);
 *week_day =I2C1_Rd(1);
 *day =I2C1_Rd(1);
 *mn =I2C1_Rd(1);
 *year =I2C1_Rd(0);
 I2C1_Stop();
}//~

//-----------------start write time routine------------------
void Write_Time(unsigned minute, unsigned hour)
{
 unsigned tmp1, tmp2;
 
 tmp1 = minute / 10;           // assign values from variables
 tmp2 = minute % 10;           // assign values from variables
 minute = tmp1 * 16 + tmp2;    // assign values from variables

 tmp1 = hour / 10;             // assign values from variables
 tmp2 = hour % 10;             // assign values from variables
 hour = tmp1 * 16 + tmp2;      // assign values from variables

 I2C1_Start();          // issue start signal
 I2C1_Wr(0xD0);         // address DS1307
 I2C1_Wr(0);            // start from word at address (REG0)
 I2C1_Wr(0x80);         // write $80 to REG0. (pause counter + 0 sec)
 I2C1_Wr(minute);       // write minutes word to (REG1)
 I2C1_Wr(hour);         // write hours word (24-hours mode)(REG2)
 I2C1_Wr(0x00);         // write 6 - Saturday (REG3)
 I2C1_Wr(0x00);         // write 14 to date word (REG4)
 I2C1_Wr(0x00);         // write 5 (May) to month word (REG5)
 I2C1_Wr(0x00);         // write 01 to year word (REG6)
 I2C1_Wr(0x80);         // write SQW/Out value (REG7)
 I2C1_Stop();           // issue stop signal

 I2C1_Start();          // issue start signal
 I2C1_Wr(0xD0);         // address DS1307
 I2C1_Wr(0);            // start from word at address 0
 I2C1_Wr(0);            // write 0 to REG0 (enable counting + 0 sec)
 I2C1_Stop();           // issue stop signal
}
//-----------------end write time routine------------------

//-------------------- Formats date and time
void Transform_Time(unsigned *sec, unsigned *min, unsigned *hr, 
                    unsigned *week_day, unsigned *day, unsigned *mn, unsigned *year)
{
 *sec  =  ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
 *min  =  ((*min & 0xF0) >> 4)*10 + (*min & 0x0F);
 *hr   =  ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
 *week_day =(*week_day & 0x07);
 *day  =  ((*day & 0xF0) >> 4)*10 + (*day & 0x0F);
 *mn   =  ((*mn & 0x10) >> 4)*10 + (*mn & 0x0F);
 *year =  ((*year & 0xF0)>>4)*10+(*year & 0x0F);
}//~

void blink_min()
{
 Chip_Select = 0;               // select max7219
 Soft_Spi_write(4);             // digit 4
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;               // deselect max7219

 Chip_Select = 0;               // select max7219
 Soft_Spi_write(3);             // digit 3
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;

 delay_ms(50);                               // 50ms delay
 max7219_display_set_mode(minute2,hour2);    // display those values
 delay_ms(50);                               // 50ms delay
}
void blink_hr()
{
 Chip_Select = 0;               // select max7219
 Soft_Spi_write(6);             // digit 6
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;               // deselect max7219

 Chip_Select = 0;               // select max7219
 Soft_Spi_write(5);             // digit 5
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;               // deselect max7219

 delay_ms(50);                               // 50ms delay
 max7219_display_set_mode(minute2,hour2);    // display those values
 delay_ms(50);                               // 50ms delay
}

char setuptime=0;
unsigned count=0;
void Press_Switch()
{
 if(button(&portb,0,1,0))        // check if button RB0 is pressed
 {
  Delay_ms(200);
  setuptime = !setuptime;        // switch that value;

  if(setuptime)
  {
  hour2=hr;
  minute2=min1;
  max7219_display_set_mode(minute2,hour2);   // display those values
  }
  else
  {
   hr=hour2;
   min1=minute2;
   Write_Time(min1,hr);
   max7219_display_set_mode(minute2,hour2);
  }
 }
 
 if(Setuptime)
 {
  if(button(&portb,1,1,0))
  {
   Delay_ms(150);
   minute2++;
   if(minute2 > 59)
   minute2=0;
   blink_min();
   }
  if(button(&portb,2,1,0))
  {
   Delay_ms(150);
   hour2++;
   if(hour2 > 23)
   hour2=0;
   blink_hr();
   }
  }
}

// Starts ds18b20 declarations
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;          // 625 for ds18b20 and 5000 for ds1820;

 Chip_Select = 0;               // select max7219
 Soft_Spi_write(1);             // digit 1
 Soft_Spi_write(mask(13));      // write C symbol
 Chip_Select = 1;               // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(2);                              // Set digit number 3
 Soft_Spi_write(mask(temp_fraction /1000));      // assigne as fraction
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(3);                              // Set digit number 3
 Soft_Spi_write((mask(temp_whole%10))+mask(12)); // Assigne as ones
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(4);                              // Set digit number 4
 Soft_Spi_write (mask((temp_whole/10)%10));      // Assigne as tens
 Chip_Select = 1;                                // deselect max7219
  
 if (isNegative == 1)
 {
  Chip_Select = 0;               // select max7219
  Soft_Spi_write(5);             // Set digit number 5
  Soft_Spi_write(mask(10));      // Assigne as symbol "-"
  Chip_Select = 1;               // deselect max7219
  }
 else
 {
  if(isNegative ==0 && temp_whole/100==0)
  {
   Chip_Select = 0;               // select max7219
   Soft_Spi_write(5);             // Set digit number 5
   Soft_Spi_write(mask(11));      // Assign as blank
   Chip_Select = 1;               // deselect max7219
   }
  else
  {
   Chip_Select = 0;                         // select max7219
   Soft_Spi_write(5);                       // Set digit number 5
   Soft_Spi_write(mask(temp_whole/100));    // Assign the hundreds
   Chip_Select = 1;                         // deselect max7219
   }
  }
  
 Chip_Select = 0;                 // select max7219
 Soft_Spi_write(6);               // Set digit number 6
 Soft_Spi_write(0);               // Assign value 0
 Chip_Select = 1;                 // deselect max7219
}// End ds18b20 declarations

void interrupt()
{
 if(setuptime)
 count=0;
 else
 count++;                  // Interrupt causes count to be incremented by 1
 TMR0 = 0;                 // Timer TMR0 is returned its initial value
 INTCON = 0x20;            // Bit T0IE is set, bit T0IF is cleared
}

void main() 
{
 CMCON  |= 7;                  // Disable Comparators
 OPTION_REG = 0x84;            // Prescaler Rate Selected at 1:32;
 TMR0 = 0;                     // Reset timer;
 INTCON = 0xA0;                // Disable interrupt PEIE,INTE,RBIE,T0IE

 Chip_Select_Direction = 0;    // Set RC0 pin as output
 Soft_Spi_init();              // Initialize software SPI module
 max7219_init();               // initialize  max7219
 I2C1_Init(100000);            // initialize I2C

 while (1)                     // and here, our while loope
 {
  Press_Switch();
     
  if(!setuptime)
  {
   if(count<=1400)                    // ~ 5 seconds
   {
    Read_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year);      // read time from RTC(DS1307)
    Transform_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // format date and time
    max7219_display(sec,min1, hr);
    }
   else
   {
    if(count>1400)                     // ~ 5 seconds
    {
     //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

     temp =  Ow_Read(&PORTC, 7);   // Next Read Temperature and Read Byte 0 from Scratchpad
     // 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);                  //Format and display result on digits.
     }
    }
   if(count>2800)
   count = 0;
   }
  }
}

Sunday, October 17, 2010

Lesson nr.14-DS18B20 using 1-Wire Protocol & 7seg

Hardware setup:
In this Lesson, we will make a digital temperature meter using DS18B20. The connection between temperature sensor and microcontroller will be done through a single wire. This is advantage of the temperature sensor model. The temperature value will be displayed on 4 digits-with 7 segment, in multiplexed mod of course.
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 RA4.
Pull-up resistor (with a value of 4.7 k), is required to perform communication between the sensor and microcontroller.











Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:



Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.14:
'          Digital thermometer with DS18B20 and 7- Segments.
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  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 RA4.
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  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
'*******************************************************************************
*/
unsigned short i, DD0=0x40, DD1=0x40,DD2=0x40, DD3 =0x61, N_Flag;
unsigned temp_value=0;                         // Variable to store temperature register value
unsigned short mask(unsigned short num)        // Mask for 7 segment common cathode;
{
 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;          // Symbol '-'
  case 11 : return 0x61;          // Symbol C
  case 12 : return 0x00;          // Blank
  } //case end
}

void display_temp(short DD0, short DD1, short DD2, short DD3)
{
 for (i = 0; i<=4; i++)
 {
  PORTB = DD3;
  RA0_bit = 1;                    // Select C Digit;
  RA1_bit = 0;
  RA2_bit = 0;
  RA3_bit = 0;
  delay_ms(2);
  PORTB = DD0;
  RA0_bit = 0;
  RA1_bit = 1;                    // Select Ones Digit;
  RA2_bit = 0;
  RA3_bit = 0;
  delay_ms(2);
  PORTB = DD1;
  RA0_bit = 0;
  RA1_bit = 0;
  RA2_bit = 1;                    // Select Tens Digit;
  RA3_bit = 0;
  delay_ms(2);
  PORTB = DD2;
  RA0_bit = 0;
  RA1_bit = 0;
  RA2_bit = 0 ;
  RA3_bit = 1;                    // Select +/- Digit;
  delay_ms(2);
  }return;
}

void DS18B20()                              //Perform temperature reading
{
 Display_temp(DD0, DD1, DD2, DD3);
 Ow_Reset(&PORTA, 4);                       // Onewire reset signal
 Ow_Write(&PORTA, 4, 0xCC);                 // Issue command SKIP_ROM
 Ow_Write(&PORTA, 4, 0x44);                 // Issue command CONVERT_T
 Display_temp(DD0, DD1, DD2, DD3);
 Ow_Reset(&PORTA, 4);
 Ow_Write(&PORTA, 4, 0xCC);                 // Issue command SKIP_ROM
 Ow_Write(&PORTA, 4, 0xBE);                 // Issue command READ_SCRATCHPAD
 Display_temp(DD0, DD1, DD2, DD3);
 // Next Read Temperature
 temp_value =  Ow_Read(&PORTA, 4);          // Read Byte 0 from Scratchpad
 temp_value = (Ow_Read(&PORTA, 4) << 8) + temp_value;       // Then read Byte 1 from
                                                            // Scratchpad and shift
                                                            // 8 bit left and add the Byte 0
 if (temp_value & 0x8000) {
                           temp_value = ~temp_value + 1;
                           N_Flag = 1;      // Temp is -ive
                           }
 if (temp_value & 0x0001) temp_value += 1;  // 0.5 round to 1
 temp_value = temp_value >> 4 ;      //<<<  // 1 for DS1820 and
                                            // 4 for DS18B20;
 }

void main()
{
 CMCON  |= 7;                               // Disable Comparators
 TRISB = 0;                                 // Set PORTB direction to be output
 PORTB = 0;                                 // Turn OFF LEDs on PORTB
 PORTA = 0;
 TRISA0_bit = 0;                            // RA.0 to RA3 Output
 TRISA1_bit = 0;
 TRISA2_bit = 0;
 TRISA3_bit = 0;
 
 do {                                        //--- main loop
     N_Flag = 0;                             // Reset Temp Flag
     DS18B20();
     DD0 = temp_value%10;                    // Extract Ones Digit
     DD0 = mask(DD0);
     DD1 = (temp_value/10)%10;               // Extract Tens Digit
     DD1 = mask(DD1);
     DD2 =  temp_value/100;                  // Extract Hundred digit
     if (N_Flag == 1) DD2=0x0A;              // DD2 10 ??
     else if (DD2 == 0) DD2 = 0x0D;          // DD2 13 ??
     DD2 = mask(DD2);
     display_temp(DD0, DD1, DD2, DD3);       // Infinite loop;
     } while (1);
 }

Lesson nr.13-7Segment and Push Button

Hardware setup:
Today Lesson is different from the last one, by the presence of two buttons and manually increment .
All 7-segment displays are connected to PORTB (RB0..RB7, segment A to RB0, segment B to RB1, etc.) with refresh via pins RA0..RA3 on PORTA.
If button on RA6 is presed the current number will be incremented by "1" and if button on RA7 is pressed the current number will be decremented by "1". Minimum number is 0000 and maximum number is 9999.



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:



Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.13:
'          Push Button & 7 Segment Display
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          This code demonstrates  displaying number on four 7-segment display (common
'          cathode), in multiplex mode. All 7-segment displays are connected to PORTB
'          (RB0..RB7, segment A to RB0, segment B to RB1, etc.) with refresh via pins
'          RA0..RA3 on PORTA. If button on RA6 is presed the current number will be
'          incremented by "1" and if button on RA7 is pressed the current number will
'          be decremented by "1".
'
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         mikroC PRO for PIC
'  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
'*******************************************************************************
*/
//***********Header*************/
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 int digit, number;
unsigned short portb_array[4];

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 > 15u)
 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
 TRISA = 0;
 TRISA6_bit = 1;
 TRISA7_bit = 1;                      // All port A pins are configured as outputs
 PORTA = 0;                           // Turn off displays
 TRISB = 0;                           // All port D pins are configured as outputs
 PORTB = 0;                           // Turn off all display segments
 
 number = 0;                          //initial value;
 
 do {
     if(Button(&PORTA,6,1,0)){
                              Delay_ms(200);
                              digit++ ;
                              number = number +1;
                              PORTB = number;
                              }
     if(Button(&PORTA,7,1,0)){
                              Delay_ms(200);
                              digit = digit -1;
                              number = number -1;
                              PORTB = number;
                              }
     if (number > 9999u)
     number = 0;

     digit = number % 10u;            //extract ones digit;
     portb_array[0] = mask(digit);    //and store it to PORTB array;
     digit = (number / 10u) % 10u;    //extract tens digit;
     portb_array[1] = mask(digit);    //and store it to PORTB array;
     digit = (number / 100u) % 10u;   //extract hundreds digit;
     portb_array[2] = mask(digit);    //and store it to PORTB array;
     digit = number / 1000u;          //extract thousands digit;
     portb_array[3] = mask(digit);    //and store it to PORTB array;
     } while(1);                      //Endless loop;
}                                     //End.

Lesson nr.12-Multiplexed 7Segment as counter mode

Hardware setup:
The basic technique is the same like the last lesson except fact that we have added a counter which counts between 0000 and 9999. Our counter increments with 1 second delay.
All 7-segment displays are connected to PORTB (RB0..RB7, segment A to RB0, segment B to RB1, etc.) with refresh via pins RA0..RA3 on PORTA.



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:



Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.12:
'          Multiplexed 7Segment as counter mode
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          This code demonstrates  displaying number on four 7-segment display (common
'          cathode), in multiplex mode. All 7-segment displays are connected to PORTB
'          (RB0..RB7, segment A to RB0, segment B to RB1, etc.) with refresh via pins
'          RA0..RA3 on PORTA. Number is incremented for 1 second. 
'          To define this project, a counter is added (counts from 0000 to 9999).
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  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
'*******************************************************************************
*/
//***********Header*************/
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 int digit, number;
unsigned short portb_array[4];

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
 number = 0;                          //initial value;
 
 do {
     digit = number % 10u;            //extract ones digit;
     portb_array[0] = mask(digit);    //and store it to PORTB array;
     digit = (number / 10u) % 10u;    //extract tens digit;
     portb_array[1] = mask(digit);    //and store it to PORTB array;
     digit = (number / 100u) % 10u;   //extract hundreds digit;
     portb_array[2] = mask(digit);    //and store it to PORTB array;
     digit = number / 1000u;          //extract thousands digit;
     portb_array[3] = mask(digit);    //and store it to PORTB array;

     Delay_ms(1000);                  // 1s delay;

     number ++ ;                      //increment number;
     if (number > 9999u)
     number = 0;
     } while(1);                      //Endless loop;
 }                                    //End.

Lesson nr.11-7Segment in multiplexed mode

Hardware setup:
In this experiment we will learn how to use more than one 7-segment Led display, connected simultaneously at the microcontroller port,  using multiplexing technique. In the current experiment will interface four digit common cathode to PORT B, the command part, and to PORT A, the control of digits. The multiplexing circuit is configured on the breadboard, being composed of four NPN transistor and some resistance. Electric scheme emphasize  multiplexing interconnection mode. Multiplexing principle is that all digits are connected in parallel port on the microcontroller and the microcontroller alternately displays between units tens hundreds and thousands digits, selecting one at a time. The switching among the digits is so fast that it gives the impression of simultaneous emission of light.
Number displayed on the digits is 1234.



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.11:
'          7Segment in multiplexed mode
'  Written by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will show how to implement the multiplexed mode 
'          to control 7 segmnet digits. PORTB will be used for character 
'          (RB0=a,RB1=b...RB6=g,RB7=dp)and for digits RA0=digit1...RA3=digit4.
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  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
'*******************************************************************************
*/
unsigned short mask(unsigned short num) // Mask for 7 segment common cathode;
{
 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 end
}
unsigned short digit1, digit2, digit3, digit4;
unsigned int number;

void main()                      // Main
{                     
 CMCON  |= 7;                    // Disable Comparators
 TRISB = 0;                      // Set PORTB direction to be output
 PORTB = 0xFF;                   // Turn OFF LEDs on PORTB
 TRISA = 0;
 PORTA = 0xFF;
 
 number = 1234;                  // value of number

 do {
     //Multiplexed mode;
     PORTB = digit4;
     RA0_bit = 0;
     RA1_bit = 0;
     RA2_bit = 0;
     RA3_bit = 1;                // Select Thousands Digit
     delay_ms(5);                // 5ms delay
     PORTB = digit3;
     RA0_bit = 0;
     RA1_bit = 0;
     RA2_bit = 1;                // Select Hundreds Digit
     RA3_bit = 0;
     delay_ms(5);                // 5ms delay
     PORTB = digit2;
     RA0_bit = 0;
     RA1_bit = 1;                // Select Tens Digit
     RA2_bit = 0;
     RA3_bit = 0;
     delay_ms(5);                // 5ms delay
     PORTB = digit1;
     RA0_bit = 1;                // Select Ones Digit
     RA1_bit = 0;
     RA2_bit = 0;
     RA3_bit = 0;
     delay_ms(5);                // 5ms delay
     
     digit1 = number%10;         // Extract Ones Digit
     digit1 = mask(digit1);
     digit2 = (number/10)%10;    // Extract Tens Digit
     digit2 = mask(digit2);
     digit3 = (number/100)%10;   // Extract Hundreds Digit
     digit3 = mask(digit3);
     digit4 = (number/1000);     // Extract Thousands Digit
     digit4 = mask(digit4);
     } while(1);                 // Infinite loop
}