Menu

all about electronic and microcontrollers
Showing posts with label PCB. Show all posts
Showing posts with label PCB. 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;
   }
  }
}

Saturday, March 29, 2014

Real Time Clock [DS1307 with Set Functions] & DS18B20

Hello dear fellows, today I will share with you this amazing project which will highlights what can be done with DS1307.
The Real Time Clock (RTC) chip produced by Maxim is a popular and relatively low cost solution for creating a room clock.

Features:
  1. Real-Time Clock (RTC) Counts Seconds, Minutes, Hours, Date of the Month, Month, Day of the week, and Year with Leap-Year Compensation Valid Up to 2100.
  2. 56-Byte, Battery-Backed, General-Purpose RAM with Unlimited Writes.
  3.  I2C Serial Interface.
  4. Programmable Square-Wave Output Signal.
  5.  Automatic Power-Fail Detect and Switch Circuitry.
  6. Consumes Less than 500nA in Battery-Backup Mode with Oscillator Running.
  7.  Operating temperature range for commercial use only: 0°C to +70°C.
  8. Optional Industrial Temperature Range: -40°C to +85°C.
  9. Available in 8-Pin Plastic DIP or SO.
As can be seen from it's datasheet, the communications are achieved via I2C (designed by Philips) protocol.

Hardware setup:
In the current article I intend to display the clock information and room temperature, on the LCD with 2x16 characters. Also trough four buttons, I will try to be able to set all the times variable, stored, in DS1307 chip.
Physical realization is carried out on the breadboard with 2420 dots.





Trough this video I would like to let you know precisely, how are things going.


Below I present the timing diagram for I2C signal transmitted on pins 5-6 of the DS1307.

Data Transfer on I2C Serial Bus.

Pin Configurations.
The diagram block.


For more details, please study the DS1307 datasheet.

Circuit Diagram:
Difficulty level of the electronic scheme, is low. The microcontroller used is PIC16F876A.
S1 is the master reset button, R1 is the resistor of pull-up button.
Cristal quartz by 8 MHz, is used.
ICSP connector is used to program the microcontroller.
Trough R7 we can adjust the contrast for LCD with 2x16 characters.
R6 adjusts the current through the LED LCD (light intensity of it).
R2-R5, R8-R10 are resistors for pull-up.

I personally designed the physical pcb circuit for DS1307, through the five pins,  pcb communicate with the breadboard in this way (GND, SQW, SCL, SDA, 5VDC). In this project i didn't use SQW pin.


The electronic scheme is built in Eagle Cad , free version.

Software:
The program is written in mikroC Pro for PIC 2013 (version v6.0.0).
Below is my software version:
/*
'*******************************************************************************
'  Project name: Real Time Clock [DS1307 with Set Functions] & DS18B20
'  Description:
'          Trough the current experiment we wish to succed the next task:
'          Display on LCD 2x16 character the clock and room temperature.
'          Setting trough four buttons: the minutes, hours, date of the month,
'          month, day of the week, and year.
'
'          Our clock displays as shown below(but just in display time,
'          not in set mode).
'          Ex. of viewing on 2x16 LCD characters:
'          Display time, mode:             Set time, mode (cursor on):
'          ------------------              ------------------
'          |Sat, 03 Dec 2011|              |Sat, 03 12  2011|
'          |21:32:03 +26,1*C|              |21:32:03        |
'          ------------------              ------------------
'
'          Hardware configuration is:
'             IC ds1307 is connected with our microcontroller trough RC3=SCL,
'             RC4=SDA (I2C Connections), RB0,RB1,RB4-RB7 are assigned to LCD (2x16)
'             DS18B20 is assigned to RC7,
'             Buttons Menu: RC0= Increment value,
'                           RC1= Decrement value,
'                           RC2= Change cursor position,
'                           RC5= Enter.(It goes to set functions or exit from set
'                                functions)
'  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.0.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
'*******************************************************************************
*/

// LCD module connections
sbit LCD_RS at RB0_bit;                 // LCD_RS assigned to PORT RB0;
sbit LCD_EN at RB1_bit;                 // LCD_EN assigned to PORT RB1;
sbit LCD_D4 at RB4_bit;                 // LCD_D4 assigned to PORT RB4;
sbit LCD_D5 at RB5_bit;                 // LCD_D5 assigned to PORT RB5;
sbit LCD_D6 at RB6_bit;                 // LCD_D6 assigned to PORT RB6;
sbit LCD_D7 at RB7_bit;                 // LCD_D7 assigned to PORT RB7;

sbit LCD_RS_Direction at TRISB0_bit;    // LCD_RS assigned to TRIS B0;
sbit LCD_EN_Direction at TRISB1_bit;    // LCD_EN assigned to TRIS B1;
sbit LCD_D4_Direction at TRISB4_bit;    // LCD_D4 assigned to TRIS B4;
sbit LCD_D5_Direction at TRISB5_bit;    // LCD_D5 assigned to TRIS B5;
sbit LCD_D6_Direction at TRISB6_bit;    // LCD_D6 assigned to TRIS B6;
sbit LCD_D7_Direction at TRISB7_bit;    // LCD_D7 assigned to TRIS B7;
// End LCD module connections

unsigned char sec,min1,hr,week_day,day,mn,year;
//--------------------- Reads time and date information from RTC (DS1307)
void Read_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year)
{
 I2C1_Start();                    // Issue start signal
 I2C1_Wr(0xD0);                   // Address DS1307, see DS1307 datasheet
 I2C1_Wr(0);                      // Start from address 0
 I2C1_Repeated_Start();           // Issue repeated start signal
 I2C1_Wr(0xD1);                   // Address DS1307 for reading R/W=1
 *sec =I2C1_Rd(1);                // Read seconds byte
 *min =I2C1_Rd(1);                // Read minutes byte
 *hr =I2C1_Rd(1);                 // Read hours byte
 *week_day =I2C1_Rd(1);           // Read week day byte
 *day =I2C1_Rd(1);                // Read day byte
 *mn =I2C1_Rd(1);                 // Read mn byte
 *year =I2C1_Rd(0);               // Read Year byte
 I2C1_Stop();                     // Issue stop signal
}
//-----------------write time routine------------------
void Write_Time(char minute, char hour ,char weekday,char day,char month,char year)
{
 char tmp1, tmp2;

 tmp1 = minute / 10;               //Write tens of minute
 tmp2 = minute % 10;               //Write unit of minute
 minute = tmp1 * 16 + tmp2;        //Includes all value

 tmp1 = hour / 10;                 //Write tens of hour
 tmp2 = hour % 10;                 //Write unit of hour
 hour = tmp1 * 16 + tmp2;          //Includes all value

 tmp1 = weekday / 10;              //Write tens of weekday
 tmp2 =  weekday % 10;             //Write unit of weekday
 weekday = tmp1 *16 +tmp2;         //Includes all value

 tmp1 = day / 10;                  //Write tens of day
 tmp2 =  day % 10;                 //Write unit of day
 day = tmp1 *16 +tmp2;             //Includes all value

 tmp1 = month / 10;                //Write tens of month
 tmp2 =  month % 10;               //Write unit of month
 month = tmp1 *16 +tmp2;           //Includes all value

 tmp1 = year / 10;                 //Write tens of year
 tmp2 =  year % 10;                //Write unit of year
 year = tmp1 *16 +tmp2;            //Includes all value

 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(weekday);      // write 6 - Saturday (REG3)
 I2C1_Wr(day);          // write 14 to date word (REG4)
 I2C1_Wr(month);        // write 5 (May) to month word (REG5)
 I2C1_Wr(year);         // 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
}
//-------------------- Formats date and time---------------------
void Transform_Time(char  *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *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);
 }
