Шахматные часы на Ардуино нано и дисплеях TM1637.
Схема
Симуляция в протеус.
Схема
C++:
//https://blog.3d-logic.com/2015/01/21/arduino-and-the-tm1637-4-digit-seven-segment-display/
const int clock1 = 7;
const int data1 = 8;
const int clock2 = 5;
const int data2 = 6;
const int red = 9;
const int selector = 11;
boolean swith=true;
const int yellow = 10;
byte dot = 128;
byte m1 = 5;
byte m2 = 5;
byte s1 = 0;
byte s2 = 0;
boolean x;
/*0*/ /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ /*6*/ /*7*/ /*8*/ /*9*/
uint8_t digits2[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
uint8_t digits1[] = { 0x3f, 0x30, 0x5b, 0x79, 0x74, 0x6d, 0x6F, 0x38, 0x7f, 0x7D };
const int pinread=2;
const int btnPin = 3;
unsigned long t;
unsigned long t1;
unsigned long t2;
void setup() {
pinMode(selector, INPUT_PULLUP);
pinMode(btnPin, INPUT_PULLUP);
pinMode(red, OUTPUT);
pinMode(yellow, OUTPUT);
digitalWrite(red, LOW);
digitalWrite(yellow, HIGH);
attachInterrupt(1, Stop, FALLING);
setupInterrupt();
pinMode(clock1, OUTPUT);
pinMode(data1, OUTPUT);
pinMode(clock2, OUTPUT);
pinMode(data2, OUTPUT);
pinMode(pinread, OUTPUT);
t1=0;
t2=0;
start(clock1,data1);
writeValue(clock1,data1,0x8c);
stop(clock1,data1);
start(clock2,data2);
writeValue(clock2,data2,0x8c);
stop(clock2,data2);
// clear display
write(clock1,data1,0x00, 0x00, 0x00, 0x00);
write(clock2,data2,0x00, 0x00, 0x00, 0x00);
//write(clock1,data1,digits1[1], digits1[2] | dot, digits1[3], digits1[4]);
// write(clock2,data2,digits2[8], digits2[7] | dot, digits2[6], digits2[5]);
swith = digitalRead(selector);
pinMode(selector, INPUT);
}
byte tcnt2;
unsigned long time = 0; // 86390000;
void Stop () {
/* First disable the timer overflow interrupt*/
TIMSK2 &= ~(1<<TOIE2);
digitalWrite(yellow, LOW);
digitalWrite(red, HIGH);
}
void loop() {
x = digitalRead(pinread);
if (swith){
reverseTime();
} else {
forwardTime();
}
}
void forwardTime(){
t = (unsigned long)(time/1000);
if (x) {
t1=t-t2;
} else {
t2=t-t1;
}
uint8_t minutes1 = (byte)((t1 / 60) % 60);
uint8_t seconds1 = (byte)(t1 % 60);
uint8_t minutes2 = (byte)((t2 / 60) % 60);
uint8_t seconds2 = (byte)(t2 % 60);
write(clock1,data1,digits1[seconds2 % 10],digits1[seconds2 / 10] | ((seconds2 & 0x01) << 7),digits1[minutes2 % 10],digits1[minutes2 / 10]);
write(clock2,data2,digits2[minutes1 / 10], digits2[minutes1 % 10] | ((seconds1 & 0x01) << 7) , digits2[seconds1 / 10], digits2[seconds1 % 10]);
}
void reverseTime() {
t = (unsigned long)(time/100);
if (x) {
t1=t-t2;
m1=4;
s1=59;
} else {
t2=t-t1;
m2=4;
s2=59;
}
uint8_t minutes1 = m1-(byte)((t1 / 600) % 60);
uint8_t seconds1 = s1-(byte)((t1 / 10) % 60);
uint8_t minutes2 = m2-(byte)((t2 / 600) % 60);
uint8_t seconds2 = s2-(byte)((t2 / 10) % 60);
uint8_t ms2 = 9 -(byte)(t2 % 10);
uint8_t ms1 = 9 -(byte)(t1 % 10);
if (t2<3000){
if (t2>2400) {
write(clock1,data1,0,digits1[ms2] | dot,digits1[seconds2 % 10],digits1[seconds2 / 10]);
} else {
write(clock1,data1,digits1[seconds2 % 10],digits1[seconds2 / 10] | dot,digits1[minutes2 % 10],digits1[minutes2 / 10]);
}
}
if (t1<3000){
if (t1>2400) {
write(clock2,data2,digits2[seconds1 / 10], digits2[seconds1 % 10] | dot, digits2[ms1], 0);
} else {
write(clock2,data2,digits2[minutes1 / 10], digits2[minutes1 % 10] | dot, digits2[seconds1 / 10], digits2[seconds1 % 10]);
}
}
}
void setupInterrupt()
{
/* First disable the timer overflow interrupt while we're configuring */
TIMSK2 &= ~(1<<TOIE2);
/* Configure timer2 in normal mode (pure counting, no PWM etc.) */
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
/* Select clock source: internal I/O clock */
ASSR &= ~(1<<AS2);
/* Disable Compare Match A interrupt enable (only want overflow) */
TIMSK2 &= ~(1<<OCIE2A);
/* Now configure the prescaler to CPU clock divided by 128 */
TCCR2B |= (1<<CS22) | (1<<CS20); // Set bits
TCCR2B &= ~(1<<CS21); // Clear bit
/* We need to calculate a proper value to load the timer counter.
* The following loads the value 131 into the Timer 2 counter register
* The math behind this is:
* (CPU frequency) / (prescaler value) = 125000 Hz = 8us.
* (desired period) / 8us = 125.
* MAX(uint8) + 1 - 125 = 131;
*/
/* Save value globally for later reload in ISR */
tcnt2 = 131;
/* Finally load end enable the timer */
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
}
/*
* Install the Interrupt Service Routine (ISR) for Timer2 overflow.
* This is normally done by writing the address of the ISR in the
* interrupt vector table but conveniently done by using ISR() */
ISR(TIMER2_OVF_vect) {
/* Reload the timer */
TCNT2 = tcnt2;
time++;
time = time % 86400000;
}
void write(int clock,int data,uint8_t first, uint8_t second, uint8_t third, uint8_t fourth)
{
start(clock,data);
writeValue(clock,data,0x40);
stop(clock,data);
start(clock,data);
writeValue(clock,data,0xc0);
writeValue(clock,data,first);
writeValue(clock,data,second);
writeValue(clock,data,third);
writeValue(clock,data,fourth);
stop(clock,data);
}
void start(int clock,int data)
{
digitalWrite(clock,HIGH);//send start signal to TM1637
digitalWrite(data,HIGH);
delayMicroseconds(5);
digitalWrite(data,LOW);
digitalWrite(clock,LOW);
delayMicroseconds(5);
}
void stop(int clock,int data)
{
digitalWrite(clock,LOW);
digitalWrite(data,LOW);
delayMicroseconds(5);
digitalWrite(clock,HIGH);
digitalWrite(data,HIGH);
delayMicroseconds(5);
}
bool writeValue(int clock,int data,uint8_t value)
{
for(uint8_t i = 0; i < 8; i++)
{
digitalWrite(clock, LOW);
delayMicroseconds(5);
digitalWrite(data, (value & (1 << i)) >> i);
delayMicroseconds(5);
digitalWrite(clock, HIGH);
delayMicroseconds(5);
}
// wait for ACK
digitalWrite(clock,LOW);
delayMicroseconds(5);
pinMode(data,INPUT);
digitalWrite(clock,HIGH);
delayMicroseconds(5);
bool ack = digitalRead(data) == 0;
pinMode(data,OUTPUT);
return ack;
}
Вложения
-
509.9 KB Просмотры: 105
Изменено: