Thursday, August 2, 2012

Time Switch_3: Designing a clock II.

In the previous entry I discussed about all the requirements that we have to meet and what are the options that are available for us to use in order to generate the clock. Now it's the time to actually code it in MicroC and see how it works. If you don't know how to write a program in MicroC first you will need to learn basics of C language and then to further understand the platform it's better to read the manual that comes with the software. You can easily download it from microelectronica website for free.

Here I will directly connect the LCD to the PIC and I will configure it, so that we can easily get a feedback on how our program is working through proteous simulations. Going through the LCD datasheet will give you an insight of how it is working.

First of all I drew the schematic diagram of the system in proteous. It should be mentioned that this is not the final system but just an arrangement with the LCD module.


Figure 1: Schematic diagram of the circuit.


Now we have the design, so let's start coding.

First step would be to create a project for our product in MicroC. Use the PIC16F628A as the micro-controller and use 20MHz as the clock frequency. Now we are set up to go.

This is the code that I implemented. Following the code would be a step by step description of the code. Here also I should state that this is just a demo code, and this can be and will be changed during the course of the product development.

void configure();

unsigned int timer_val = 0;
unsigned int timer_sec = 0;
char a[] = "0";
int a1 = 0;
//LCD configuration

sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB2_bit;
sbit LCD_D5 at RB3_bit;
sbit LCD_D6 at RB4_bit;
sbit LCD_D7 at RB5_bit;

sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB4_bit;
sbit LCD_D7_Direction at TRISB5_bit;

//Setting all the necessary configurations.
void configure(){
TRISA = 0b00000000; // port-A 0~7 output / no input
PORTA = 0x00; // port-A clear
CMCON = 0x07; // turn OFF comparators
VRCON = 0x00; // turn OFF voltage reference
TRISB = 0b00000000; // port-B 0~7 output / no input
Lcd_Init();
INTCON = 0xA0; // timer0 interrupt enable and flag cleared
OPTION_REG.PSA = 1; // clock prescalar for timer0 disabled
OPTION_REG.T0CS = 0; // timer0 connected to instruction cycle clock
}

void interrupt(){
INTCON.GIE = 0; // global interrupts disabled
if(INTCON.T0IF){ // handling the timer0 interrupt
timer_val++;
if(timer_val == 15000){ // 19531.25 overflows per second
timer_sec++;
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
a1 = a[0];
a1++;
a[0] = a1;
Lcd_Out(1,1,a);
timer_val = 0;
}
}

INTCON.T0IF = 0; // clearing the interrupt flag bit
INTCON.GIE = 1; // enabling global interrupts
}


void main() {
configure();
while(1);
}


Okay, to those who know C language the above code will be kinda familiar, but others should do their homework. ;)

Above code has two main parts,
  1. The configuration method.
  2. The interrupt method.

1. The configuration method.

This is the method I use to put all the configuration to the micro-controller. Most of the steps above are commented so that you can understand what is going on. That I believe is a very good practice for a programmer. Basically, the ports are configured as outputs(TRIS), comparators have been switched off so that all the ports can be be used for digital I/O, LCD configuration was done, timer0 interrupt has been enabled and the timer0 module parameters have been changed accordingly, referring the datasheet.

2. The interrupt method.

Within this method, I have counted the number of timer0 register overflows. Since it will overflow around 19600 times per second I have put another counter to count the number of seconds. I used the LCD to display something every second so that I can get a feedback of my program easily.

You might be wandering why I used 15000 instead of 19600. This is because, processor will spend some time to execute the instructions available inside the interrupt method. That time should be mitigated accordingly. The number will be changed later(after the practical implementation) to tune the device to measure time accurately.

Now we have a mechanism to count seconds. Let's move-on and design the alarm. :)