//------------------------Display time---------------------------
char *txt,*mny;
void Display_Time(char sec, char min, char hr, char week_day, char day, char mn, char year)
{
 switch(week_day)
 {
  case 1: txt="Mon"; break;       // Monday;
  case 2: txt="Tue"; break;       // Tuesday;
  case 3: txt="Wed"; break;       // Wednesday;
  case 4: txt="Thu"; break;       // Thursday;
  case 5: txt="Fri"; break;       // Friday;
  case 6: txt="Sat"; break;       // Saturday;
  case 7: txt="Sun"; break;       // Sunday;
  }

 LCD_Out(1, 1,txt);
 LCD_chr(1, 4,',');

 switch(mn)
 {
  case  1: mny="Jan"; break;
  case  2: mny="Feb"; break;
  case  3: mny="Mar"; break;
  case  4: mny="Apr"; break;
  case  5: mny="May"; break;
  case  6: mny="Jun"; break;
  case  7: mny="Jul"; break;
  case  8: mny="Aug"; break;
  case  9: mny="Sep"; break;
  case 10: mny="Oct"; break;
  case 11: mny="Nov"; break;
  case 12: mny="Dec"; break;
  }

 Lcd_Chr(1, 6, (day / 10) + 48);    // Print tens digit of day variable
 Lcd_Chr(1, 7, (day % 10) + 48);    // Print oness digit of day variable
 Lcd_Out(1, 9,mny);
 Lcd_out(1,13,"20");
 Lcd_Chr(1,15, (year / 10)  + 48);  // we can set year 00-99 [tens]
 Lcd_Chr(1,16, (year % 10)  + 48);  // we can set year 00-99 [ones]
 Lcd_Chr(2, 1, (hr / 10)  + 48);
 Lcd_Chr(2, 2, (hr % 10)  + 48);
 Lcd_Chr(2, 3,':');
 Lcd_Chr(2, 4, (min / 10) + 48);
 Lcd_Chr(2, 5, (min % 10) + 48);
 Lcd_Chr(2, 6,':');
 Lcd_Chr(2, 7, (sec / 10) + 48);
 Lcd_Chr(2, 8, (sec % 10) + 48);
 }
//-------------------Display Time in Set mode--------------------
char minute1,hour1,weekday1,month1;
char minute,hour,weekday,day1,month,year1;
void Display_Time_SetMode()
{
 switch(weekday1)
 {
  case 1: txt="Mon"; break;       // Monday;
  case 2: txt="Tue"; break;       // Tuesday;
  case 3: txt="Wed"; break;       // Wednesday;
  case 4: txt="Thu"; break;       // Thursday;
  case 5: txt="Fri"; break;       // Friday;
  case 6: txt="Sat"; break;       // Saturday;
  case 7: txt="Sun"; break;       // Sunday;
  }

 LCD_Out(1, 1,txt);
 LCD_chr(1, 4,',');

 Lcd_Chr(1, 6, (day1 / 10)   + 48);    // Print tens digit of day variable
 Lcd_Chr(1, 7, (day1 % 10)   + 48);    // Print oness digit of day variable
 Lcd_chr(1,10, (month1 / 10) + 48);    // Print tens digit of month variable
 Lcd_chr(1,11, (month1 % 10) + 48);    // Print oness digit of month variable
 Lcd_out(1,13,"20");
 Lcd_Chr(1,15, (year1 / 10)  + 48);    // Print tens digit of year variable
 Lcd_Chr(1,16, (year1 % 10)  + 48);    // Print oness digit of year variable
 Lcd_Chr(2, 1, (hour1 / 10)  + 48);    // Print tens digit of hour variable
 Lcd_Chr(2, 2, (hour1 % 10)  + 48);    // Print oness digit of hour variable
 Lcd_Chr(2, 3,':');
 Lcd_Chr(2, 4, (minute1 / 10) + 48);   // Print tens digit of minute variable
 Lcd_Chr(2, 5, (minute1 % 10) + 48);   // Print oness digit of minute variable
 Lcd_Chr(2, 6,':');
 Lcd_Chr(2, 7, (0 / 10) + 48);
 Lcd_Chr(2, 8, (0 % 10) + 48);
}

char SPos;
//----------------------Move cursor routine----------------------
char index;
void movecursor()
{
 char i,moveto;
 if(SPos==0)
 lcd_cmd(_lcd_first_row);  // set weekday;
 if(SPos==1)
 lcd_cmd(_lcd_first_row);  // set day;
 if(SPos==2)
 lcd_cmd(_lcd_first_row);  // set month;
 if(SPos==3)
 lcd_cmd(_lcd_first_row);  // set year;
 if(SPos==4)
 lcd_cmd(_lcd_second_row); // set hours;
 if(SPos==5)
 lcd_cmd(_lcd_second_row); // set minutes;

 moveto = 2;
 switch(index)
 {
  case 0: moveto = 2;break;
  case 1: moveto = 6;break;
  case 2: moveto =10;break;
  case 3: moveto =15;break;
  case 4: moveto = 1;break;
  case 5: moveto = 4;break;
  }
  for(i=1; i<= moveto; i++)
  lcd_cmd(_lcd_move_cursor_right);
}
//------------Start Buttons routine--------------;
char setuptime=0;
void Press_Switch()
{
 if(setuptime)
 {
  if(Button(&portc,2,1,0))         // If buttons at port c2 is pressed
  {
   delay_ms(200);
   SPos++;
   if(SPos>5)
   SPos=0;
   index++;
   if(index > 5)
   index=0;
   movecursor();
   }
  //-----------------------------case mode to set all values---------------------
  switch(SPos)
  {
   case 0: if(button(&portc,0,1,0))       // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            weekday1++;
            if(weekday1 > 7)
            weekday1=1;
            Display_Time_SetMode();
            index=0;
            movecursor();
            }

           if(button(&portc,1,1,0))       // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            weekday1--;
            if(weekday1 < 1)
            weekday1=7;
            Display_Time_SetMode();
            index=0;
            movecursor();
            }
           break;
   case 1: if(button(&portc,0,1,0))       // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            day1++;
            if(day1 > 31)
            day1 = 1;
            Display_Time_SetMode();
            index=1;
            movecursor();
            }

           if(button(&portc,1,1,0))        // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            day1--;
            if(day1 < 1)
            day1 = 31;
            Display_Time_SetMode();
            index=1;
            movecursor();
            }
           break;
   case 2: if(button(&portc,0,1,0))         // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            month1++;
            if(month1 > 12)
            month1 = 1;
            Display_Time_SetMode();
            index=2;
            movecursor();
            }

           if(button(&portc,1,1,0))          // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            month1--;
            if(month1 < 1)
            month1 = 12;
            Display_Time_SetMode();
            index=2;
            movecursor();
            }
           break;
   case 3: if(button(&portc,0,1,0))           // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            year1++;
            if(year1 > 99)
            year1 = 1;
            Display_Time_SetMode();
            index=3;
            movecursor();
            }

           if(button(&portc,1,1,0))           // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            year1--;
            if(year1 < 1)
            year1 = 99;
            Display_Time_SetMode();
            index=3;
            movecursor();
            }
           break;
   case 4: if(button(&portc,0,1,0))            // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            hour1++;
            if(hour1 > 23)
            hour1 = 0;
            Display_Time_SetMode();
            index=4;
            movecursor();
            }

           if(button(&portc,1,1,0))            // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            hour1--;
            if(hour1 > 23)
            hour1 = 0;
            Display_Time_SetMode();
            index=4;
            movecursor();
            }
           break;
   case 5: if(button(&portc,0,1,0))            // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            minute1++;
            if(minute1 > 59)
            minute1 = 0;
            Display_Time_SetMode();
            index=5;
            movecursor();
            }

           if(button(&portc,1,1,0))             // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            minute1--;
            if(minute1 > 59)
            minute1 = 0;
            Display_Time_SetMode();
            index=5;
            movecursor();
            }
           break;
   }                            // end "if is in switch mode"
  }                             // end "if is in setup"

 if(button(&portc,5,1,0))                      // If buttons at port c5 is pressed
 {
  Delay_ms(200);
  setuptime = !setuptime;
  if(SetupTime)
  {
   lcd_cmd(_lcd_clear);
   lcd_cmd(_lcd_blink_cursor_on);
   weekday1=week_day;
   hour1=hr;
   minute1=min1;
   day1=day;
   month1=mn;
   year1=year;
   Display_Time_SetMode();
   SPos=0;
   index=0;
   movecursor();
   }
   else
   {
   Lcd_Cmd(_Lcd_clear);
   lcd_cmd(_lcd_cursor_off);
   weekday=weekday1;
   hour=hour1;
   minute=minute1;
   day=day1;
   month=month1;
   year=year1;
   Write_time(minute,hour,weekday,day,month,year);
   }
  }
 }
//----------------------End Buttons Routine-------------------
//------------------Temperature sensor routines---------------
const unsigned short TEMP_RESOLUTION = 12;     // 9 for DS1820 and 12 for DS18B20
char *text = "000,0";
unsigned temp;
void Display_Temperature(unsigned int temp2write)
{
 const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
 char temp_whole;
 unsigned int temp_fraction;
 unsigned short isNegative = 0x00;

 // Check if temperature is negative
 if (temp2write & 0x8000)
 {
  text[0] = '-';
  temp2write = ~temp2write + 1;
  isNegative = 1;
  }
  // Extract temp_whole
  temp_whole = temp2write >> RES_SHIFT ;
  // Convert temp_whole to characters
  if (!isNegative){
  if (temp_whole/100)
  text[0] = temp_whole/100  + 48;                // Extract hundreds digit
  else
  text[0] = '+';
  }
  text[1] = (temp_whole/10)%10 + 48;             // Extract tens digit
  text[2] =  temp_whole%10     + 48;             // Extract ones digit
  // Extract temp_fraction and convert it to unsigned int
  temp_fraction  = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;
  // Convert temp_fraction to characters
  text[4] =  temp_fraction/1000 + 48;         // Extract thousands digit
  // Print temperature on LCD
  Lcd_Out(2, 10,text);
  lcd_chr(2, 15,0xB2);                        // Ascii code for degrees symbol;
  Lcd_chr(2, 16,'C');                         // Show symbol "C" from Celsius
}
//----------------Read and display Temperature from DS18B20--------------
void Read18b20()
{
 //--- Perform temperature reading
 Ow_Reset(&PORTC, 7);                           // Onewire reset signal;
 Ow_Write(&PORTC, 7, 0xCC);                     // 0xCC Issue command SKIP_ROM;
 Ow_Write(&PORTC, 7, 0x44);                     // Issue command CONVERT_T;
 Delay_us(700);                                 // delay 0,7s (required for signal
                                                // processing);
 Ow_Reset(&PORTC, 7);                           // Onewire reset signal;
 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, read Byte
                                                // 0 from Scratchpad;
 temp = (Ow_Read(&PORTC, 7) << 8) + temp;       // Then read Byte 1 from Scratchpad
                                                // and shift 8 bit left and add the Byte 0;
 //--- Format and display result on Lcd
 Display_Temperature(temp);                     // Call Display_Temperature;
 }
//------------------Temperature sensor routines---------------
void Init_Main()
{
 CMCON |=7;             //TURN OFF ANALOGUE COMPARATOR AND MAKE PORTA TO DIGITAL I/O;

 I2C1_Init(100000);         // initialize I2C
 Lcd_Init();                // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
 Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off

 Display_Time(sec, min1, hr, week_day, day, mn, year);

 !setuptime=1;
 index=0;
 SPos=0;
 }
//-----------------Here we have the Main Routine----------------
void main()
{
 Init_Main();
 while (1)                                                 // While loop
 {
  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); // Transform time
  Press_Switch();                                          // Check buttons;
  if(!setuptime)
  {
   Display_Time(sec, min1, hr, week_day, day, mn, year);
   Read18b20();
   }
  }
}

Sunday, July 24, 2011

Dot Matrix Led 8x8 & MAX 7219

In this article we will discuss about functions of MAX 7219, created by the Maxim company. This IC (Integrated Circuit) could help as, when we whant to work with digits and LEDs.
At the designing of this IC,was wanted fulfillment of the following functions:
  • Control of eight digits, made ​​with LED technology;
  • Common cathode configuration;
  • Communication via SPI, with a slew-rate limited on the segment driver, to reduce EMI (Electromagnetic Interference).
