
Showing posts with label MikroC. Show all posts
Showing posts with label MikroC. Show all posts
Wednesday, March 11, 2009
Setting Internal Oscillator for PIC16F627A
I love to use PIC16F627A and PIC16F628 because they come with internal oscillators. That means I can make a project with lower component count (without 1 crystal and 2 load capacitors). The project setting of MikroC for using internal oscillator of the PIC16F627A shows below:

Tuesday, January 20, 2009
2-digit BCD to decimal conversion
Now, I'm working on the full feature clock using DS1307. In the clock, I use many BCD to decimal (bcd2dec) and decimal to BCD conversions for reading and setting time of the DS1307 RTC. MikroC provides buit-in functions for these conversions but the functions consume modest amount of MCU memory space. I have came up with simple functions that consume less memory for doing 2-digit BCD to decimal and the reverse conversions.
2-digit BCD to Decimal conversion function:
Example: myBcd2Dec(01000101) = 45
2-digit Decimal to BCD conversion function:
Example: myDec2Bcd(45) = 01000101
2-digit BCD to Decimal conversion function:
unsigned short myBcd2Dec(unsigned short bcd){
return ((bcd >> 4)*10+(bcd & 0x0F));
}
return ((bcd >> 4)*10+(bcd & 0x0F));
}
Example: myBcd2Dec(01000101) = 45
2-digit Decimal to BCD conversion function:
unsigned short myDec2Bcd(unsigned short dec){
return (((dec/10)<<4)(dec%10));
}
return (((dec/10)<<4)(dec%10));
}
Example: myDec2Bcd(45) = 01000101
Wednesday, December 31, 2008
6 Digits 7-Segment LED Multiplexing using a Shift Register
Multiplexing technique can reduce number of needed I/O pins of the MCU as I have explained in 'LED 7-Segment Multiplexing' and '6 Digits LED 7-Segment Multiplexing'. In those posts, I used 13 I/O pins for driving 6 digits LED 7-Segment. However, the PIC16F627A and PIC16F628 have only 15 usable I/O pins that include 2 pins for external 32.768KHz oscillator. So, there is no pin left for time setting buttons. I can change to the PIC that has more I/O pins, but I don't think it's a good solution. From my searches, I can overcome this I/O pins shortage problem by using shift register to expand the MCU I/O pins.
The concept is very similar to led dot matrix driving technique. Each digit is multiplexed via a shift register 74HC595 which is required 3 pins of the MCU. Each segment of the 7-segment display is driven by PORTA of the PIC16F628. As a result, the required pins for driving 6-Digit 7-Segment display are just 3+7 = 10 pins!. With this configuration, there are 3 I/O pins that are free for time setting buttons and driving blinking second LEDs.
I use TMR2 module for scanning digits. TMR2 is an 8-bit timer which overflows every 256 (0xFF) counts. It's known that the refresh rate above 50Hz would be enough for human's eyes to see the display without recognizing the flickering. If I set TMR2 with 1:8 Prescaler (T2CON = 0x3C), the multiplexing frequency will be 81.3Hz (4MHz/4/256/8/6 = 81.3Hz) which is enough for flicker free display.
PORTA is used to drive each segment of the 7-segment displays. However, I have to skip the RA5 as it's a MCLR pin and it can be only input pin. So, my 7-segment digit mask is different then the normal 7-segment digit mask.
Below is the example schematic of 999999-second counter using the PIC16F627A or PIC16F628 and a shift register. I will not implement a clock with this configuration as I need more free MCU pins for driving Alarm buzzer and other things.

The source code for 999999-second counter in MikroC is listed below
The concept is very similar to led dot matrix driving technique. Each digit is multiplexed via a shift register 74HC595 which is required 3 pins of the MCU. Each segment of the 7-segment display is driven by PORTA of the PIC16F628. As a result, the required pins for driving 6-Digit 7-Segment display are just 3+7 = 10 pins!. With this configuration, there are 3 I/O pins that are free for time setting buttons and driving blinking second LEDs.
I use TMR2 module for scanning digits. TMR2 is an 8-bit timer which overflows every 256 (0xFF) counts. It's known that the refresh rate above 50Hz would be enough for human's eyes to see the display without recognizing the flickering. If I set TMR2 with 1:8 Prescaler (T2CON = 0x3C), the multiplexing frequency will be 81.3Hz (4MHz/4/256/8/6 = 81.3Hz) which is enough for flicker free display.
PORTA is used to drive each segment of the 7-segment displays. However, I have to skip the RA5 as it's a MCLR pin and it can be only input pin. So, my 7-segment digit mask is different then the normal 7-segment digit mask.
my PORTA 7-segment digit mask : {0x5F, 0x06, 0x9b, 0x8f, 0xC6, 0xCd,0xDD, 0x07,
0xDf, 0xCf}
Normal 7-segment digit mask : {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f} for number 0-9 respectively.
0xDf, 0xCf}
Normal 7-segment digit mask : {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f} for number 0-9 respectively.
Below is the example schematic of 999999-second counter using the PIC16F627A or PIC16F628 and a shift register. I will not implement a clock with this configuration as I need more free MCU pins for driving Alarm buzzer and other things.

The source code for 999999-second counter in MikroC is listed below
//PIC16F627A or PIC16F628
//4MHz Internal OSC
//MUX by using Shift Register 595
// Critical parameters:
// Delay, Postscaler, Prescaler
// Low delay + High Prescaler
// 03/11/2008
// punkky@gmail.com
#define SH_CP PORTB.F0
#define DS PORTB.F1
#define ST_CP PORTB.F2
// 7-Segment code is skipping RA5, so the code is not as normal 7-segment coding
unsigned short number [10] = {
0x5F, 0x06, 0x9b, 0x8f, 0xC6, 0xCd, 0xDD, 0x07,
0xDf, 0xCf
};
unsigned short digit [6] = {
0, 0, 0, 0, 0, 0
};
unsigned short i;
unsigned short n;
unsigned short counter;
unsigned short tick;
unsigned short shift_register;
unsigned short x1;
unsigned short x2;
unsigned short x3;
unsigned short x4;
unsigned short x5;
unsigned short x6;
void interrupt ()
{
if (PIR1.TMR2IF)
{
PIR1.TMR2IF = 0;
if (counter == 5)
{
//Shift data
DS = 0;
//Store data
SH_CP = 1;
SH_CP = 0;
Delay_us (250);
counter = 0;
}else
{
//Shift data
DS = 1;
//Store
SH_CP = 1;
SH_CP = 0;
Delay_us (250);
counter ++;
}
ST_CP = 1;
ST_CP = 0;
PORTA = 0x00;
PORTA = number [digit [counter]];
}
if (PIR1.TMR1IF)
{
TMR1H = 0x80;
PIR1.TMR1IF = 0;
tick = 1;
x6 ++;
if (x6 > 9)
{
x6 = 0;
x5 ++;
if (x5 > 9)
{
x5 = 0;
x4 ++;
if (x4 > 9)
{
x4 = 0;
x3 ++;
if (x3 > 9)
{
x3 = 0;
x2 ++;
if (x2 > 9)
{
x2 = 0;
x1 ++;
if (x1 > 9)
{
x1 = 0;
}
}
}
}
}
}
}
}
void main ()
{
//Digital I/O for PORTA
CMCON = 0x07;
TRISA = 0x00;
PORTA = 0x00;
TRISB = 0x00;
PORTB = 0x00;
//Internal Clock 4MHz
PCON.OSCF = 1;
counter = 0;
// Set GIE, PEIE
INTCON = 0xC0;
//1:8 post scaler
T2CON = 0x3C;
// enable interupt
PIE1.TMR2IE = 1;
T1CON = 0x0F;
//Initial value TMR1: 0x8000
TMR1H = 0x80;
TMR1L = 0x00;
// enable interupt
PIE1.TMR1IE = 1;
//Data
DS = 0;
//Store
SH_CP = 0;
ST_CP = 0;
x1 = 0;
x2 = 0;
x3 = 0 ;
x4 = 0;
x5 = 0;
x6 = 0;
while (1)
{
if (tick)
{
tick = 0;
digit [0] = x1;
digit [1] = x2;
digit [2] = x3;
digit [3] = x4;
digit [4] = x5;
digit [5] = x6;
}
}
}
//4MHz Internal OSC
//MUX by using Shift Register 595
// Critical parameters:
// Delay, Postscaler, Prescaler
// Low delay + High Prescaler
// 03/11/2008
// punkky@gmail.com
#define SH_CP PORTB.F0
#define DS PORTB.F1
#define ST_CP PORTB.F2
// 7-Segment code is skipping RA5, so the code is not as normal 7-segment coding
unsigned short number [10] = {
0x5F, 0x06, 0x9b, 0x8f, 0xC6, 0xCd, 0xDD, 0x07,
0xDf, 0xCf
};
unsigned short digit [6] = {
0, 0, 0, 0, 0, 0
};
unsigned short i;
unsigned short n;
unsigned short counter;
unsigned short tick;
unsigned short shift_register;
unsigned short x1;
unsigned short x2;
unsigned short x3;
unsigned short x4;
unsigned short x5;
unsigned short x6;
void interrupt ()
{
if (PIR1.TMR2IF)
{
PIR1.TMR2IF = 0;
if (counter == 5)
{
//Shift data
DS = 0;
//Store data
SH_CP = 1;
SH_CP = 0;
Delay_us (250);
counter = 0;
}else
{
//Shift data
DS = 1;
//Store
SH_CP = 1;
SH_CP = 0;
Delay_us (250);
counter ++;
}
ST_CP = 1;
ST_CP = 0;
PORTA = 0x00;
PORTA = number [digit [counter]];
}
if (PIR1.TMR1IF)
{
TMR1H = 0x80;
PIR1.TMR1IF = 0;
tick = 1;
x6 ++;
if (x6 > 9)
{
x6 = 0;
x5 ++;
if (x5 > 9)
{
x5 = 0;
x4 ++;
if (x4 > 9)
{
x4 = 0;
x3 ++;
if (x3 > 9)
{
x3 = 0;
x2 ++;
if (x2 > 9)
{
x2 = 0;
x1 ++;
if (x1 > 9)
{
x1 = 0;
}
}
}
}
}
}
}
}
void main ()
{
//Digital I/O for PORTA
CMCON = 0x07;
TRISA = 0x00;
PORTA = 0x00;
TRISB = 0x00;
PORTB = 0x00;
//Internal Clock 4MHz
PCON.OSCF = 1;
counter = 0;
// Set GIE, PEIE
INTCON = 0xC0;
//1:8 post scaler
T2CON = 0x3C;
// enable interupt
PIE1.TMR2IE = 1;
T1CON = 0x0F;
//Initial value TMR1: 0x8000
TMR1H = 0x80;
TMR1L = 0x00;
// enable interupt
PIE1.TMR1IE = 1;
//Data
DS = 0;
//Store
SH_CP = 0;
ST_CP = 0;
x1 = 0;
x2 = 0;
x3 = 0 ;
x4 = 0;
x5 = 0;
x6 = 0;
while (1)
{
if (tick)
{
tick = 0;
digit [0] = x1;
digit [1] = x2;
digit [2] = x3;
digit [3] = x4;
digit [4] = x5;
digit [5] = x6;
}
}
}
Wednesday, November 12, 2008
Making a Digital Clock (Updated)
My fist Microcontroller project, PIC Digital Clock, is shown below.
I have added time setting feature to make it to be a usable clock. The updated version is shown below:

More features will be added in the future.
There is no fast or slow time setting as in normal/simple digital clocks. In this clock, each digit of the clock display can be set one by one via 2 setting buttons.
Features
1. Bright Led 7-Segment display without Multiplexing
2. Display: Hour, Minute, Second
3. Set time via 2 buttons
4. Set time Digit by Digit
5. Use internal oscillator of PIC16F627a or PIC16F628
6. Use 32.768KHz crystal for better clock accuracy
Setting Time:
1. The clock shows 12:34:56 when power the clock on. The first digit of hour (it's number 1 in this case) will be blinking to notify that the time is not correct and need to be set.
2. Press SET button to count up the digit.
3. Press MODE button when the digit is the correct time. The next digit will be blinking.
4. Repeat step 2 and 3 for setting minute and second.
5. Make sure that pressing MODE button for setting the second digit of second at the correct time.
Shecmatic of the Digital Clock

Example of a PCB design of the Digital Clock

The firmware ( source code in C ) written in MikroC
I don't have the picture of the prototype as I haven't made it yet. But I have tested the circuit and firmware with proteus already.
--- Update ---
- The prototype of this updated version is done. Please see its photographs at 7-Segment PIC Digital Clock : The photographs
- The PCB is ready: please check out PCB for PIC Digital Clock

I have added time setting feature to make it to be a usable clock. The updated version is shown below:

More features will be added in the future.
There is no fast or slow time setting as in normal/simple digital clocks. In this clock, each digit of the clock display can be set one by one via 2 setting buttons.
Features
1. Bright Led 7-Segment display without Multiplexing
2. Display: Hour, Minute, Second
3. Set time via 2 buttons
4. Set time Digit by Digit
5. Use internal oscillator of PIC16F627a or PIC16F628
6. Use 32.768KHz crystal for better clock accuracy
Setting Time:
1. The clock shows 12:34:56 when power the clock on. The first digit of hour (it's number 1 in this case) will be blinking to notify that the time is not correct and need to be set.
2. Press SET button to count up the digit.
3. Press MODE button when the digit is the correct time. The next digit will be blinking.
4. Repeat step 2 and 3 for setting minute and second.
5. Make sure that pressing MODE button for setting the second digit of second at the correct time.
Shecmatic of the Digital Clock

Example of a PCB design of the Digital Clock

The firmware ( source code in C ) written in MikroC
//6 digit clock
//Using timer1 16bit counter interrupt
// PIC16F627A or PIC16F628
// Internal Clock 4MHz
// PUNKKY@gmail.com
#define MODE PORTB.F4
#define SET PORTB.F5
#define Sec_port_l PORTA.F6
#define Sec_port_h PORTA.F4
#define Min_port_l PORTA.F3
#define Min_port_h PORTA.F2
#define Hr_port_l PORTA.F1
#define Hr_port_h PORTA.F0
#define Blink PORTA.F7
#define HTMR1 0x80
#define LTMR1 0x00
typedef unsigned short uns8;
uns8 i;
uns8 hr_h;
uns8 hr_l;
uns8 min_h;
uns8 min_l;
uns8 sec_h;
uns8 sec_l;
uns8 tick;
uns8 myTimer;
uns8 setting_time;
void setup ();
void set_time ();
void show_time ();
void display (uns8 digit);
void blink_digit (uns8 digit);
void check_bt ();
//void check_bt(); //chech button
void interrupt ()
{
PIR1.TMR1IF = 0;
// clears TMR1IF
TMR1H = HTMR1;
tick = 1;
Blink = 1;
sec_l ++;
if(sec_l>9){
sec_l = 0;
sec_h++;
}
if(sec_h>5){
sec_h=0;
min_l++;
}
if(min_l>9){
min_l = 0;
min_h++;
}
if(min_h>5){
min_h = 0;
hr_l++;
}
if(hr_l>9){
hr_l = 0;
hr_h++;
}
if(hr_h >2){
hr_h = 0;
}
if(hr_h >=2 && hr_l>3){
hr_h = 0;
hr_l = 0;
}
}
void main ()
{
setup ();
//Set time
hr_h = 1;
hr_l = 2;
min_h = 3;
min_l = 4;
sec_h = 5;
sec_l = 6;
show_time ();
setting_time = 1;
set_time();
while (1)
{
//blink_digit();
if (tick)
{
tick = 0;
show_time ();
Delay_ms (300);
Blink = 0;
}
check_bt ();
}
}
void setup ()
{
tick = 0;
//Digital output on PORTA
CMCON = 0x07;
//Input buttons + external clock
TRISB = 0xB0;
PORTB = 0x00;
TRISA = 0x00;
PORTA = 0x00;
//Internal Clock 4MHz
PCON.OSCF = 1;
// Prescaler 1:1 external clock
T1CON = 0x0F;
PIE1.TMR1IE = 0; // disable interupt to stop the clock
INTCON = 0xC0;
// Set GIE, PEIE
TMR1L = LTMR1;
TMR1H = HTMR1;
// TMR1 starts at 0x0BDC = 3036 to make TMR1 counts to 62500 and
// overclows in every 0.1 sec
// Math: 1/500000*8*62500 = 0.1
// 1/5000000 : time for 20MHz crystal (internal clock will be 20/4 = 5MHz)
// 8: prescaler
// 62500: TMR1 counts to 62500
// Counting number of overflows to 10 will get 1 sec.
}
void show_time ()
{
display (1);
display (2);
display (3);
display (4);
display (5);
display (6);
}
void display (uns8 digit)
{
switch (digit)
{
case 1 :
PORTB = hr_h;
Hr_port_h = 1;
Hr_port_h = 0;
break;
case 2 :
PORTB = hr_l;
Hr_port_l = 1;
Hr_port_l = 0;
break;
case 3 :
PORTB = min_h;
Min_port_h = 1;
Min_port_h = 0;
break;
case 4 :
PORTB = min_l;
Min_port_l = 1;
Min_port_l = 0;
break;
case 5 :
PORTB = sec_h;
Sec_port_h = 1;
Sec_port_h = 0;
break;
case 6 :
PORTB = sec_l;
Sec_port_l = 1;
Sec_port_l = 0;
break;
}
}
void blink_digit (uns8 digit)
{
switch (digit)
{
case 1 :
PORTB = 0xFF;
Hr_port_h = 1;
Hr_port_h = 0;
Delay_ms (100);
display (1);
Delay_ms (100);
break;
case 2 :
PORTB = 0xFF;
Hr_port_l = 1;
Hr_port_l = 0;
Delay_ms (100);
display (2);
Delay_ms (100);
break;
case 3 :
PORTB = 0xFF;
Min_port_h = 1;
Min_port_h = 0;
Delay_ms (100);
display (3);
Delay_ms (100);
break;
case 4 :
PORTB = 0xFF;
Min_port_l = 1;
Min_port_l = 0;
Delay_ms (100);
display (4);
Delay_ms (100);
break;
case 5 :
PORTB = 0xFF;
Sec_port_h = 1;
Sec_port_h = 0;
Delay_ms (100);
display (5);
Delay_ms (100);
break;
case 6 :
PORTB = 0xFF;
Sec_port_l = 1;
Sec_port_l = 0;
Delay_ms (100);
display (6);
Delay_ms (100);
break;
}
}
void set_time ()
{
i = 1;
while (setting_time)
{
blink_digit (i);
while (SET == 0)
{
Delay_ms (5);
switch (i)
{
case 1 :
hr_h ++;
if (hr_h > 2)
{
hr_h = 0;
}
break;
case 2 :
hr_l ++;
if (hr_l > 9)
{
hr_l = 0;
}
if (hr_h >= 2 && hr_l > 3)
{
hr_l = 0;
}
break;
case 3 :
min_h ++;
if (min_h > 5)
{
min_h = 0;
}
break;
case 4 :
min_l ++;
if (min_l > 9)
{
min_l = 0;
}
break;
case 5 :
sec_h ++;
if (sec_h > 5)
{
sec_h = 0;
}
break;
case 6 :
sec_l ++;
if (sec_l > 9)
{
sec_l = 0;
}
break;
}
while (SET == 0)
{
Delay_ms (5);
}
}
while (MODE == 0)
{
Delay_ms (5);
i ++;
if (i > 6)
{
sec_l--;
TMR1H = 0x80;
TMR1L = 0x00;
PIE1.TMR1IE = 1;
setting_time = 0;
break;
}
while (MODE == 0)
{
Delay_ms (5);
}
}
}
}
void check_bt ()
{
myTimer = 0;
if (setting_time == 0)
{
while (MODE == 0)
{
Delay_ms (5);
myTimer ++;
if (myTimer > 200)
{
setting_time = 1;
myTimer = 0;
break;
}
}
}
while (MODE == 0)
{
PIE1.TMR1IE = 0;
//Stop clock
Delay_ms (5);
blink_digit (1);
}
set_time ();
}
//Using timer1 16bit counter interrupt
// PIC16F627A or PIC16F628
// Internal Clock 4MHz
// PUNKKY@gmail.com
#define MODE PORTB.F4
#define SET PORTB.F5
#define Sec_port_l PORTA.F6
#define Sec_port_h PORTA.F4
#define Min_port_l PORTA.F3
#define Min_port_h PORTA.F2
#define Hr_port_l PORTA.F1
#define Hr_port_h PORTA.F0
#define Blink PORTA.F7
#define HTMR1 0x80
#define LTMR1 0x00
typedef unsigned short uns8;
uns8 i;
uns8 hr_h;
uns8 hr_l;
uns8 min_h;
uns8 min_l;
uns8 sec_h;
uns8 sec_l;
uns8 tick;
uns8 myTimer;
uns8 setting_time;
void setup ();
void set_time ();
void show_time ();
void display (uns8 digit);
void blink_digit (uns8 digit);
void check_bt ();
//void check_bt(); //chech button
void interrupt ()
{
PIR1.TMR1IF = 0;
// clears TMR1IF
TMR1H = HTMR1;
tick = 1;
Blink = 1;
sec_l ++;
if(sec_l>9){
sec_l = 0;
sec_h++;
}
if(sec_h>5){
sec_h=0;
min_l++;
}
if(min_l>9){
min_l = 0;
min_h++;
}
if(min_h>5){
min_h = 0;
hr_l++;
}
if(hr_l>9){
hr_l = 0;
hr_h++;
}
if(hr_h >2){
hr_h = 0;
}
if(hr_h >=2 && hr_l>3){
hr_h = 0;
hr_l = 0;
}
}
void main ()
{
setup ();
//Set time
hr_h = 1;
hr_l = 2;
min_h = 3;
min_l = 4;
sec_h = 5;
sec_l = 6;
show_time ();
setting_time = 1;
set_time();
while (1)
{
//blink_digit();
if (tick)
{
tick = 0;
show_time ();
Delay_ms (300);
Blink = 0;
}
check_bt ();
}
}
void setup ()
{
tick = 0;
//Digital output on PORTA
CMCON = 0x07;
//Input buttons + external clock
TRISB = 0xB0;
PORTB = 0x00;
TRISA = 0x00;
PORTA = 0x00;
//Internal Clock 4MHz
PCON.OSCF = 1;
// Prescaler 1:1 external clock
T1CON = 0x0F;
PIE1.TMR1IE = 0; // disable interupt to stop the clock
INTCON = 0xC0;
// Set GIE, PEIE
TMR1L = LTMR1;
TMR1H = HTMR1;
// TMR1 starts at 0x0BDC = 3036 to make TMR1 counts to 62500 and
// overclows in every 0.1 sec
// Math: 1/500000*8*62500 = 0.1
// 1/5000000 : time for 20MHz crystal (internal clock will be 20/4 = 5MHz)
// 8: prescaler
// 62500: TMR1 counts to 62500
// Counting number of overflows to 10 will get 1 sec.
}
void show_time ()
{
display (1);
display (2);
display (3);
display (4);
display (5);
display (6);
}
void display (uns8 digit)
{
switch (digit)
{
case 1 :
PORTB = hr_h;
Hr_port_h = 1;
Hr_port_h = 0;
break;
case 2 :
PORTB = hr_l;
Hr_port_l = 1;
Hr_port_l = 0;
break;
case 3 :
PORTB = min_h;
Min_port_h = 1;
Min_port_h = 0;
break;
case 4 :
PORTB = min_l;
Min_port_l = 1;
Min_port_l = 0;
break;
case 5 :
PORTB = sec_h;
Sec_port_h = 1;
Sec_port_h = 0;
break;
case 6 :
PORTB = sec_l;
Sec_port_l = 1;
Sec_port_l = 0;
break;
}
}
void blink_digit (uns8 digit)
{
switch (digit)
{
case 1 :
PORTB = 0xFF;
Hr_port_h = 1;
Hr_port_h = 0;
Delay_ms (100);
display (1);
Delay_ms (100);
break;
case 2 :
PORTB = 0xFF;
Hr_port_l = 1;
Hr_port_l = 0;
Delay_ms (100);
display (2);
Delay_ms (100);
break;
case 3 :
PORTB = 0xFF;
Min_port_h = 1;
Min_port_h = 0;
Delay_ms (100);
display (3);
Delay_ms (100);
break;
case 4 :
PORTB = 0xFF;
Min_port_l = 1;
Min_port_l = 0;
Delay_ms (100);
display (4);
Delay_ms (100);
break;
case 5 :
PORTB = 0xFF;
Sec_port_h = 1;
Sec_port_h = 0;
Delay_ms (100);
display (5);
Delay_ms (100);
break;
case 6 :
PORTB = 0xFF;
Sec_port_l = 1;
Sec_port_l = 0;
Delay_ms (100);
display (6);
Delay_ms (100);
break;
}
}
void set_time ()
{
i = 1;
while (setting_time)
{
blink_digit (i);
while (SET == 0)
{
Delay_ms (5);
switch (i)
{
case 1 :
hr_h ++;
if (hr_h > 2)
{
hr_h = 0;
}
break;
case 2 :
hr_l ++;
if (hr_l > 9)
{
hr_l = 0;
}
if (hr_h >= 2 && hr_l > 3)
{
hr_l = 0;
}
break;
case 3 :
min_h ++;
if (min_h > 5)
{
min_h = 0;
}
break;
case 4 :
min_l ++;
if (min_l > 9)
{
min_l = 0;
}
break;
case 5 :
sec_h ++;
if (sec_h > 5)
{
sec_h = 0;
}
break;
case 6 :
sec_l ++;
if (sec_l > 9)
{
sec_l = 0;
}
break;
}
while (SET == 0)
{
Delay_ms (5);
}
}
while (MODE == 0)
{
Delay_ms (5);
i ++;
if (i > 6)
{
sec_l--;
TMR1H = 0x80;
TMR1L = 0x00;
PIE1.TMR1IE = 1;
setting_time = 0;
break;
}
while (MODE == 0)
{
Delay_ms (5);
}
}
}
}
void check_bt ()
{
myTimer = 0;
if (setting_time == 0)
{
while (MODE == 0)
{
Delay_ms (5);
myTimer ++;
if (myTimer > 200)
{
setting_time = 1;
myTimer = 0;
break;
}
}
}
while (MODE == 0)
{
PIE1.TMR1IE = 0;
//Stop clock
Delay_ms (5);
blink_digit (1);
}
set_time ();
}
I don't have the picture of the prototype as I haven't made it yet. But I have tested the circuit and firmware with proteus already.
--- Update ---
- The prototype of this updated version is done. Please see its photographs at 7-Segment PIC Digital Clock : The photographs
- The PCB is ready: please check out PCB for PIC Digital Clock
Thursday, November 6, 2008
10-Second Counter
I have made a 10-Second Counter by using a PIC16F627a and a CD4543 BCD to 7-Segment decoder. This circuit and source code are just a demonstration of using MCU to drive an LED 7-Segment Display via CD4543. The 7-Segment displays from 0 to 9 and the number will roll over to 0 again. The interval between change is 1 second. So, this circuit counts 10 seconds between the roll over. I use TIMER1 module and 32.768KHz crystal to make 1 second timebase (see Clock with 32.768KHz Crystal for more info ).
The schematic of the 10-Second counter

Project setting of MikroC for using internal oscillator of the PIC16f627a.

The firmware is written in MikroC and you can find it below.
//PIC16F627A
//4MHz Internal OSC
// One Digit Counter
// 06/11/2008
//Punkky
unsigned short counter;
unsigned short tick;
void interrupt ()
{
PIR1.TMR1IF = 0; // clears TMR1IF
TMR1H = 0x80;
tick = 1;
}
void main(){
CMCON = 0x07; //Digital I/O for PORTA
TRISA = 0x00;
PORTA = 0x00;
TRISB = 0x00;
PORTB = 0x00;
T1CON = 0x0F;
// Prescaler 1:1 external clock
PIE1.TMR1IE = 1; // enable interupt to start the clock
INTCON = 0xC0; // Set GIE, PEIE
TMR1L = 0x00;
TMR1H = 0x80;
PCON.OSCF = 1; //Internal Clock 4MHz
//PCON.OSCF = 0; //Internal Clock 48KHz doesn't work well
counter = 0;
tick = 0;
PORTA.F0 = 1; // Enable 4345 BCD to 7-Segment
while(1){
if(tick){
tick = 0;
counter++;
PORTB = counter;
if(counter>9){
counter = 0;
}
}
}
}
The schematic of the 10-Second counter

Project setting of MikroC for using internal oscillator of the PIC16f627a.

The firmware is written in MikroC and you can find it below.
//PIC16F627A
//4MHz Internal OSC
// One Digit Counter
// 06/11/2008
//Punkky
unsigned short counter;
unsigned short tick;
void interrupt ()
{
PIR1.TMR1IF = 0; // clears TMR1IF
TMR1H = 0x80;
tick = 1;
}
void main(){
CMCON = 0x07; //Digital I/O for PORTA
TRISA = 0x00;
PORTA = 0x00;
TRISB = 0x00;
PORTB = 0x00;
T1CON = 0x0F;
// Prescaler 1:1 external clock
PIE1.TMR1IE = 1; // enable interupt to start the clock
INTCON = 0xC0; // Set GIE, PEIE
TMR1L = 0x00;
TMR1H = 0x80;
PCON.OSCF = 1; //Internal Clock 4MHz
//PCON.OSCF = 0; //Internal Clock 48KHz doesn't work well
counter = 0;
tick = 0;
PORTA.F0 = 1; // Enable 4345 BCD to 7-Segment
while(1){
if(tick){
tick = 0;
counter++;
PORTB = counter;
if(counter>9){
counter = 0;
}
}
}
}
Wednesday, October 22, 2008
MikroC "Hello World!" LCD example

Just an example of using MikroC to make a simple "Hello World!" PIC Microcontroller LCD project. The MCU is PIC16F877A (of course, it can be PIC16F887). The LCD display word "Hellow World!" on the first line and counting number on the second line. The image above is a screen capture of a simulation. I use the Proteus 7 VSM simulator to simulate my programs.
The source code in MikroC
//Test LCD
char *text = "Hello World!";
char mytext[3];
int i;
void main() {
// pic16f887
// ANSEL = 0x00; //Digital I/O for PORTA
// ANSELH = 0x00; //Digital Input for PORTB
// pic16f877A
CMCON = 0x07; //Set PORTA to Digital input
TRISB = 0; // PORTB is output
TRISA = 0x07; //PORTA as the input/output 0000 0111
i=0;
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, text); // Print text to LCD, 2nd row
while(1){
while(i<200){
IntToStr(i,mytext);
Lcd_Out(2,1,mytext);
Delay_ms(500);
i++;
}
i=0;
}
}
char *text = "Hello World!";
char mytext[3];
int i;
void main() {
// pic16f887
// ANSEL = 0x00; //Digital I/O for PORTA
// ANSELH = 0x00; //Digital Input for PORTB
// pic16f877A
CMCON = 0x07; //Set PORTA to Digital input
TRISB = 0; // PORTB is output
TRISA = 0x07; //PORTA as the input/output 0000 0111
i=0;
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, text); // Print text to LCD, 2nd row
while(1){
while(i<200){
IntToStr(i,mytext);
Lcd_Out(2,1,mytext);
Delay_ms(500);
i++;
}
i=0;
}
}
Tuesday, October 21, 2008
MikroC for PIC Microcontroller Programming

As a beginner in PIC Microcontroller, MikroC is my favorite compiler for my Microcontroller projects. I know 'C' already so it's very easy to use MikroC no complex settings involved. MikroC provides a lot of useful and handy libraries for example, LCD interface , UART, I2C, SD card access and many more. Good new, there is a free lite version that can compile code upto 2Kbyte which is enough for beginner projects. The commercial version is also affordable. Of course, I am not selling MikroC :) I just want to share information. Please visit their site for more info: http://www.mikroe.com/
MikroC sample for sending "Hello World!" to LCD
Lcd_Init(&PORTB); // Initialize LCD connected to PORTB
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, "Hello World!");
Lcd_Cmd(Lcd_CLEAR); // Clear display
Lcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor off
Lcd_Out(1, 1, "Hello World!");
Friday, September 26, 2008
Source Code for one chip 5x7 led dot matrix clock
As promised, listed below is the source code in MikroC for the 5x7 Led Dot Matrix Clock. The free demo version of MikroC can compile this code without any problem. Of course, the code is just for educational purpose only and use it with your own risk. The explanation about the source code will come later.
Setting time
- Press and hold MODE button until the digits blink
- The blinking digits are the hour is being set
- Press SET button to count up the hour
- When get the right hour, press MODE button to confirm hour setting
- Now the minute digits are blinking and ready to be set
- Press SET button to count up the minute
- When get the right minute, press MODE button to confirm minute setting and the second will be set to 0 automatically
- Now, the clock is set and the clock is running
Have fun!!!
Next improvements:
1. Using DS1307 as the time base will improve the clock accuracy and backup battery is also a nice feature of the DS1307
2. Dot matrix will be scanned and updated via interrupt routine to give the PIC more free time for doing something else
== Updated on 29 Nov 2009 ===
This firmware is written for The 5x7 Dot matrix Cathode Row. If you use Anode Row you have to make change to make_dotmatrix() by inverting the output PORTB and PORTD
===========================
Setting time
- Press and hold MODE button until the digits blink
- The blinking digits are the hour is being set
- Press SET button to count up the hour
- When get the right hour, press MODE button to confirm hour setting
- Now the minute digits are blinking and ready to be set
- Press SET button to count up the minute
- When get the right minute, press MODE button to confirm minute setting and the second will be set to 0 automatically
- Now, the clock is set and the clock is running
Have fun!!!
Next improvements:
1. Using DS1307 as the time base will improve the clock accuracy and backup battery is also a nice feature of the DS1307
2. Dot matrix will be scanned and updated via interrupt routine to give the PIC more free time for doing something else
== Updated on 29 Nov 2009 ===
This firmware is written for The 5x7 Dot matrix Cathode Row. If you use Anode Row you have to make change to make_dotmatrix() by inverting the output PORTB and PORTD
===========================
//One 5x7 Led Dot Matrix Clock
// PIC16F887
// I will use DS1307 as the RTC for the next improvement
// punkky@gmail.com
// 26 Sep 2008
#define MYMODE PORTA.F0
#define SET PORTA.F1
//External OSC 32.768KHz
#define HTMR1 0x80
#define LTMR1 0x00
//Constants for 4MHz Internal Clock
#define PAUSE_TIME 40
#define SCROLL_TIME_DELAY 60
#define HM_PAUSE_TIME 8
#define DTime 200
//Cursor Positions
#define HR_H_POS 0
#define HR_L_POS 0
#define DOT_1_POS 32
#define MIN_H_POS 12
#define MIN_L_POS 12
#define DOT_2_POS 56
#define SEC_H_POS 64
#define SEC_L_POS 72
//5x7 font
//Vertical scan , Little endian order
const unsigned char char2[][4]={
{0x1F,0x11,0x1F,0x00}, //0
{0x09,0x1F,0x01,0x00},
{0x17,0x15,0x1D,0x00},
{0x11,0x15,0x1F,0x00},
{0x1C,0x04,0x1F,0x00},
{0x1D,0x15,0x17,0x00},
{0x1F,0x15,0x17,0x00},
{0x10,0x10,0x1F,0x00},
{0x1F,0x15,0x1F,0x00},
{0x1D,0x15,0x1F,0x00}, //9
{0x0E,0x0E,0x0E,0x00}, //Comma1
{0x04,0x0E,0x04,0x00} //Comma2
};
unsigned char output[8];
unsigned char data[40];
unsigned char ptr;
unsigned char base_ptr;
unsigned char result_ptr;
unsigned char pp;
unsigned char pause_cnt;
unsigned char hr_pause_cnt;
unsigned char min_pause_cnt;
unsigned short counter;
unsigned short sec_h;
unsigned short sec_l;
unsigned short min_h;
unsigned short min_l;
unsigned short hr_h;
unsigned short hr_l;
unsigned short tick;
unsigned short num;
unsigned short i;
unsigned short j;
unsigned short time[8];
unsigned short setting_time;
unsigned short change_MYMODE;
void check_bt();
void button_fn(unsigned short param1, unsigned short pos1, unsigned short pos2);
void make_dotmatrix();
void interrupt() { //Internal clock
PIR1.TMR1IF = 0; // clears TMR1IF
TMR1H = HTMR1; //Set only high byte
tick = 1; // increment counter
}
void update_time();
void make_time();
void fill_data();
void show_digit(unsigned short pos);
void scroll();
void pause_digit(unsigned short position,unsigned short pause_delay);
unsigned short shift_register;
void main(){
setting_time = 0;
change_MYMODE = 0;
ANSEL = 0x00; //Digital I/O for PORTA
TRISA = 0x03;
PORTA = 0x03;
TRISB = 0x00;
PORTB = 0xFF;
TRISC = 0x0E;
TRISD = 0x00;
PORTD = 0x00;
ANSELH = 0x00; //Digital Input for PORTB
OSCCON = 0x65 ; //pic16f887 : 0110 0101, Internal Osc at 4MHz for lowest power consumption
counter = 0;
shift_register = 0x01;
hr_h = 1;
hr_l = 2;
min_h = 3;
min_l =4;
sec_h = 0;
sec_l = 0;
tick = 0;
fill_data();
pause_cnt =0;
hr_pause_cnt = 0;
min_pause_cnt = 0;
//TMR1 setup
T1CON = 0x8F; // 887 TMR1 Prescaler 1:1 external clock
INTCON = 0xC0; // Set GIE, PEIE
TMR1H = 0x80;
TMR1L = 0x00;
Delay_ms(10); // Delay for setting up TMR1
PIE1.TMR1IE = 1; // enable interupt
tick =0;
while(1){
scroll();
}
}
void show_digit(unsigned short pos){
for(i=0;i<8;i++){
output[i] = data[i+pos];
}
}
void update_time(){
if(tick){
tick =0;
sec_l++;
make_time();
fill_data();
}
}
void make_time(){
if(sec_l>9){
sec_l = 0;
sec_h++;
}
if(sec_h>5){
sec_h=0;
min_l++;
}
if(min_l>9){
min_l = 0;
if(setting_time == 0){
min_h++;
}
}
if(min_h>5){
min_h = 0;
if(setting_time == 0){
hr_l++;
}
}
if(hr_l>9){
hr_l = 0;
if(setting_time == 0){
hr_h++;
}
}
if(hr_h >2){
hr_h = 0;
}
if(hr_h >=2 && hr_l>3){
if(setting_time == 0){
hr_h = 0;
}
hr_l = 0;
}
}
void fill_data(){
time[0] = hr_h;
time[1] = hr_l;
time[2] = 10;
time[3] = min_h;
time[4] = min_l;
time[5] = 11;
time[6] = sec_h;
time[7] = sec_l;
for(i = 0;i<8;i++){
for(j=0;j<4;j++){
data[j+4*i] = char2[time[i]][j];
}
}
}
void button_fn(unsigned short param1, unsigned short pos1, unsigned short pos2){
for(;;){
if(SET == 0){
Delay_ms(10);
while(SET == 0);
Delay_ms(10);
switch (param1){
case 1: hr_h++; break;
case 2: hr_l++; break;
case 3: min_h++;break;
case 4: min_l++;break;
}
make_time();
fill_data();
show_digit(pos1);
}
if(MYMODE == 0){
Delay_ms(10);
while(MYMODE == 0);
Delay_ms(10);
if( param1 == 4){
setting_time = 0;
ptr = 0;
base_ptr = 0;
}else{
show_digit(pos2);
}
break;
}
make_dotmatrix();
Delay_ms(1);
}
}
void check_bt(){
while(MYMODE == 0){
Delay_ms(10);
for(i=0;i<100;i++){
for(j=0;j<10;j++){
make_dotmatrix();
Delay_ms(1);
if(MYMODE != 0){
setting_time = 0;
change_MYMODE = 1;
break;
}
}
}
while(MYMODE == 0){ // Set Hr high
setting_time = 1;
show_digit(HR_H_POS);
make_dotmatrix();
}
if(change_MYMODE){
ptr=8;
base_ptr = 0;
change_MYMODE = 0;
}
}
if(setting_time){
INTCON.GIE = 0 ; //Stop time counting
button_fn(1, HR_H_POS, HR_L_POS);
button_fn(2, HR_L_POS, MIN_H_POS);
button_fn(3, MIN_H_POS, MIN_L_POS);
button_fn(4, MIN_L_POS, 0);
//Reset timer1
TMR1L = LTMR1;
TMR1H = HTMR1;
INTCON.GIE = 1 ; // start clock
sec_l =0;
sec_h =0;
tick=0;
make_time();
fill_data();
}
}
void pause_digit(unsigned short position, unsigned short pause_delay){
if(base_ptr == position){
if(pause_cnt<pause_delay){
base_ptr--;
pause_cnt++;
}else{
base_ptr = position+1;
pause_cnt=0;
}
}
}
void scroll(){
ptr = 0; //start pointer
base_ptr = 0;
while(base_ptr<41){
result_ptr = (base_ptr+ptr)%40;
output[ptr] = data[result_ptr];
ptr++;
if(ptr == 8){
ptr = 0;
base_ptr++;
//Sec pause
pause_digit(25,PAUSE_TIME);
//Min pause
pause_digit(13,HM_PAUSE_TIME);
//Hr pause
pause_digit(1,HM_PAUSE_TIME);
}
for(pp=0;pp<SCROLL_TIME_DELAY;pp++){
update_time();
make_dotmatrix();
}
update_time();
check_bt();
make_dotmatrix();
}
}
void make_dotmatrix(){
if(counter == 7){
PORTB = output[counter]; //sent font data to PORTB
Delay_us(DTime);
PORTB = 0x00; //Turn off dots
shift_register = 0x01;
PORTD = ~shift_register; //sent scan data to PORTD
counter = 0;
} else{
PORTB = output[counter];
Delay_us(DTime);
PORTB = 0x00; //Turn off dots
shift_register = shift_register << 1;
PORTD = ~shift_register;
counter++;
}
}
// PIC16F887
// I will use DS1307 as the RTC for the next improvement
// punkky@gmail.com
// 26 Sep 2008
#define MYMODE PORTA.F0
#define SET PORTA.F1
//External OSC 32.768KHz
#define HTMR1 0x80
#define LTMR1 0x00
//Constants for 4MHz Internal Clock
#define PAUSE_TIME 40
#define SCROLL_TIME_DELAY 60
#define HM_PAUSE_TIME 8
#define DTime 200
//Cursor Positions
#define HR_H_POS 0
#define HR_L_POS 0
#define DOT_1_POS 32
#define MIN_H_POS 12
#define MIN_L_POS 12
#define DOT_2_POS 56
#define SEC_H_POS 64
#define SEC_L_POS 72
//5x7 font
//Vertical scan , Little endian order
const unsigned char char2[][4]={
{0x1F,0x11,0x1F,0x00}, //0
{0x09,0x1F,0x01,0x00},
{0x17,0x15,0x1D,0x00},
{0x11,0x15,0x1F,0x00},
{0x1C,0x04,0x1F,0x00},
{0x1D,0x15,0x17,0x00},
{0x1F,0x15,0x17,0x00},
{0x10,0x10,0x1F,0x00},
{0x1F,0x15,0x1F,0x00},
{0x1D,0x15,0x1F,0x00}, //9
{0x0E,0x0E,0x0E,0x00}, //Comma1
{0x04,0x0E,0x04,0x00} //Comma2
};
unsigned char output[8];
unsigned char data[40];
unsigned char ptr;
unsigned char base_ptr;
unsigned char result_ptr;
unsigned char pp;
unsigned char pause_cnt;
unsigned char hr_pause_cnt;
unsigned char min_pause_cnt;
unsigned short counter;
unsigned short sec_h;
unsigned short sec_l;
unsigned short min_h;
unsigned short min_l;
unsigned short hr_h;
unsigned short hr_l;
unsigned short tick;
unsigned short num;
unsigned short i;
unsigned short j;
unsigned short time[8];
unsigned short setting_time;
unsigned short change_MYMODE;
void check_bt();
void button_fn(unsigned short param1, unsigned short pos1, unsigned short pos2);
void make_dotmatrix();
void interrupt() { //Internal clock
PIR1.TMR1IF = 0; // clears TMR1IF
TMR1H = HTMR1; //Set only high byte
tick = 1; // increment counter
}
void update_time();
void make_time();
void fill_data();
void show_digit(unsigned short pos);
void scroll();
void pause_digit(unsigned short position,unsigned short pause_delay);
unsigned short shift_register;
void main(){
setting_time = 0;
change_MYMODE = 0;
ANSEL = 0x00; //Digital I/O for PORTA
TRISA = 0x03;
PORTA = 0x03;
TRISB = 0x00;
PORTB = 0xFF;
TRISC = 0x0E;
TRISD = 0x00;
PORTD = 0x00;
ANSELH = 0x00; //Digital Input for PORTB
OSCCON = 0x65 ; //pic16f887 : 0110 0101, Internal Osc at 4MHz for lowest power consumption
counter = 0;
shift_register = 0x01;
hr_h = 1;
hr_l = 2;
min_h = 3;
min_l =4;
sec_h = 0;
sec_l = 0;
tick = 0;
fill_data();
pause_cnt =0;
hr_pause_cnt = 0;
min_pause_cnt = 0;
//TMR1 setup
T1CON = 0x8F; // 887 TMR1 Prescaler 1:1 external clock
INTCON = 0xC0; // Set GIE, PEIE
TMR1H = 0x80;
TMR1L = 0x00;
Delay_ms(10); // Delay for setting up TMR1
PIE1.TMR1IE = 1; // enable interupt
tick =0;
while(1){
scroll();
}
}
void show_digit(unsigned short pos){
for(i=0;i<8;i++){
output[i] = data[i+pos];
}
}
void update_time(){
if(tick){
tick =0;
sec_l++;
make_time();
fill_data();
}
}
void make_time(){
if(sec_l>9){
sec_l = 0;
sec_h++;
}
if(sec_h>5){
sec_h=0;
min_l++;
}
if(min_l>9){
min_l = 0;
if(setting_time == 0){
min_h++;
}
}
if(min_h>5){
min_h = 0;
if(setting_time == 0){
hr_l++;
}
}
if(hr_l>9){
hr_l = 0;
if(setting_time == 0){
hr_h++;
}
}
if(hr_h >2){
hr_h = 0;
}
if(hr_h >=2 && hr_l>3){
if(setting_time == 0){
hr_h = 0;
}
hr_l = 0;
}
}
void fill_data(){
time[0] = hr_h;
time[1] = hr_l;
time[2] = 10;
time[3] = min_h;
time[4] = min_l;
time[5] = 11;
time[6] = sec_h;
time[7] = sec_l;
for(i = 0;i<8;i++){
for(j=0;j<4;j++){
data[j+4*i] = char2[time[i]][j];
}
}
}
void button_fn(unsigned short param1, unsigned short pos1, unsigned short pos2){
for(;;){
if(SET == 0){
Delay_ms(10);
while(SET == 0);
Delay_ms(10);
switch (param1){
case 1: hr_h++; break;
case 2: hr_l++; break;
case 3: min_h++;break;
case 4: min_l++;break;
}
make_time();
fill_data();
show_digit(pos1);
}
if(MYMODE == 0){
Delay_ms(10);
while(MYMODE == 0);
Delay_ms(10);
if( param1 == 4){
setting_time = 0;
ptr = 0;
base_ptr = 0;
}else{
show_digit(pos2);
}
break;
}
make_dotmatrix();
Delay_ms(1);
}
}
void check_bt(){
while(MYMODE == 0){
Delay_ms(10);
for(i=0;i<100;i++){
for(j=0;j<10;j++){
make_dotmatrix();
Delay_ms(1);
if(MYMODE != 0){
setting_time = 0;
change_MYMODE = 1;
break;
}
}
}
while(MYMODE == 0){ // Set Hr high
setting_time = 1;
show_digit(HR_H_POS);
make_dotmatrix();
}
if(change_MYMODE){
ptr=8;
base_ptr = 0;
change_MYMODE = 0;
}
}
if(setting_time){
INTCON.GIE = 0 ; //Stop time counting
button_fn(1, HR_H_POS, HR_L_POS);
button_fn(2, HR_L_POS, MIN_H_POS);
button_fn(3, MIN_H_POS, MIN_L_POS);
button_fn(4, MIN_L_POS, 0);
//Reset timer1
TMR1L = LTMR1;
TMR1H = HTMR1;
INTCON.GIE = 1 ; // start clock
sec_l =0;
sec_h =0;
tick=0;
make_time();
fill_data();
}
}
void pause_digit(unsigned short position, unsigned short pause_delay){
if(base_ptr == position){
if(pause_cnt<pause_delay){
base_ptr--;
pause_cnt++;
}else{
base_ptr = position+1;
pause_cnt=0;
}
}
}
void scroll(){
ptr = 0; //start pointer
base_ptr = 0;
while(base_ptr<41){
result_ptr = (base_ptr+ptr)%40;
output[ptr] = data[result_ptr];
ptr++;
if(ptr == 8){
ptr = 0;
base_ptr++;
//Sec pause
pause_digit(25,PAUSE_TIME);
//Min pause
pause_digit(13,HM_PAUSE_TIME);
//Hr pause
pause_digit(1,HM_PAUSE_TIME);
}
for(pp=0;pp<SCROLL_TIME_DELAY;pp++){
update_time();
make_dotmatrix();
}
update_time();
check_bt();
make_dotmatrix();
}
}
void make_dotmatrix(){
if(counter == 7){
PORTB = output[counter]; //sent font data to PORTB
Delay_us(DTime);
PORTB = 0x00; //Turn off dots
shift_register = 0x01;
PORTD = ~shift_register; //sent scan data to PORTD
counter = 0;
} else{
PORTB = output[counter];
Delay_us(DTime);
PORTB = 0x00; //Turn off dots
shift_register = shift_register << 1;
PORTD = ~shift_register;
counter++;
}
}
Subscribe to:
Posts (Atom)