Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Clock
History
I got this idea by browsing the web. I found by hazard Mr. Bob
Blick's page who make the first propeller clock. I began to
check how can I build one myself. Base on AVR AT90S2313 I
saw rapidly that my MCU must be clocked very fast to make
all the calculations needed to light the leds at the right place.
The speed is at 16Mhz, 4 times faster than Atmel's
specifications. It's working without any problems.
Each time the PCB passed at 12h00 an hall effect sensor
sensed the magnet and generated an interruption. At this
time, we have to check the counter to se how many ticks had
been passed from this rotation since the last rotation tooks
this value and divide it by 360. This calculation will gives you
the time between each degree. Now, you have to set an
interruption to occur at each degree and after you will be able
to light leds whenever you want at any of 360 degrees. At
this MCU speed, there is no jitter everything is just FIXED!!!
Features
Analog clock mode
Digital clock mode
Infrared clock setting with a standard universal remote
control
Pictures
Click to enlarge
Anoalog mode
Digital mode
//**************************************
// Clock 16Mhz
// Version 1.0 Janvier 2002
// Sylvain Bissonnette
//**************************************
//**************************************
//
INCLUDE
//**************************************
#include <io2313v.h>
#include <macros.h>
//**************************************
//
DEFINE
//**************************************
#define TRUE
0x01
#define FALSE
0x00
#define ANALOG 0x01
#define DIGITAL 0x02
//**************************************
// I N T E R R U P T H A N D L E R
//**************************************
#pragma interrupt_handler Crossing_interrupt:2
#pragma interrupt_handler IR_interrupt:4
#pragma interrupt_handler Degre_interrupt:5
#pragma interrupt_handler Ticker_interrupt:7
//**************************************
//
PROTOTYPE
//**************************************
void
void
void
void
void
void
void
void
Crossing_interrupt(void);
Degre_interrupt(void);
Time(unsigned char);
IR_interrupt(void);
Ticker_interrupt(void);
Display(void);
CopyData(int Value);
CopyDot(void);
//**************************************
// G L O B A L V A R I A B L E
//**************************************
int WeelPosition;
unsigned char Pos;
unsigned int Adder;
unsigned char LatchedIrData;
unsigned char Sec;
unsigned char Min;
unsigned char Hrs;
int SecComp;
int MinComp;
int HrsComp;
unsigned char ClockStyle;
unsigned char TimeString[50];
unsigned char *TimeStringPtr;
unsigned char i;
//**************************************
//
CONSTANT
//**************************************
const unsigned char table[12][6] = {{ 0x3e, 0x41, 0x41, 0x41,
0x3e, 0x00 }, // 0
{ 0x00, 0x21, 0x7f, 0x01, 0x00, 0x00 }, // 1
{ 0x21, 0x43, 0x45, 0x49, 0x31, 0x00 }, // 2
{ 0x42, 0x41, 0x51, 0x69, 0x46, 0x00 }, //
3
{ 0x0c, 0x14, 0x24, 0x5f, 0x04, 0x00 }, // 4
{ 0x72, 0x51, 0x51, 0x51, 0x4e, 0x00 }, // 5
{ 0x1e, 0x29, 0x49, 0x49, 0x06, 0x00 }, // 6
{ 0x40, 0x47, 0x48, 0x50, 0x60, 0x00 }, // 7
{ 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 }, // 8
{ 0x30, 0x49, 0x49, 0x4a, 0x3c, 0x00 }, // 9
{ 0x00, 0x36, 0x36, 0x00, 0x00, 0x00 }, // :
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};//
space
//**************************************
//
MAIN
//**************************************
void main()
{
WDTCR = 0x0e;
// Enable WatchDog at 0.97 sec
PORTD = 0x0d;
DDRD = 0x03;
PD7-I
//INT 0
MCUCR = 0x02;
GIMSK = 0x40;
//Timer0
TCCR0 = 0x05;
// Timer0 / 1024
//Timer1
TCCR1B = 0x42;
// Timer1 / 8 & Input Capture on Rising eadge
TIMSK = 0x4a;
// int enable on Timer1 Compare Match
// int enable on Timer 1 Input Capture
// int enable on Timer0 Overflow
PORTB = 0x00;
DDRB = 0xff;
// PB0-7 as output
Hrs = 0;
Min = 0;
Sec = 0;
ClockStyle = ANALOG;
SEI();
while(1)
{
asm("WDR");
for (i=0;i<200;i++);
if ((LatchedIrData == 0xbb) || (LatchedIrData == 0x92))
Time(TRUE);
if ((LatchedIrData == 0xb3) || (LatchedIrData == 0xb0)) ClockStyle
= DIGITAL;
void Time(void)
Description:
Input:
Output:
none
none
Misc:
**********************************************************/
void Time(unsigned char Fast)
{
if (Fast == FALSE) Sec++;
else Sec += 60;
if (Sec > 59)
{
Sec = 0;
Min++;
if (Min > 59)
{
Min = 0;
Hrs++;
if (Hrs > 11)
{
Hrs = 0;
}
}
}
if (ClockStyle == ANALOG)
{
SecComp = Sec*6;
MinComp = Min*6;
HrsComp = (Hrs*30)+(Min/2);
}
else
{
TimeStringPtr = &TimeString[0];
CopyData(Hrs);
CopyDot();
CopyData(Min);
CopyDot();
CopyData(Sec);
}
}
/**********************************************************
Name:
Description:
Input:
Output:
none
none
Misc:
**********************************************************/
void CopyData(int Value)
{
if (Value < 10)
{
for (i=0;i<6;i++) *TimeStringPtr++ = table[0][i];
for (i=0;i<6;i++) *TimeStringPtr++ = table[Value][i];
}
else
{
for (i=0;i<6;i++) *TimeStringPtr++ = table[Value/10][i];
for (i=0;i<6;i++) *TimeStringPtr++ = table[Value-((Value/10)*10)]
[i];
}
}
/**********************************************************
Name:
void CopySpace(void)
Description:
Input:
none
Output:
none
Misc:
**********************************************************/
void CopyDot(void)
{
for (i=0;i<6;i++) *TimeStringPtr++ = table[10][i];
}
/**********************************************************
Name:
void Crossing_interrupt(void
Description:
Input:
Output:
none
none
Misc:
**********************************************************/
void Crossing_interrupt(void)
{
static unsigned int LastCount;
static unsigned int TotalCount;
static int Latch;
static unsigned char Lap;
Latch = TCNT1;
TotalCount = Latch - LastCount;
LastCount = Latch;
Lap++;
if (Lap > 250)
{
Adder = TotalCount / 378;
Lap = 0;
}
WeelPosition = 0;
OCR1 = Latch + Adder;
TIFR |= 0x80;
Display();
}
/**********************************************************
Name:
void Degre_interrupt(void)
Description:
Input:
none
Output:
none
Misc:
**********************************************************/
void Degre_interrupt(void)
{
OCR1 = TCNT1 + Adder;
Display();
}
/**********************************************************
Name:
void Display(void)
Description:
Input:
Output:
none
none
Misc:
**********************************************************/
void Display(void)
{
PORTB = 0x00;
if (ClockStyle == ANALOG)
{
if (WeelPosition == HrsComp) PORTB = 0x80;
if (WeelPosition == MinComp) PORTB = 0xff;
if (WeelPosition == SecComp) PORTB |= 0x03;
if ((WeelPosition == 0) ||
(WeelPosition == 30) ||
(WeelPosition == 60) ||
(WeelPosition == 90) ||
(WeelPosition == 120) ||
(WeelPosition == 150) ||
(WeelPosition == 180) ||
(WeelPosition == 210) ||
(WeelPosition == 240) ||
(WeelPosition == 270) ||
(WeelPosition == 300) ||
(WeelPosition == 330)) PORTB |= 0x01;
}
else
{
Pos = ((WeelPosition-100) / 3);
if (Pos < 49)
{
PORTB = TimeString[48-Pos];
}
}
WeelPosition++;
}
/**********************************************************
Name:
void IR_interrupt(void)
none
Output:
Misc:
**********************************************************/
void IR_interrupt(void)
{
static unsigned int LastCapture;
unsigned int PulseWidth;
static unsigned int IrPulseCount;
static unsigned int IrData;
PulseWidth = ICR1 - LastCapture;
LastCapture = ICR1;
void Ticker_interrupt(void)
Description:
Input:
none
Output:
none
Misc:
**********************************************************/
void Ticker_interrupt(void)
{
static unsigned char Tick;
Tick++;
if (Tick > 62)
{
Time(FALSE);
Tick = 0;
}
TCNT0 = 0x04; // reload counter
}