Of course Max7219 may be used for handling an matrix of LEDs, up to 8x8 resolution, bar-graph displays or control up to 64 LEDs, individually.
Included on-chip are a BCD code-B decoder, multiplex scan circuitry, segment and digit drivers, and an 8x8 static RAM that stores each digit. Only one external resistor is required to set the segment current for all LEDs.

Hardware setup:
Physical realization is carried out on the breadboard with 2420 dots. The example made ​​by me can be studied below.

Electronic scheme, in action.

Trough video below I whant to demonstrate that things can be put in motion.


In a dot led matrix display, multiple LEDs are connected together in row and columns. This connection is established to reduce the number of pins needed to manipulate them.
In the current article we will use a 8x8 LED matrix, which would require 64-pin I/O, one for each pixel.
Connecting all the anodes together (from R1 to R8) and cathodes in column (from C1 to C8), the required number of I/O pins, is reduced to 16. Each LED is accessed by its row and column number.
In the figure below, if R5 is in in 1 logic and C3 is in 0 logic, the LED on line 5 column 3 will be turned on.
The characters will be displayed by fast scanning of each row and column.

Dot Matrix Led 8x8
The structure of dot matrix LED 8x8.

The table below shows the logic levels, which are applied to rows and columns, to display the character "X". At the bottom of the table we have the hex code for it.

The logic levels
Logical level of 8x8 matrix.

The image above shows pins connections for my dot matrix led 8x8.

Serial-Data Format (16 Bits):

Serial-Data Format

For the MAX7219, serial data at DIN, sent in 16-bit packets, is shifted into the internal 16-bit shift register with each rising edge of CLK regardless of the state of
LOAD. For the MAX7221, CS must be low to clock data in or out. The data is then latched into either the digit or control registers on the rising edge of LOAD/CS.
LOAD/CS must go high concurrently with or after the 16th rising clock edge, but before the next rising clock edge or data will be lost. Data at DIN is propagated
through the shift register and appears at DOUT 16.5 clock cycles later. Data is clocked out on the falling edge of CLK. Data bits are labeled D0–D15 (picture from above). D8–D11 contain the register address. D0–D7 contain the data, and D12–D15 are “don’t care” bits. The first received is D15, the most significant bit (MSB).

Register Address Map:

Address Map

For more details, please study the MAX7219 datasheet.

Circuit Diagram:
Difficulty level of the electronic scheme, is low. Microcontroller used in the current project is PIC16F876A, this MCU supports SPI communication.
S1 is the master reset button, R3 is the resistor of pull-up button.
Cristal quartz by 8 MHz, is used.
R1 represent the pull-up resistor for "LOAD/CS".
R2 adjusts the current on the segment, for all digits.
Our matrix LED 8x8 is in common catode configuration.

Electronic Schematic
The electronic schematic.

The electronic scheme is built in Eagle Cad, free version:

Software:
The program is written in mikroC Pro for PIC 2011 (version v4.60). To store the entire alphabet and symbols, the column 0 and 7 are not used, in case you opt for a microcontroller with more RAM, you can add columns 0 and 7 and you will enjoy the entire matrix.
/*
'*******************************************************************************
'  Project name: PIC16F876A & MAX7219 For 8x8 LED Display
'  Description:
'          Trough the current experiment we wish to succed the next task:
'          Display on 8x8 Led matrix, the alphabet. The sequence between letters,
'          will have one second delay.
'  Written by:
'          Mark &
'          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:             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
'*******************************************************************************
*/

// For more space, we don't need byte 0 and byte 7.
// We have stripped them out, if/when we have a need and a bigger PIC,
// then we can put them back if we want.

// Here we define row values for each of the six columns corresponding to the
// Alphabet, from  A through Z.
unsigned const short Alphabet[156]={
                                     0x7f, 0x88, 0x88, 0x88, 0x88, 0x7f,  // A
                                     0xff, 0x91, 0x91, 0x91, 0x91, 0x6e,  // B
                                     0x7e, 0x81, 0x81, 0x81, 0x81, 0x42,  // C
                                     0xff, 0x81, 0x81, 0x81, 0x81, 0x7e,  // D
                                     0x81, 0xff, 0x91, 0x91, 0x91, 0x91,  // E
                                     0x81, 0xff, 0x91, 0x90, 0x90, 0x80,  // F
                                     0x7e, 0x81, 0x81, 0x89, 0x89, 0x4e,  // G
                                     0xff, 0x10, 0x10, 0x10, 0x10, 0xff,  // H
                                     0x00, 0x81, 0xff, 0xff, 0x81, 0x00,  // I
                                     0x06, 0x01, 0x81, 0xfe, 0x80, 0x00,  // J
                                     0x81, 0xff, 0x99, 0x24, 0xc3, 0x81,  // K
                                     0x81, 0xff, 0x81, 0x01, 0x01, 0x03,  // L
                                     0xff, 0x60, 0x18, 0x18, 0x60, 0xff,  // M
                                     0xff, 0x60, 0x10, 0x08, 0x06, 0xff,  // N
                                     0x7e, 0x81, 0x81, 0x81, 0x81, 0x7e,  // O
                                     0x81, 0xff, 0x89, 0x88, 0x88, 0x70,  // P
                                     0x7e, 0x81, 0x85, 0x89, 0x87, 0x7e,  // Q
                                     0xff, 0x98, 0x98, 0x94, 0x93, 0x61,  // R
                                     0x62, 0x91, 0x91, 0x91, 0x91, 0x4e,  // S
                                     0xc0, 0x81, 0xff, 0xff, 0x81, 0xc0,  // T
                                     0xfe, 0x01, 0x01, 0x01, 0x01, 0xfe,  // U
                                     0xfc, 0x02, 0x01, 0x01, 0x02, 0xfc,  // V
                                     0xff, 0x02, 0x04, 0x04, 0x02, 0xff,  // W
                                     0xc3, 0x24, 0x18, 0x18, 0x24, 0xc3,  // X
                                     0xc0, 0x20, 0x1f, 0x1f, 0x20, 0xc0,  // Y
                                     0xc3, 0x85, 0x89, 0x91, 0xa1, 0xc3,  // Z
                                     };

 unsigned const short Symbols[114]={
                                    0x00, 0x3c, 0x42, 0x81, 0x00, 0x00,   // (
                                    0x00, 0x00, 0x81, 0x42, 0x3c, 0x00,   // )
                                    0x00, 0x00, 0xff, 0x81, 0x00, 0x00,   // [
                                    0x00, 0x00, 0x81, 0xff, 0x00, 0x00,   // ]
                                    0x00, 0x18, 0xe7, 0x81, 0x00, 0x00,   // {
                                    0x00, 0x00, 0x81, 0xe7, 0x18, 0x00,   // }
                                    0x00, 0x18, 0x24, 0x42, 0x81, 0x00,   // <
                                    0x00, 0x81, 0x42, 0x24, 0x18, 0x00,   // >
                                    0x00, 0x03, 0x0c, 0x30, 0xc0, 0x00,   // /
                                    0x00, 0xc0, 0x30, 0x0c, 0x03, 0x00,   // \
                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   //
                                    0x00, 0x00, 0xfd, 0xfd, 0x00, 0x00,   // !
                                    0x60, 0x80, 0x8d, 0x8d, 0x90, 0x60,   // ?
                                    0x42, 0x24, 0xff, 0xff, 0x24, 0x42,   // *
                                    0x24, 0xff, 0x24, 0x24, 0xff, 0x24,   // #
                                    0x62, 0x91, 0xff, 0xff, 0x91, 0x4e,   // $
                                    0x66, 0x99, 0x99, 0x66, 0x09, 0x00,   // &
                                    0x42, 0xa4, 0x48, 0x12, 0x25, 0x42,   // %
                                    0x20, 0x3f, 0x20, 0x20, 0x3e, 0x21,   // pi
                                    };

// Serial 8x8 Matrix Display connections.
sbit Chip_Select at RC0_bit;
sbit Chip_Select_Direction at TRISC0_bit;
// End Serial 8x8 Matrix Display connections.

// Here we set the configuration of max7219.
void max7219_init1()
{
Chip_Select = 0;       // SELECT MAX
SPI1_write(0x09);      // BCD mode for digit decoding
SPI1_write(0x00);
Chip_Select = 1;       // DESELECT MAX

Chip_Select = 0;       // SELECT MAX
SPI1_write(0x0A);
SPI1_write(0x0F);      // Segment luminosity intensity
Chip_Select = 1;       // DESELECT MAX

Chip_Select = 0;       // SELECT MAX
SPI1_write(0x0B);
SPI1_write(0x07);      // Display refresh
Chip_Select = 1;       // DESELECT MAX

Chip_Select = 0;       // SELECT MAX
SPI1_write(0x0C);
SPI1_write(0x01);      // Turn on the display
Chip_Select = 1;       // DESELECT MAX

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

// This is write Byte function.
void Write_Byte(unsigned short myColumn, unsigned short myValue)
{
 Chip_Select = 0;       // select max7219.
 SPI1_write(myColumn);  // send myColumn value to max7219 (digit place).
 SPI1_write(myValue);   // send myValue value to max7219 (digit place).
 Chip_Select = 1;       // deselect max7219.
 }

// This is clear matrix function.
void Clear_Matrix(void)
{
unsigned short x;

for(x=1;x<9;x++)
{
  Write_Byte(x,0x00);
  }
}

void Write_Char(char myChar)
{
unsigned short Column, Start_Byte;
// We will use only uppercase characters, so we will start from 65
// (look at the ascii chart), with an offset of 6, becouse we are using only 6
// bytes for each character.

// Clear the display first.
Clear_Matrix();

// The next line defines our byte, from which to start the array.
Start_Byte = (myChar - 65) * 6;     // 65 represents the letter "A" in ASCII code.

// We are using only columns from 2 through 7 for displaying the character.
for(Column=2;Column<8;Column++)
{
  Write_Byte(Column, Alphabet[Start_Byte++]);
  }
}

// This is write char function.
void Write_Symbol(char mysymbols)
{
unsigned short Column1, Start_Byte1;
// We will use only uppercase characters, so we will start from 65
// (look at the ascii chart), with an offset of 6, becouse we are using only 6
// bytes for each character.

// Clear the display first.
Clear_Matrix();

// The next line defines our byte, from which to start the array.
Start_Byte1 = (mysymbols-0) * 6 ;

// We are using only columns from 2 through 7 for displaying the character.
for(Column1=2;Column1<8;Column1++)
{
  Write_Byte(Column1, Symbols[Start_Byte1++]);
  }
}

// Here we have the main function.
void main()
{
unsigned int x,y;

Chip_Select_Direction = 0;    // Set RC0 pin as output.
SPI1_init();                  // Initialize SPI1 module.

max7219_init1();              // initialize  max7219.

do                            // infinite loop.
{
  // You can write the characters this way, one at a time.

  /*
  Write_Char('R');
  Delay_ms(1000);
  Write_Char('A');
  Delay_ms(1000);
  Write_Char('D');
  Delay_ms(1000);
  Write_Char('U');
  Delay_ms(1000);
  */
  // or

 for(x=65;x<=90;x++)    // Increment with 1, from 65 until 90.
  {
   Write_Char(x);
   Delay_ms(1000);      // This is our delay, between two consecutive character.
   }

  Clear_Matrix();       // Clear the Matrix display;
  delay_ms(500);

  for(y=0;y<=18;y++)
  {
   Write_Symbol(y);     // This is our delay, between two consecutive character.
   Delay_ms(1000);
   }

  }while(1);            // do forever.
}

Sunday, October 17, 2010

Printed Circuit Board (P.C.B)

Creating printed circuit boards (PCB) with the toner transfer method. The films speak for themselves:














Creating printed circuit boards (PCB) with the ultraviolet (UV) method. The films speak for themselves: