Tuesday, December 14, 2010

C codes for 8-Bit Microcontrollers

Blog Posted By:
  Muhammad Muzammil
  Lecturer
  International Islamic University, Islamabad, PAKISTAN


Education: 
   PhD Electronic Engg in progress From IIUI, Islamabad, PAKISTAN
   M.Sc Electrical Engg (Digital Techniques) in 2014 From UET, Taxila PAKISTAN
   B.Sc Electrical Engg (Electronics) in 2009 From FUUAST, Islamabad, PAKISTAN




C Codes for P18F452 Microcontroller:
  • Battery Charger in MikroC

Circuit Diagram for Battery Charger

Code:


/*
  Battery Indicator based on PIC18f452
  MUHAMMAD MUZAMMIL, Compiler MikroC
*/


unsigned char Message1[] = "BATERY INDICATOR";
unsigned int ADC_Value;


void main(void)
{
/*///////////CONFIGURE ADC \\\\\\\\\\\\\\\\\\\\*/
  ADCON1 = 0x80;             // Configure analog inputs and Vref
  TRISA  = 0xFF;             // PORTA configure as input
  TRISD.F0 = 0;              // PortD bit 0 configure as output
  PORTD.F0 = 0;              // PortD bit 0 of low


/*///////////CONFIGURE LCD \\\\\\\\\\\\\\\\\\\\*/
  Lcd_Init(&PORTB);          // Configure PortB for LCD
  Lcd_Cmd(Lcd_Clear);        // CLEAR display
  Lcd_Cmd(Lcd_CURSOR_OFF);   // Cursor off


/*/////////////SHOW BATTERY STATUS\\\\\\\\\\\\\*/
  while(1)
  {
    ADC_Value = ADC_Read(0);    //Read ADC on Channel 0
    delay_ms(100);    
    if(ADC_Value > 0x2A4)      // Check for  3.3V
    {
        Lcd_Out(1,1,Message1);
        Lcd_Out(2,1,"  BATTERY FULL");
        delay_ms(1000);
    }


    if(ADC_Value <= 0x2A4 && ADC_Value > 0x197)  // 1.98V > Batt > 3.3V
    {
        Lcd_Out(1,1,Message1);
        Lcd_Out(2,1," PLEASE CHARGE");
        delay_ms(1000);
    }


    if(ADC_Value <= 0x197)                      // Check for Batt V < 1.98V
    {
        Lcd_Out(1,1,Message1);
        Lcd_Out(2,1," BATTERY EMPTY");
        PORTD.F0 = 1;
        delay_ms(200);
        PORTD.F0 = 0;
        delay_ms(200);
    }
  }                                             //End while(1)
}                                               //End Main




  • 1kHz Square Wave generation in MikroC
Code:
/*
  1kHz Square Wave Generator based on PIC18f452 using Timer0
  MUHAMMAD MUZAMMIL,
*/

void Delay(void);
void main()
{
  TRISD.F0 = 0;              // PORTD is output
  while(1)
  {
    Delay();
    PORTD.F0 = ~PORTD.F0;    // Toggle bit 0 of PORTD
  }
}


void Delay(void)
{


  INTCON.TMR0IF = 0;         // Timer0 Interrupt Flag is Down
  T0CON.TMR0ON = 0;          // Timer0 is off
                             // Crystal Freq = 10MHz
                             // 10M/4 = 0.25M = 0.4u sec
                             // 1/1kHz = 1mSec
                             // 1m/2 = 0.5m (Low+High=1 cycle)
                             // 0.5mSec / 0.4uSec = 1250
  TMR0H = 0xFB;              //65535-1250 =  64286 = 0XFB1E
  TMR0L = 0x1E;
  T0CON = 0x88;              //Prescalar configured to 1:64, Enable Timer0
  while(INTCON.TMR0IF != 1); //wait for rise of timer0 Interrupt flag
}

Schematic Diagram: Square Wave Generator


  • Serial Port Access (USART) using MikroC
Code:
/*

    Author: Muhammad Muzammil, PhD Electronic Engineering (In-progress)
    Device: PIC18F452
    Compiler: MikroC
    Code for Serial Communication through PIC
   
*/

void main(void)
{
  char strings[] = "MUHAMMAD MUZAMMIL";
  unsigned int data;
  unsigned int i;

///*///////////////Initialized USART \\\\\\\\\\\\\\\\\\\\ */
  USART_init(9600);             //baud rate is 9600

///*///////////////Transmit String \\\\\\\\\\\\\\\\\\\\ */
  for(i=0; i<17; i++)
  {
     Usart_Write(strings[i]);
     delay_ms(50);
  }

///*////////Receive from Terminal & Transmit \\\\\\\\\\ */
  while(1)
  {
    if (Usart_Data_Ready())     // Check if Data  is ready for receiving
    {
         data = Usart_Read();
         delay_ms(50);
         Usart_Write(data);
    }
  }
}


Circuit Diagram: USART
Transistor and Diode Tester using PIC18F452

Diode and Transistor tester can be designed with the PIC18F452 using its general feature. Following is the MikroC code for the above project:

/*
Project: Diode and Transistor Tester
Author: Muhammad Muzammil
Target Device: PIC 18F452
Compiler: MikroC
Crystal Freq: 10MHz
08th Jan, 2011
PhD Electronic Engineering (In-progress)
*/

// LCD connections
sbit LCD_RS at RC4_bit;
sbit LCD_EN at RC5_bit;
sbit LCD_D4 at RC0_bit;
sbit LCD_D5 at RC1_bit;
sbit LCD_D6 at RC2_bit;
sbit LCD_D7 at RC3_bit;
sbit LCD_RS_Direction at TRISC4_bit;
sbit LCD_EN_Direction at TRISC5_bit;
sbit LCD_D4_Direction at TRISC0_bit;
sbit LCD_D5_Direction at TRISC1_bit;
sbit LCD_D6_Direction at TRISC2_bit;
sbit LCD_D7_Direction at TRISC3_bit;
// End LCD connections

sbit TestPin1 at RB0_bit;
sbit TestPin2 at RB1_bit;
sbit TestPin3 at RB2_bit;
sbit Detail at RB4_bit;
sbit SelectButton at RB5_bit;

// LCD Messages
char message1[] = "Diode Tester";
char message2[] = "BJT Tester";
char message3[] = "Result:";
char message4[] = "Short";
char message5[] = "Open ";
char message6[] = "Good ";
char message7[] = "BJT is";
char *type = "xxx";
char *BE_Info = "xxxxx";
char *BC_Info = "xxxxx";

//Global cariables definition
unsigned int select, test1, test2, update_select, detail_select;
unsigned int BE_Junc, BC_Junc, EB_Junc, CB_Junc;

void debounce_delay(void);

void main()
{
   PORTC = 0x00;
   PORTB = 0x00;
   TRISC = 0x00;                  // PORTC All Outputs
   TRISB = 0b00111000;            // PORTB All Outputs, Except RA3 (I/P only)
   Lcd_Init();                    // Initialize LCD
   Lcd_Cmd(_LCD_CLEAR);           // LCD CLEAR display
   Lcd_Cmd(_LCD_CURSOR_OFF);      // LCD Cursor off
   Lcd_Out(1,2,message1);         // Write message1 in 1st row

   select = 0;
   test1 = 0;
   test2 = 0;
   update_select = 1;
   detail_select = 0;
   while(1)
   {
      if(!SelectButton)
      {
         debounce_delay();
         update_select = 1;
         switch (select)
         {
            case 0 : select=1; break;
            case 1 : select=0; break;
         }                         //End case
      }                            //End if(!SelectButton)

      if(select == 0)              // Diode Tester
      {
         if(update_select)
         {
            Lcd_Cmd(_LCD_CLEAR);
            Lcd_Out(1,2,message1);
            Lcd_Out(2,2,message3);
            update_select=0;
         }
         TRISB = 0b00110100; // RA0 O/P, RA2 I/P
         TestPin1 = 1;
         test1 = TestPin3 ; // Read I/P at RA2
         TestPin1 = 0;
         TRISB = 0b00110001; // RA0 I/P, RA2 O/P
         TestPin3 = 1;
         test2 = TestPin1;
         TestPin3 = 0;

         if((test1==1) && (test2 ==1))
            Lcd_Out(2,10,message4);

         if((test1==1) && (test2 ==0))
            Lcd_Out(2,10,message6);

         if((test1==0) && (test2 ==1))
            Lcd_Out(2,10,message6);
         if((test1==0) && (test2 ==0))
            Lcd_Out(2,10,message5);
      }  // End if(select == 0)

      if(select && !detail_select)    // Transistor Tester
      {
         if(update_select)
         {
            Lcd_Cmd(_LCD_CLEAR);
            Lcd_Out(1,2,message2);
            update_select = 0;
         }
// Test for BE and BC Junctions of NPN
         TRISB = 0b00110101; // RA0, RA2 I/P, RA1 O/P
         TestPin2 = 1;
         BE_Junc = TestPin1 ; // Read I/P at RA0
         BC_Junc = TestPin3;   // Read I/P at RA2
         TestPin2 = 0;

// Test for EB and CB Junctions of PNP
         TRISB = 0b00110110; // RA0 O/P, RA1/RA2 I/P
         TestPin1 = 1;
         EB_Junc = TestPin2;
         TestPin1 = 0;
         TRISB = 0b00110011; // RA0 O/P, RA1/RA2 I/P
         TestPin3 = 1;
         CB_Junc = TestPin2;
         TestPin3 = 0;

         if(BE_Junc && BC_Junc && !EB_Junc && !CB_Junc)
         {
            Lcd_Out(2,2,message3);
            Lcd_Out(2,10,message6);
            type = "NPN";
            BE_info = "Good ";
            BC_info = "Good ";
         }
         else
         if(!BE_Junc && !BC_Junc && EB_Junc && CB_Junc)
         {
            Lcd_Out(2,2,message3);
            Lcd_Out(2,10,message6);
            type = "PNP";
            BE_info = "Good ";
            BC_info = "Good ";
         }
         else
         {
            Lcd_Out(2,2,message3);
            Lcd_Out(2,10,"Bad ");
            type = "Bad";
         }
      }
      if(select && !Detail)
      {
         debounce_delay();
         switch (detail_select)
         {
            case 0 : detail_select=1; break;
            case 1 : detail_select=0; break;
         } //case end
        
         update_select = 1;
      }

      if(detail_select && update_select)    // For Details of Transistor
      {
// Test for BE Junction open
         if(!BE_Junc && !EB_Junc)
            BE_info = "Open ";

// Test for BC Junction open
         if(!BC_Junc && !CB_Junc)
            BC_info = "Open ";

// Test for BE Junction short
         if(BE_Junc && EB_Junc)
            BE_info = "Short";

// Test for BC Junction short
         if(BC_Junc && CB_Junc)
            BC_info = "Short";
           
         Lcd_Cmd(_LCD_CLEAR);
         Lcd_Out(1,1,"Type:");
         Lcd_Out(1,7,type);
         Lcd_Out(2,1,"BE:");
         Lcd_Out(2,4,BE_info);
         Lcd_Out(2,9,"BC:");
         Lcd_Out(2,12,BC_info);
         update_select = 0;
      }                             // End if (detail_select)
   }                                // End while
}

void debounce_delay(void)
{
   Delay_ms(200);
}
Figure: Diode and Transistor Tester


Diode testing procedure:
Connect D1 and D2 to the I/O pins of microcontroller.
  • First defined D1 as output and D2 as input. Then set D1 High and read D2.
  • Next defined D2 as output and D1 as input. Then set D2 High and read D1.
If both the reading are high then the diode is short. If both the readings are Low then the diode is open. If any of read pins are low and the second is high then the diode is good.

Setup for Testing of Diodes
 

This concept can be easily extended to test a transistor by realizing that a transistor consists of two PN junctions: one between the base and the emitter (BE junction), and the another between the base and the collector (BC junction). If both the junctions conduct in only one direction, the transistor is normal, otherwise it is faulty. We can also identify the type (PNP or NPN) of the transistor by considering the direction of the current conduction. Three I/O pins of a microcontroller are required to implement the testing algorithm for a transistor.
Transistor testing procedure:

The test sequence for a transistor would be as follows:

1.    Set D2 High and read D1 and D3. If D1 is High, BE junction conducts, otherwise not. If D3 is High, BC junction conducts, otherwise not. 
2.    Set D1 High and read D2. If D2 is High, EB junction conducts, otherwise not. Set D3 High and read D2. If D2 is High, CB junction conducts, otherwise not.
Setup for Testing of Transistors

Now, if only the BE and BC junctions conduct, the transistor is of NPN type and is working fine. And, if only the EB and CB junctions conduct, the transistor is still normal but the transistor type is PNP. All other cases (like EB and BE both conduct, or BC and CB both not conducting, etc.) indicate the transistor is not good. 





Telephonic Keypad and 7 Segment Display Interfacing with PIC18F452

This project gives an idea that how we can interface the keypad and & Segment Display with PIC Microcontroller. When we press any digit from keypad, it will be displayed on the seven segment display. By pressing the # key, digit will increment and by pressing the * key, displayed digit will be decremented.

7 Segment Displays are of two types. Common Anode and Common Cathode. In Common Anode type display, Anode of each segment of display is common and we connect it to the Vcc or +5V. Whereas, cathode of each segment is available on the physical pins of 7 segment display as depicted in the following figure:


I have used the common cathode type display. Common pin is connected to the ground whereas pin a, b, c, ...g are connected to PD0, PD1, PD2, ... PD6 respectively. 

In a keypad there are physical switches for each number. Multiplexing technique is used to access the 12 keys with only 7 I/O pins. All the columns are pulled down through a resistor which means that a ground signal will always be on the pins connected to columns unless we apply a high through microcontroller. By the polling method, we keep sending high to the columns one by one and each time we send high to a column, we check all the four rows for a high signal. 

Lets say, if button 6 is presses. Microcontroller will send a high to Col0, no high signal will be received on Row 0 to Row 3. Then it will send high to Col1, again no high signal will be received on Row 0 to Row3. Now it will send high to Col2, then a high signal will be received on Row1 which means that the button 6 is pressed.

Keypad Schematic

Following cod is written and compiled using MikroC Pro:


/*
Project: 7 Segment & Keypad Interfacing
Author: Muhammad Muzammil
Target Device: PIC 18F452
Compiler: MikroC Pro
Crystal Freq: 12MHz
07th Nov, 2012
PhD Electronic Engineering (In-progress)
*/

unsigned char b[] = {0x3F,       // 0 = 0011 1111
                   0x06,        // 1 = 0000 0110
                   0x5B,        // 2 = 0101 1011
                   0x4F,        // 3 = 0100 1111
                   0x66,        // 4 = 0110 0110
                   0x6D,        // 5 = 0110 1101
                   0x7D,        // 6 = 0111 1101
                   0x07,        // 7 = 0000 0111
                   0x7F,        // 8 = 0111 1111
                   0x6F};       // 9 = 0110 1111
char x=0;

void main()
{
  TRISB.RB0=1;
  TRISB.RB1=1;
  TRISB.RB2=1;
  TRISB.RB3=1;
  TRISB.RB4=0;
  TRISB.RB5=0;
  TRISB.RB6=0;
  TRISD = 0x00;
  PORTD = 0x3F;

 
  while(1)
  {
    PORTB = 0x00;
    PORTB.RB4=1;
    if(PORTB.RB4)       //Put Column 0 high to check (1, 4, 7, *)
    {
      if (PORTB.RB0==1) {x=1; PORTD= b[x];}
      if (PORTB.RB1==1) {x=4; PORTD= b[x];}
      if (PORTB.RB2==1) {x=7; PORTD= b[x];}
      if (PORTB.RB3==1) {if(x>0) x--; PORTD= b[x]; delay_ms(500);}
      PORTB.RB4=0;
    }

    PORTB.RB5=1;
    if(PORTB.RB5)       //Column 1 is high
to check (2, 5, 8, 0)
    {
      if (PORTB.RB0==1) {x=2; PORTD=b[x];}
      if (PORTB.RB1==1) {x=5; PORTD=b[x];}
      if (PORTB.RB2==1) {x=8; PORTD=b[x];}
      if (PORTB.RB3==1) {x=0; PORTD=b[x];}
      PORTB.RB5=0;
    }
   
    PORTB.RB6=1;
    if(PORTB.RB6)       //Column 2 is high
to check (3, 6, 9, #)
    {
      if (PORTB.RB0==1) {x=3; PORTD=b[x];}
      if (PORTB.RB1==1) {x=6; PORTD=b[x];}
      if (PORTB.RB2==1) {x=9; PORTD=b[x];}
      if (PORTB.RB3==1) {if(x<9)x++; PORTD=b[x]; delay_ms(500);}
      PORTB.RB6=0;
    }
  }
}









 

7 comments:

  1. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Thanks Prakash. You can make some minor changes in the code and add a relay with driver, on one of the I/O pins to use the above circuit for charge controller. If you have further questions, feel free to contact

      Delete
  2. hi bro. nice post.
    can u send me ur email id, i want to discus for code.
    my email glorious_green@live.com

    ReplyDelete
  3. Hi,
    How did you calculate 0x2A4 for 3.3V. Well, that must sound silly to you, but I am new to embedded. What will be the hex for 12V ?

    ReplyDelete
  4. AsalaamOAliakum
    Nice project i want ur email id if u dont mind
    mine is yasiralikhi2@gmail.com Thnkyou

    ReplyDelete