Carlos Ventura
Published

MSP430 Alarm Clock with Grove Modules

Create your own alarm clock using the MSP430F5529 LaunchPad and the SeeedStudio Grove Modules.

Full instructions provided6,894
MSP430 Alarm Clock with Grove Modules

Things used in this project

Hardware components

MSP-EXP430F5529LP MSP430 LaunchPad
Texas Instruments MSP-EXP430F5529LP MSP430 LaunchPad
×1
Grove Starter Kit for LaunchPad
Seeed Studio Grove Starter Kit for LaunchPad
×1
SeeedStudio 4-Digit Display
Included in Grove Starter Kit
×1
SeeedStudio Buzzer
Included in Grove Starter Kit
×1

Story

Read more

Code

alarm_clock.ino

C/C++
Main Alarm Code. The main alarm code you will paste into your alarm project. Once you have the libraries in the correct place, you should be able to run the code smoothly.
#include "sRTCsec.h";
#include "legacymsp430.h"
#include "TimerSerial.h"
#include "ClickButton.h"
#include "TM1637.h"

#define CLK 9//pins definitions for TM1637 and can be changed to other ports
#define DIO 10

#define BUZZER_PIN               39            /* sig pin of the buzzer */
TM1637 tm1637(CLK,DIO);

#define OFF 0
#define ON 1

int8_t TimeDisp[] = {
  0x00,0x00,0x00,0x00};
  
int8_t RealTimeDisp[] = {
  0x00,0x00,0x00,0x00};
unsigned char ClockPoint = 1;
unsigned char Update;

// Declaring the constant values that will not change 

const int  buttonPin1 = PUSH1;    // the pin that the pushbutton is attached to
ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);

const int  buttonPin2 = PUSH2;    // the pin that the pushbutton is attached to
ClickButton button2(buttonPin2, LOW, CLICKBTN_PULLUP);

const int ledPin1 = RED_LED;       // the pin that the LED is attached to
const int ledPin2 = GREEN_LED;      // the pin that the LED is attached to

TimerSerial mySerial;
RealTimeClockSec myRTC;

int ledState = LOW;  

// Declaring the variables that will change:

// Referring to PUSH 1
int buttonPushCounter1 = 0;   // counter for the number of button presses
int buttonState1 = 0;         // current state of the button
int lastButtonState1 = 0;     // previous state of the button

// Referring to PUSH 2
int buttonPushCounter2 = 0;   // counter for the number of button presses
int buttonState2 = 0;         // current state of the button
int lastButtonState2 = 0;     // previous state of the button

int hrsSet =  0;              // keeps track of the actual time hour set 
int minSet =  0;              // keeps track of the actual time minute set 
int alarmHrs = 0;             // keeps track of the alarm time hour set 
int alarmMin = 0;             // keeps track of the alarm time minute set 
int alarmSec = 0;             // keeps track of the alarm time second set 

// Various flags used  throughout the timeset and alarmset functions:
int hrflag = 0;               // keeps track of time set toggle for hours
int minflag = 0;              // keeps track of time set toggle for minutes
int firstTime = 1;
int clicksflag = -1;
int stateflag = 0;
int alarmflag  = 0; // keeps track of alarm on/off 0 = off



// ButtonClicks1 function calculates the number of times Push 1 has been pressed
void ButtonClicks1(void) {
  // read the pushbutton input pin:
  buttonState1 = !digitalRead(buttonPin1);

  // compare the buttonState to its previous state
  if (buttonState1 != lastButtonState1) {
    // if the state has changed, increment the counter
    if (buttonState1 == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter1++;
      Serial.println("on");
      Serial.print("number of button 1 pushes:  ");
      Serial.println(buttonPushCounter1);
    }
    else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off");
    }
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState1 = buttonState1;
}


// ButtonClicks2 function calculates the number of times Push 2 has been pressed
void ButtonClicks2(void) {
  // read the pushbutton input pin:
  buttonState2 = !digitalRead(buttonPin2);

  // compare the buttonState to its previous state
  if (buttonState2 != lastButtonState2) {
    // if the state has changed, increment the counter
    if (buttonState2 == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter2++;
      Serial.println("on");
      Serial.print("number of button 2 pushes:  ");
      Serial.println(buttonPushCounter2);
    }
    else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off");
    }
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState2 = buttonState2;

}


// TimeUpdate allows the user to set the actual time and places the values set into RTC
// Time is displayed in 4-Digit display 

void TimeUpdate(void)
{
  if(ClockPoint)tm1637.point(POINT_ON);    // Turns 
  else tm1637.point(POINT_OFF);

   while(1){
   button1.Update();
   ButtonClicks1();
   ButtonClicks2();
  if ((buttonPushCounter1 % 2) == 0)      // Editing the hour side HH:MM = H1 H2 :M1 M2
  {
Serial.println("TIME UPDATE MODE we are changing hours");
    if(hrflag == 0){
      hrflag = 1;
      minflag = 0;

      if(firstTime){
        minSet = 0;
        firstTime = 0;
      }
      else
        minSet = buttonPushCounter2;

      buttonPushCounter2 = hrsSet;
    }

    hrsSet = (buttonPushCounter2 % 24);
  
    TimeDisp[0] = (hrsSet/10)%10;
    TimeDisp[1] = (hrsSet%10)%10;
    
  }
  else if ((buttonPushCounter1 % 2) == 1) 
  {
    Serial.println("TIME UPDATE MODE we are changing mins");
     if(minflag == 0){
      hrflag = 0;
      minflag = 1;
      hrsSet = buttonPushCounter2;
      buttonPushCounter2 = minSet;
    }

    minSet = (buttonPushCounter2 % 60);
    
    TimeDisp[2] = (minSet /10)%10;
    TimeDisp[3] = (minSet %10)%10;

  }
    
  button1.Update();
  tm1637.display(TimeDisp);
  

    if(button1.clicks ==2){    // Exit Time Update mode when double clicking
    
    myRTC.RTC_hr = hrsSet % 24;
    myRTC.RTC_min = minSet % 60;
    myRTC.RTC_sec = 0;
    stateflag = 0;
    return;
   }
   }
  Update = OFF;
};



// AlarmSet function allows user to set an alarm time and stores values 
// Alarm time is displayed in 4-Digit display 

void AlarmSet(void)
{
  
  if(ClockPoint)tm1637.point(POINT_ON);
  else tm1637.point(POINT_OFF);

   while(1){
   button1.Update();
   ButtonClicks1();
   ButtonClicks2();
  if ((buttonPushCounter1 % 2) == 0)  
  {
Serial.println("ALARM SET MODE we are changing hours");
    if(hrflag == 0){
      hrflag = 1;
      minflag = 0;

      if(firstTime){
        minSet = 0;
        firstTime = 0;
      }
      else
        minSet = buttonPushCounter2;

      buttonPushCounter2 = hrsSet;
    }

    hrsSet = (buttonPushCounter2 % 24);
  
    TimeDisp[0] = (hrsSet/10)%10;
    TimeDisp[1] = (hrsSet%10)%10;
    
  }
  else if ((buttonPushCounter1 % 2) == 1) 
  {
    Serial.println("ALARM SET MODE we are changing mins");
     if(minflag == 0){
      hrflag = 0;
      minflag = 1;
      hrsSet = buttonPushCounter2;
      buttonPushCounter2 = minSet;
    }

    minSet = (buttonPushCounter2 % 60);
    
    TimeDisp[2] = (minSet /10)%10;
    TimeDisp[3] = (minSet %10)%10;
  }
   
  
  button1.Update();
  tm1637.display(TimeDisp);
     
    alarmHrs = hrsSet % 24;
    alarmMin = minSet % 60;
    
    if(button1.clicks ==2){    // Exit Alarm Set mode when double clicking
    stateflag = 0;
    Serial.print("Alarm Time Set:");
    Serial.print(alarmHrs);
    Serial.print(":");
    Serial.print(alarmMin);
    return;
   }
   }
  Update = OFF;
};


// AlarmOn checks if all criteria is met to turn on the Alarm
void AlarmOn(void)
{
  // If the alarm is on and the alarm time set matches the current time
  if ((alarmflag == 1) && (alarmHrs == myRTC.RTC_hr) && (alarmMin == myRTC.RTC_min) && (alarmSec == myRTC.RTC_sec))
    {  
    digitalWrite(ledPin2, HIGH);       // turn the Green LED on while alarm goes off
    Serial.println("Alarm IS ON!!");   // Prints to Serial Monitor (Alarm is on)
    digitalWrite(BUZZER_PIN,HIGH);
   
    }
    else if (digitalRead(PUSH2) == LOW) {
    digitalWrite(ledPin2, LOW);   // turn the Green LED off while alarm goes off
    digitalWrite(BUZZER_PIN,LOW);
    return;
    }  
}


// Debug Function - Allows user to view the current time, 
void Debug (void)
{
    Serial.print(myRTC.RTC_hr, DEC);
    Serial.print(":");
    Serial.print(myRTC.RTC_min, DEC);
    Serial.print(":");
    Serial.print(myRTC.RTC_sec, DEC);
    Serial.print("   Alarm Flag: ");
    Serial.print(alarmflag);
    Serial.print("   Alarm Set Time ");
    Serial.print(alarmHrs);
    Serial.print(":");
    Serial.println(alarmMin);
    
}

// QuickBeep funtion makes the buzzer beep once for 200ms
void QuickBeep(void){
  digitalWrite(BUZZER_PIN,HIGH);
  delay(200);
  digitalWrite(BUZZER_PIN,LOW);
}

// QuickBeeps funtion makes the buzzer beep twice for 200ms with 100ms delay in between
void QuickBeeps(void){
  digitalWrite(BUZZER_PIN,HIGH);
  delay(200);
  digitalWrite(BUZZER_PIN,LOW);
  delay(100);
  digitalWrite(BUZZER_PIN,HIGH);
  delay(200);
  digitalWrite(BUZZER_PIN,LOW);
}
void fin() {
  Serial.end();
};




// Setup function runs once at the start

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);    
  digitalWrite(BUZZER_PIN,LOW);
  pinMode(2, OUTPUT);
  
  // This is to close the serial output so you are able to upload a new sketch to the LaunchPad
  pinMode(5, INPUT_PULLUP),
  attachInterrupt(5,fin,LOW);

  // initialize serial communication:
  Serial.begin(9600);

  // Adjusting the timer preferences
  tm1637.init();
  tm1637.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;

  button1.debounceTime   = 20;   // Debounce timer in ms
  button1.multiclickTime = 250;  // Time limit for multi clicks
  button1.longClickTime  = 1000; // time until "held-down clicks" register
}


void loop() {

  button1.Update();

  ButtonClicks1();
  ButtonClicks2();

  
switch (stateflag){ //Toggle between the different modes
  
  case 2:    // TIME UPDATE MODE 
    
    Serial.println("ENTERED TIME UPDATE MODE");
    digitalWrite(ledPin2, HIGH);   // turn the Green LED while time is being set
    TimeUpdate();                  // Calls the TimeUpdate function
    tm1637.display(TimeDisp);      // Displays the time on LCD
    digitalWrite(ledPin2, LOW);    // turn the green LED off 
    Serial.println("EXIT TIME UPDATE MODE");
    QuickBeeps();
    
    break;
    
  case 3:    // ALARM SET MODE
    
    Serial.println("ENTERED ALARM SET MODE");
    digitalWrite(ledPin1, HIGH);   // turn the Red LED while alarm time is being set
    AlarmSet();                    // Calls the AlarmSet funtion
    tm1637.display(TimeDisp);      // Displays time on LCD
    digitalWrite(ledPin1, LOW);    // turn the red LED off
    Serial.println("EXIT ALARM SET MODE");
    QuickBeeps();
    break;
  
  case 0:    // Default mode where time is displayed once it has been set
    
    Serial.println("TIME DISPLAY MODE");
    
    while(1) {
    AlarmOn();
    RealTimeDisp[0] = (myRTC.RTC_hr / 10);
    RealTimeDisp[1] = (myRTC.RTC_hr % 10); 
    RealTimeDisp[2] = (myRTC.RTC_min / 10); 
    RealTimeDisp[3] = (myRTC.RTC_min % 10);
    tm1637.display(RealTimeDisp);   
  
    if ((myRTC.RTC_sec % 2)==0 && ledState== LOW) {
      ledState = HIGH;
     Debug();
    };
  
    if ((myRTC.RTC_sec % 2)==1 && ledState== HIGH) {
      ledState = LOW;
     Debug();
     
   };


  ButtonClicks2();
  
  // Turning the Alarm On or Off pressing Push 2 while in Default Mode
   if ((buttonPushCounter2 % 2) == 0) {
      digitalWrite(ledPin1, LOW);   // turn the Red LED to display ALARM is ON
      alarmflag = 0;
      
    }
    else if ((buttonPushCounter2 % 2) == 1) {
     digitalWrite(ledPin1, HIGH);   // turn the Red LED to display ALARM is ON    
     alarmflag = 1;
     
  }
    button1.Update();
      
    if (button1.clicks == 2){
      stateflag = 2;
     
      
      QuickBeeps();
      break;
    }
    if (button1.clicks == 3){
      stateflag = 3;
      QuickBeeps();
      break;
    }
    }
    break;
}

};



interrupt(TIMER1_A0_VECTOR) Tic_Tac(void) {
  myRTC.Inc_sec();              // Update seconds
};

ClickButton.cpp

C/C++
ClickButton is a library that decodes multiple clicks on one button. Also copes with long clicks and click-and-hold.A positive number denotes the number of (short) clicks after a released button. A negative number denotes the number of "long" clicks.
/*    ClickButton
 
 Arduino library that decodes multiple clicks on one button.
 Also copes with long clicks and click-and-hold.
 
 Usage: ClickButton buttonObject(pin [LOW/HIGH, [CLICKBTN_PULLUP]]);
 
  where LOW/HIGH denotes active LOW or HIGH button (default is LOW)
  CLICKBTN_PULLUP is only possible with active low buttons.
 

 Returned click counts:

   A positive number denotes the number of (short) clicks after a released button
   A negative number denotes the number of "long" clicks
 
NOTE!
 This is the OPPOSITE/negative of click codes from the last pre-2013 versions!
 (this seemed more logical and simpler, so I finally changed it)

 Based on the Debounce example at arduino playground site

 
 Copyright (C) 2010,2012, 2013 raron

  
 GNU GPLv3 license
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.



 Contact: raronzen@gmail.com

 
 History:
 2013.08.29 - Some small clean-up of code, more sensible variable names etc.
                Added another example code for multiple buttons in an object array
 2013.04.23 - A "minor" debugging: active-high buttons now work (wops)!
                Thanks goes to John F. H. for pointing that out!
 2013.02.17 - Some improvements, simplified click codes.
				Added a LED fader example. Thanks to Tom K. for the idea.
 2012.01.31 - Tiny update for Arduino 1.0
 2010.06.15 - First version. Basically just a small OOP programming exercise.
*/

#include "ClickButton.h"

ClickButton::ClickButton(uint8_t buttonPin)
{
  _pin           = buttonPin;
  _activeHigh    = LOW;           // Assume active-low button
  _btnState      = !_activeHigh;  // initial button state in active-high logic
  _lastState     = _btnState;
  _clickCount    = 0;
  clicks         = 0;
  depressed      = false;
  _lastBounceTime= 0;
  debounceTime   = 20;            // Debounce timer in ms
  multiclickTime = 250;           // Time limit for multi clicks
  longClickTime  = 1000;          // time until long clicks register
  pinMode(_pin, INPUT_PULLUP);
}


ClickButton::ClickButton(uint8_t buttonPin, boolean activeType)
{
  _pin           = buttonPin;
  _activeHigh    = activeType;
  _btnState      = !_activeHigh;  // initial button state in active-high logic
  _lastState     = _btnState;
  _clickCount    = 0;
  clicks         = 0;
  depressed      = 0;
  _lastBounceTime= 0;
  debounceTime   = 20;            // Debounce timer in ms
  multiclickTime = 250;           // Time limit for multi clicks
  longClickTime  = 1000;          // time until long clicks register
  pinMode(_pin, INPUT_PULLUP);
}

ClickButton::ClickButton(uint8_t buttonPin, boolean activeType, boolean internalPullup)
{
  _pin           = buttonPin;
  _activeHigh    = activeType;
  _btnState      = !_activeHigh;  // initial button state in active-high logic
  _lastState     = _btnState;
  _clickCount    = 0;
  clicks         = 0;
  depressed      = 0;
  _lastBounceTime= 0;
  debounceTime   = 20;            // Debounce timer in ms
  multiclickTime = 250;           // Time limit for multi clicks
  longClickTime  = 1000;          // time until "long" click register
  pinMode(_pin, INPUT_PULLUP);
  // Turn on internal pullup resistor if applicable
  if (_activeHigh == LOW && internalPullup == CLICKBTN_PULLUP) digitalWrite(_pin,HIGH);
}



void ClickButton::Update()
{
  long now = (long)millis();      // get current time
  _btnState = digitalRead(_pin);  // current appearant button state

  // Make the button logic active-high in code
  if (!_activeHigh) _btnState = !_btnState;

  // If the switch changed, due to noise or a button press, reset the debounce timer
  if (_btnState != _lastState) _lastBounceTime = now;


  // debounce the button (Check if a stable, changed state has occured)
  if (now - _lastBounceTime > debounceTime && _btnState != depressed)
  {
    depressed = _btnState;
    if (depressed) _clickCount++;
  }

  // If the button released state is stable, report nr of clicks and start new cycle
  if (!depressed && (now - _lastBounceTime) > multiclickTime)
  {
    // positive count for released buttons
    clicks = _clickCount;
    _clickCount = 0;
  }

  // Check for "long click"
  if (depressed && (now - _lastBounceTime > longClickTime))
  {
    // negative count for long clicks
    clicks = 0 - _clickCount;
    _clickCount = 0;
  }

  _lastState = _btnState;
}

ClickButton.h

C/C++
ClickButton.h
#ifndef ClickButton_H

#define ClickButton_H



#if (ARDUINO <  100)

#include <WProgram.h>

#else

#include <Arduino.h>

#endif





#define CLICKBTN_PULLUP HIGH





class ClickButton

{

  public:

    ClickButton(uint8_t buttonPin);

    ClickButton(uint8_t buttonPin, boolean active);

    ClickButton(uint8_t buttonPin, boolean active, boolean internalPullup);

    void Update();

    int clicks;                   // button click counts to return

    boolean depressed;            // the currently debounced button (press) state (presumably it is not sad :)

    long debounceTime;

    long multiclickTime;

    long longClickTime;

  private:

    uint8_t _pin;                 // Arduino pin connected to the button

    boolean _activeHigh;          // Type of button: Active-low = 0 or active-high = 1

    boolean _btnState;            // Current appearant button state

    boolean _lastState;           // previous button reading

    int _clickCount;              // Number of button clicks within multiclickTime milliseconds

    long _lastBounceTime;         // the last time the button input pin was toggled, due to noise or a press

};



#endif

sRTCsec.cpp

C/C++
The sRTC Library is a library for adding simple RTC capabilities using MSP430 hardware
/*

 sRTC.h - Library for adding simple RTC capabilities using MSP430 hardware

 By Yannick DEVOS (XV4Y) - 2012

 */

 

// include this library's description file

#include <sRTCsec.h>

#include <legacymsp430.h>

 

// Constructor /////////////////////////////////////////////////////////////////

 

RealTimeClockSec::RealTimeClockSec(void)

{

    RTC_sec = 0;

    RTC_min = 0;

    RTC_hr = 0;

 

    WDTCTL = WDTPW | WDTHOLD; // Kill watch-dog

 

    UCSCTL1 = DIVA_3;        // Clock = ACLK / 8

    UCSCTL3 |= (XT1BYPASS | XCAP_3);        // Internal 12.5pF cap for 32KHz crystal

 

    TA1CCTL0 = CCIE;             //  CCR0 interupt activated

    TA1CCR0 = 4096-1;               // 4096 ticks of 32KHz XTal = 1 second => CCR0 counts N+1

    TA1CTL = TASSEL_1 | ID_3 | MC_1;  // Clock for TIMER 1 = ACLK, By 8 division, up front

 

};

 

// Methods /////////////////////////////////////////////////////////////////

 

void RealTimeClockSec::Inc_sec(void) {

    RTC_sec = RTC_sec + 1;            // Update seconds

    if (RTC_sec == 60) {

        RTC_sec=0;

        Inc_min();

    };

};

 

void RealTimeClockSec::Inc_min(void) {

    RTC_min = RTC_min + 1;            // Update minutes

    if (RTC_min == 60) {

        RTC_min=0;

        Inc_hr();

    };

};

 

void RealTimeClockSec::Inc_hr(void) {

    RTC_hr = RTC_hr + 1;              // Update hours

    if (RTC_hr == 24) {

        RTC_hr=0;

    };

};

 

void RealTimeClockSec::Set_Time(char hrs=0, char mins=0, char secs=0) {

    if ((hrs>=0 && hrs <24) && (mins>=0 && mins<60) && (secs>=0 && secs<60)) {

        RTC_hr = hrs;   // Set time to values given in parameters

        RTC_min = mins;

        RTC_sec = secs;

    };

};

sRTCsec.h

C/C++
sRTCsec.h
/*

 sRTC.h - Library for adding simple RTC capabilities using MSP430 hardware

 By Yannick DEVOS (XV4Y) - 2012

 

///////////////////////////////// How to use the lib

 

 * Create an instance of the object

 

 RealTimeClock myClock;

 

 * In order to have this RTC library working you should add this code to the end of your main program :

 

 interrupt(TIMER1_A0_VECTOR) Tic_Tac(void) {

    myClock.Inc_sec();            // Update secondes

 };

 

 * Enjoy the clock reading the RTC_sec, RTC_min, RTC_hr variables

 

 */

 

// ensure this library description is only included once

#ifndef RTCsec_h

#define RTCsec_h

 

// library interface description

class RealTimeClockSec

{

    // user-accessible "public" interface

public:

    RealTimeClockSec(void);

    void Set_Time(char hr, char mins, char secs);

    char RTC_sec; // This how you read the time, by reading the vars

    char RTC_min;

    char RTC_hr;

    void Inc_sec(void); // This methode should be invoked by an Interrupt call (see top of the file comment)

    // A few private methods

private:

    void Inc_min(void);

    void Inc_hr(void);

};

 

#endif

TM1637.h

C/C++
TM1637 Library allows the use of the 4-Digit Seven Segment Display
//  Author:Frankie.Chu

//  Date:9 April,2012

//

//  This library is free software; you can redistribute it and/or

//  modify it under the terms of the GNU Lesser General Public

//  License as published by the Free Software Foundation; either

//  version 2.1 of the License, or (at your option) any later version.

//

//  This library is distributed in the hope that it will be useful,

//  but WITHOUT ANY WARRANTY; without even the implied warranty of

//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

//  Lesser General Public License for more details.

//

//  You should have received a copy of the GNU Lesser General Public

//  License along with this library; if not, write to the Free Software

//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

//

//  Modified record:

//

/*******************************************************************************/



#ifndef TM1637_h

#define TM1637_h

#include <inttypes.h>

#include <Arduino.h>

//************definitions for TM1637*********************

#define ADDR_AUTO  0x40

#define ADDR_FIXED 0x44



#define STARTADDR  0xc0 

/**** definitions for the clock point of the digit tube *******/

#define POINT_ON   1

#define POINT_OFF  0

/**************definitions for brightness***********************/

#define  BRIGHT_DARKEST 0

#define  BRIGHT_TYPICAL 2

#define  BRIGHTEST      7



class TM1637

{

  public:

    uint8_t Cmd_SetData;

    uint8_t Cmd_SetAddr;

    uint8_t Cmd_DispCtrl;

    boolean _PointFlag;     //_PointFlag=1:the clock point on

    TM1637(uint8_t, uint8_t);

    void init(void);        //To clear the display

    void writeByte(int8_t wr_data);//write 8bit data to tm1637

    void start(void);//send start bits

    void stop(void); //send stop bits

    void display(int8_t DispData[]);

    void display(uint8_t BitAddr,int8_t DispData);

    void clearDisplay(void);

    void set(uint8_t = BRIGHT_TYPICAL,uint8_t = 0x40,uint8_t = 0xc0);//To take effect the next time it displays.

    void point(boolean PointFlag);//whether to light the clock point ":".To take effect the next time it displays.

    void coding(int8_t DispData[]); 

    int8_t coding(int8_t DispData); 

  private:

    uint8_t Clkpin;

    uint8_t Datapin;

};

#endif

TM1637.cpp

C/C++
//  Author:Frankie.Chu

//  Date:9 April,2012

//

//  This library is free software; you can redistribute it and/or

//  modify it under the terms of the GNU Lesser General Public

//  License as published by the Free Software Foundation; either

//  version 2.1 of the License, or (at your option) any later version.

//

//  This library is distributed in the hope that it will be useful,

//  but WITHOUT ANY WARRANTY; without even the implied warranty of

//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU

//  Lesser General Public License for more details.

//

//  You should have received a copy of the GNU Lesser General Public

//  License along with this library; if not, write to the Free Software

//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

//

//  Modified record:

//

/*******************************************************************************/

#include "TM1637.h"

#include <Arduino.h>

static int8_t TubeTab[] = {0x3f,0x06,0x5b,0x4f,

                           0x66,0x6d,0x7d,0x07,

                           0x7f,0x6f,0x77,0x7c,

                           0x39,0x5e,0x79,0x71};//0~9,A,b,C,d,E,F                        

TM1637::TM1637(uint8_t Clk, uint8_t Data)

{

  Clkpin = Clk;

  Datapin = Data;

  pinMode(Clkpin,OUTPUT);

  pinMode(Datapin,OUTPUT);

}



void TM1637::init(void)

{

  clearDisplay();

}



void TM1637::writeByte(int8_t wr_data)

{

  uint8_t i,count1;   

  for(i=0;i<8;i++)        //sent 8bit data

  {

    digitalWrite(Clkpin,LOW);      

    if(wr_data & 0x01)digitalWrite(Datapin,HIGH);//LSB first

    else digitalWrite(Datapin,LOW);

    wr_data >>= 1;      

    digitalWrite(Clkpin,HIGH);

      

  }  

  digitalWrite(Clkpin,LOW); //wait for the ACK

  digitalWrite(Datapin,HIGH);

  digitalWrite(Clkpin,HIGH);     

  pinMode(Datapin,INPUT);

  while(digitalRead(Datapin))    

  { 

    count1 +=1;

    if(count1 == 200)//

    {

     pinMode(Datapin,OUTPUT);

     digitalWrite(Datapin,LOW);

     count1 =0;

    }

    pinMode(Datapin,INPUT);

  }

  pinMode(Datapin,OUTPUT);

  

}

//send start signal to TM1637

void TM1637::start(void)

{

  digitalWrite(Clkpin,HIGH);//send start signal to TM1637

  digitalWrite(Datapin,HIGH); 

  digitalWrite(Datapin,LOW); 

  digitalWrite(Clkpin,LOW); 

} 

//End of transmission

void TM1637::stop(void)

{

  digitalWrite(Clkpin,LOW);

  digitalWrite(Datapin,LOW);

  digitalWrite(Clkpin,HIGH);

  digitalWrite(Datapin,HIGH); 

}

//display function.Write to full-screen.

void TM1637::display(int8_t DispData[])

{

  int8_t SegData[4];

  uint8_t i;

  for(i = 0;i < 4;i ++)

  {

    SegData[i] = DispData[i];

  }

  coding(SegData);

  start();          //start signal sent to TM1637 from MCU

  writeByte(ADDR_AUTO);//

  stop();           //

  start();          //

  writeByte(Cmd_SetAddr);//

  for(i=0;i < 4;i ++)

  {

    writeByte(SegData[i]);        //

  }

  stop();           //

  start();          //

  writeByte(Cmd_DispCtrl);//

  stop();           //

}

//******************************************

void TM1637::display(uint8_t BitAddr,int8_t DispData)

{

  int8_t SegData;

  SegData = coding(DispData);

  start();          //start signal sent to TM1637 from MCU

  writeByte(ADDR_FIXED);//

  stop();           //

  start();          //

  writeByte(BitAddr|0xc0);//

  writeByte(SegData);//

  stop();            //

  start();          //

  writeByte(Cmd_DispCtrl);//

  stop();           //

}



void TM1637::clearDisplay(void)

{

  display(0x00,0x7f);

  display(0x01,0x7f);

  display(0x02,0x7f);

  display(0x03,0x7f);  

}

//To take effect the next time it displays.

void TM1637::set(uint8_t brightness,uint8_t SetData,uint8_t SetAddr)

{

  Cmd_SetData = SetData;

  Cmd_SetAddr = SetAddr;

  Cmd_DispCtrl = 0x88 + brightness;//Set the brightness and it takes effect the next time it displays.

}



//Whether to light the clock point ":".

//To take effect the next time it displays.

void TM1637::point(boolean PointFlag)

{

  _PointFlag = PointFlag;

}

void TM1637::coding(int8_t DispData[])

{

  uint8_t PointData;

  if(_PointFlag == POINT_ON)PointData = 0x80;

  else PointData = 0; 

  for(uint8_t i = 0;i < 4;i ++)

  {

    if(DispData[i] == 0x7f)DispData[i] = 0x00;

    else DispData[i] = TubeTab[DispData[i]] + PointData;

  }

}

int8_t TM1637::coding(int8_t DispData)

{

  uint8_t PointData;

  if(_PointFlag == POINT_ON)PointData = 0x80;

  else PointData = 0; 

  if(DispData == 0x7f) DispData = 0x00 + PointData;//The bit digital tube off

  else DispData = TubeTab[DispData] + PointData;

  return DispData;

}

Credits

Carlos Ventura

Carlos Ventura

1 project • 7 followers

Comments