
Důvodem vzniku této aplikace hodin, případně čítače bylo obdržení objednaných displejů pro digitální stupnici BITX z Ebay. K mému rozčarování tyto displeje sice mají desetinné tečky a dvojtečku, ale lze rozsvítit pouze dvojtečku. Bohužel datasheet k tomuto displeji CL5642BH jsem nesehnal, ale vzhledem k ceně 8.33USD vč. poštovného za 10ks jsem jej objednal.
Z důvodu využití těchto displejů alespoň k něčemu, vznikla tato aplikace. Vzhledem k dostupnému vývojovému kitu MSP-EXP430G2 (u TI v eshopu za 4.30USD, Farnel za 98Kč bez DPH) jsem zvolil řadu MSP430.
Kit obashuje 2ks obvodů a to MSP430G2211 a MSP430G2231 v pouzdře DIL14. Na hodiny plně vyhoví prvně jmenovaný 2211.
Hodiny jsou vzhledem k malému počtu portů rozšířeny o shift registr. Vzhledem k ne zcela dostupným stabilizátorům 3.3V jsem použil 7805 (78L05) se snížením napětí pomocí 2 diod 1N4148. Lze však použít např. LE33CZ v pouzdře TO92 a diody D1, D2 nahradit zkratovací propojkou. Zapojení LE33CZ je stejné jako 78L05.
Jako další možnost je na PCB místo pro vstupní tvarovač pro jednoduchý čítač, prozatím neosazen,
Tlačítka jsou klasické "žabky", já na prototypu použil co jsem našel v šuplíku. Neosazeny jsou pozice R12-R14, T5,C4 a X2.
K vývoji s těmito procesory je k dispozici několik různých vývojovách prostředí, používám IAR, který generuje značně optimalizovaný kód a do 4kB přeloženého kódu je zdarma.
Více na stránkách TI zde
Ke stažení poslední verze a popis změn od předchozích verzí zde
Pár linků na datasheet a popis celé rodiny, ačkoliv toto může vypadat jako jakási forma reklamy, dělám to spíše kvůli omezení dotazů typu "kde najdu" a snadnějšímu hledání. Je možné, že při další revizi dokumentů výrobcem již nebudou linky fungovat korektně, pak je nutné hledat přímo na stránkách TI.
Datasheet obvodu MSP430G2211 zde
User guide od celé rodiny CPU MSP430x2xx zde
Obsazení paměti po zkompilování:
772 bytes of CODE memory
64 bytes of DATA memory (+ 19 absolute )
11 bytes of CONST memory
Listing aktuálního programu pro hodiny, bohužel formátování textu vzalo za své, v sekci ke stažení je celý projekt a další soubory k dispozici.
//******************************************************************************
// Ridici program pro hodiny
//
// Robert Kucera
// OK2UWQ
// c 2012
// Built with IAR Embedded Workbench Version: 5.10
//
//******************************************************************************
#include "msp430g2211.h"
const unsigned char table[]={0x21,0xe7,0x34,0xa4,0xe2,0xa8,0x28,0xe5,0x20,0xa0,0xff}; //tabulka znaku 0-9
static unsigned char disp[4];
static unsigned char locksw; // pro osetreni zakmitu tlacitek
static unsigned char autoinc; // povoleni automatickeho pricitani pri nastavovani casu
static unsigned char autotmr; // cas zpozdeni od stisku tlacitka k povoleni autoinc (*0,5sec)
static unsigned char autocnt; // zpozdeni - rychlost pricitani hodnoty
static unsigned char showpos; // pozice zobrazovaneho segmentu v multiplexu
static unsigned char display; // navesti k zobrazeni dalsi pozice - zobrazeni mimo preruseni
static unsigned char divsec; // pomocne pocitadlo pro 0.5sec
static unsigned char sec; // pocitadlo 1/2 sec
static unsigned char min; // pocitadlo minut
static unsigned char hod; // pocitadlo hodin
/*******************************************/
void Set164(unsigned char data) // posle 8bitu na vystup registru
{
unsigned char i,j;
i = data;
for(j=0;j<8;j++){
P1OUT &= ~0x80;
P1OUT |= (i & 0x80);
P1OUT |= 0x40; //clk high - posun registru o 1
i = i<<1;
P1OUT &= ~0x40; //clk low
}
}
void DecodeTime(void) // nacte aktualni cas do registru pro zobrazeni
{
disp[0] = hod / 10; // desitky hodin
disp[1] = hod % 10; // jednotky hodin
disp[2] = min / 10; // desitky minut
disp[3] = min % 10; // jednotky minut
}
#pragma vector=PORT1_VECTOR
__interrupt void port1_irq (void) //osetreni preruseni os stisku tlacitka
{
if(P1IFG & 0x01){
P1IFG ^= 0x01;
if(!locksw){
min++; // pri stisku tlacitka pricteni +1 a
sec=0;
divsec=0; // nulovani sekund a pom. pocitadla
if(min==60)min=0;
locksw++; // zpozdeni - osetreni zakmitu
DecodeTime();
autotmr=6; // reset pocitadla autoinc na 3sec
}
}
if(P1IFG & 0x02){ // obdobne pro stisk tlacitka hodin
P1IFG ^= 0x02;
if(!locksw){
hod++;
if(hod==24)hod=0;
locksw++;
DecodeTime();
autotmr=6;
}
}
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void) // obsluha preruseni od citace - takt 512Hz
{
display++; //priznak - po ukonceni preruseni posun na zobrazeni dalsiho segmentu
divsec++; // citac /256 - vysledny takt 0,5sec pro blikani dvojtecky a dalsi pocitani
if((P1IN & 0x03)==0x03){
autotmr=0;
autocnt=0;
autoinc=0;
}
if(divsec==0){
sec++;
if(autotmr>0){
autotmr--;
if(autotmr==0)autoinc++; //citac zpozdeni autoinc
}
locksw=0;
if(sec==120){ // citani jedne minuty - 120*0,5sec
sec=2; //kompenzace chyby cca 1sec/min
min++;
if(min==60){ // citani hodin - 60min
min=0;
hod++;
if(hod==24)hod=0;
}
DecodeTime(); // obnova zobrazeni aktualniho casu na displeji
}
}
if(autoinc){ // povolen autoinc
autocnt++;
if(autocnt==64){ // cekani na napocitani zpozdeni
if(~P1IN & 0x01){ // test stisknuteho tlacitka minut
min++;
sec=0;
divsec=0;
if(min==60)min=0;
}
if(~P1IN & 0x02){ // test stisknuteho tlacitka hodin
hod++;
if(hod==24)hod=0;
}
DecodeTime();
autocnt=0;
}
}
}
int main( void )
{
unsigned char dt;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 64; // interrupt timming
TACTL = TASSEL_1 + MC_1; // ACLK, up mode
P1DIR = 0xfc;
P1REN = 0x03;
P1OUT = 0x3f;
P1IE |= 0x03; // Enable interrupt for all pins
P1IES |= 0x03; // set H-L transition to set IRQ
P1IFG = 0;
showpos = 0; // nulovani pomocnych pocitadel a navesti
divsec = 0;
sec = 0;
min = 0;
hod = 0;
DecodeTime();
_BIS_SR(GIE); // povoleni preruseni
while(1){
if(display){
P1OUT |=(0x04 << showpos); // zhasnuti predchoziho segmentu
showpos++; // posun na dalsi pozici
dt = 0;
if((showpos==1)&((sec&0x01)==0x01))dt=0x20; //je-li dvojtecka, zobraz co 0,5sec
if(showpos>3)showpos=0; // max. 4 segmenty, pak navrat na prvni
Set164(table[disp[showpos]]&~dt); // zobrazeni obsahu disp a prevod podle table
P1OUT &=~(0x04 << showpos); // rozsviceni segmentu
display=0; // nulovani navesti
}
}
}
Z důvodu využití těchto displejů alespoň k něčemu, vznikla tato aplikace. Vzhledem k dostupnému vývojovému kitu MSP-EXP430G2 (u TI v eshopu za 4.30USD, Farnel za 98Kč bez DPH) jsem zvolil řadu MSP430.
Kit obashuje 2ks obvodů a to MSP430G2211 a MSP430G2231 v pouzdře DIL14. Na hodiny plně vyhoví prvně jmenovaný 2211.
![]() |
deska kitu MSP-EXP430G2 |
![]() |
Reálný vzorek prototypu desky - aktuální verze má navíc oddělovací diodu pro připojení VCC z emulačního kitu. Fotografie více nasvícená a navíc v prototypu použity resistory 100R namísto finálních 22R, takže svit segmentů je menší. |
Hodiny jsou vzhledem k malému počtu portů rozšířeny o shift registr. Vzhledem k ne zcela dostupným stabilizátorům 3.3V jsem použil 7805 (78L05) se snížením napětí pomocí 2 diod 1N4148. Lze však použít např. LE33CZ v pouzdře TO92 a diody D1, D2 nahradit zkratovací propojkou. Zapojení LE33CZ je stejné jako 78L05.
![]() |
Jako další možnost je na PCB místo pro vstupní tvarovač pro jednoduchý čítač, prozatím neosazen,
Tlačítka jsou klasické "žabky", já na prototypu použil co jsem našel v šuplíku. Neosazeny jsou pozice R12-R14, T5,C4 a X2.
![]() |
![]() |
![]() |
K vývoji s těmito procesory je k dispozici několik různých vývojovách prostředí, používám IAR, který generuje značně optimalizovaný kód a do 4kB přeloženého kódu je zdarma.
Více na stránkách TI zde
Ke stažení poslední verze a popis změn od předchozích verzí zde
Pár linků na datasheet a popis celé rodiny, ačkoliv toto může vypadat jako jakási forma reklamy, dělám to spíše kvůli omezení dotazů typu "kde najdu" a snadnějšímu hledání. Je možné, že při další revizi dokumentů výrobcem již nebudou linky fungovat korektně, pak je nutné hledat přímo na stránkách TI.
Datasheet obvodu MSP430G2211 zde
User guide od celé rodiny CPU MSP430x2xx zde
Obsazení paměti po zkompilování:
772 bytes of CODE memory
64 bytes of DATA memory (+ 19 absolute )
11 bytes of CONST memory
Listing aktuálního programu pro hodiny, bohužel formátování textu vzalo za své, v sekci ke stažení je celý projekt a další soubory k dispozici.
//******************************************************************************
// Ridici program pro hodiny
//
// Robert Kucera
// OK2UWQ
// c 2012
// Built with IAR Embedded Workbench Version: 5.10
//
//******************************************************************************
#include "msp430g2211.h"
const unsigned char table[]={0x21,0xe7,0x34,0xa4,0xe2,0xa8,0x28,0xe5,0x20,0xa0,0xff}; //tabulka znaku 0-9
static unsigned char disp[4];
static unsigned char locksw; // pro osetreni zakmitu tlacitek
static unsigned char autoinc; // povoleni automatickeho pricitani pri nastavovani casu
static unsigned char autotmr; // cas zpozdeni od stisku tlacitka k povoleni autoinc (*0,5sec)
static unsigned char autocnt; // zpozdeni - rychlost pricitani hodnoty
static unsigned char showpos; // pozice zobrazovaneho segmentu v multiplexu
static unsigned char display; // navesti k zobrazeni dalsi pozice - zobrazeni mimo preruseni
static unsigned char divsec; // pomocne pocitadlo pro 0.5sec
static unsigned char sec; // pocitadlo 1/2 sec
static unsigned char min; // pocitadlo minut
static unsigned char hod; // pocitadlo hodin
/*******************************************/
void Set164(unsigned char data) // posle 8bitu na vystup registru
{
unsigned char i,j;
i = data;
for(j=0;j<8;j++){
P1OUT &= ~0x80;
P1OUT |= (i & 0x80);
P1OUT |= 0x40; //clk high - posun registru o 1
i = i<<1;
P1OUT &= ~0x40; //clk low
}
}
void DecodeTime(void) // nacte aktualni cas do registru pro zobrazeni
{
disp[0] = hod / 10; // desitky hodin
disp[1] = hod % 10; // jednotky hodin
disp[2] = min / 10; // desitky minut
disp[3] = min % 10; // jednotky minut
}
#pragma vector=PORT1_VECTOR
__interrupt void port1_irq (void) //osetreni preruseni os stisku tlacitka
{
if(P1IFG & 0x01){
P1IFG ^= 0x01;
if(!locksw){
min++; // pri stisku tlacitka pricteni +1 a
sec=0;
divsec=0; // nulovani sekund a pom. pocitadla
if(min==60)min=0;
locksw++; // zpozdeni - osetreni zakmitu
DecodeTime();
autotmr=6; // reset pocitadla autoinc na 3sec
}
}
if(P1IFG & 0x02){ // obdobne pro stisk tlacitka hodin
P1IFG ^= 0x02;
if(!locksw){
hod++;
if(hod==24)hod=0;
locksw++;
DecodeTime();
autotmr=6;
}
}
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void) // obsluha preruseni od citace - takt 512Hz
{
display++; //priznak - po ukonceni preruseni posun na zobrazeni dalsiho segmentu
divsec++; // citac /256 - vysledny takt 0,5sec pro blikani dvojtecky a dalsi pocitani
if((P1IN & 0x03)==0x03){
autotmr=0;
autocnt=0;
autoinc=0;
}
if(divsec==0){
sec++;
if(autotmr>0){
autotmr--;
if(autotmr==0)autoinc++; //citac zpozdeni autoinc
}
locksw=0;
if(sec==120){ // citani jedne minuty - 120*0,5sec
sec=2; //kompenzace chyby cca 1sec/min
min++;
if(min==60){ // citani hodin - 60min
min=0;
hod++;
if(hod==24)hod=0;
}
DecodeTime(); // obnova zobrazeni aktualniho casu na displeji
}
}
if(autoinc){ // povolen autoinc
autocnt++;
if(autocnt==64){ // cekani na napocitani zpozdeni
if(~P1IN & 0x01){ // test stisknuteho tlacitka minut
min++;
sec=0;
divsec=0;
if(min==60)min=0;
}
if(~P1IN & 0x02){ // test stisknuteho tlacitka hodin
hod++;
if(hod==24)hod=0;
}
DecodeTime();
autocnt=0;
}
}
}
int main( void )
{
unsigned char dt;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = 64; // interrupt timming
TACTL = TASSEL_1 + MC_1; // ACLK, up mode
P1DIR = 0xfc;
P1REN = 0x03;
P1OUT = 0x3f;
P1IE |= 0x03; // Enable interrupt for all pins
P1IES |= 0x03; // set H-L transition to set IRQ
P1IFG = 0;
showpos = 0; // nulovani pomocnych pocitadel a navesti
divsec = 0;
sec = 0;
min = 0;
hod = 0;
DecodeTime();
_BIS_SR(GIE); // povoleni preruseni
while(1){
if(display){
P1OUT |=(0x04 << showpos); // zhasnuti predchoziho segmentu
showpos++; // posun na dalsi pozici
dt = 0;
if((showpos==1)&((sec&0x01)==0x01))dt=0x20; //je-li dvojtecka, zobraz co 0,5sec
if(showpos>3)showpos=0; // max. 4 segmenty, pak navrat na prvni
Set164(table[disp[showpos]]&~dt); // zobrazeni obsahu disp a prevod podle table
P1OUT &=~(0x04 << showpos); // rozsviceni segmentu
display=0; // nulovani navesti
}
}
}