Ik vond het wel eens tijd worden mijn 12 jaar oude wekker radio te upgraden met een echte uC zodat ik het display en de behuizing voor leuke projecten kan gebruiken.

Het display en dus de clock werd aangestuurd door een TMS3450 (pdf) met een (vind ik) vreemde manier van multiplexen om de segmenten aan te sturen. (zie datasheet pagina 10 onderaan)

Ik gebruik nu de volgende syntax in C om het scherm aan te sturen: (dit is voorbeeld code, ben nu op mijn werk. Als ik thuis ben zal ik de exacte code posten.)


  Data0.0 = Digit0.0;
  Data0.1 = Digit0.2;
  Data0.2 = Digit0.5;
  Data0.3 = Digit1.5;
  Data0.4 = Digit1.3;
  Data0.5 = Digit1.2;
  Data0.6 = Digit1.0;
 

Ik zet dus steeds een bit over van de ene naar de andere byte. Ik gebruik een PIC 16F72 en het display zit aan een MCP23S17 via de hardware SPI poort.

Ik heb het scherm werkend gekregen en ik kan alle mogelijke cijfers weergeven alleen de functies waar deze code in voor komt zijn nogal groot. Na het compileren zijn ze ongeveer 160 words/instructies.

Weet iemand een betere manier om dit te programmeren?

Alvast bedankt,
Archer

Het is een vreemde manier van multiplexen maar wel logisch voor een klokdisplay. Segement 1 hoeft enkel maar 1 en 2 te kunnen weergeven. Seg 2 en 4 alles cijfers en segment 3 maar 0 t/m 5

Met vreemd bedoelde ik vooral dat all vier de segmenten met "maar" 2 row selects aangestuurt worden. En dat de volgorde van segment a,b,c, enz voor mij er vreemd uit ziet. Er zal vast over dit display nagedacht zijn, maar ik zie de logica er niet van. :)

Het eerste segment kan en hoeft inderdaad niet hoger te kunnen dan 2 (Al past er wel een 3 op) op de andere segmenten kan ik alles weergeven. Het eerste cijfer mist segment f waardoor een aantal getallen niet te lezen zijn.

Daar zit dan ook niet mijn "probleem". Door de multiplexing heb ik een conversie functie geschreven, die naar mijn mening niet echt optimaal is.

Dit is mijn code:


//76543210
// gfedcba
//01011011
void CLKDisplay_Row0(char Digit0,char Digit1,char Digit2, char Digit3,char Misc)
{
  char Disp0 = 0;
  char Disp1 = 0;
  if (Digit0 == 0x3f){Digit0 = 0;}  
  Disp0.0 = Misc.0;   //LED Upper Left
  Disp0.1 = Digit0.0; //Digit 0 - Segment A
  Disp0.2 = Digit0.3; //Digit 0 - Segment D
  Disp0.3 = Digit1.4; //Digit 1 - Segment E
  Disp0.4 = Digit1.6; //Digit 1 - Segment G
  Disp0.5 = Digit1.3; //Digit 1 - Segment D
  Disp0.6 = Digit1.5; //Digit 1 - Segment F
  
  Disp1.0 = Digit2.0; //Digit 2 - Segment A
  Disp1.1 = Digit2.1; //Digit 2 - Segment B
  Disp1.2 = Digit2.2; //Digit 2 - Segment C
  Disp1.3 = Digit3.4; //Digit 3 - Segment E
  Disp1.4 = Digit3.6; //Digit 3 - Segment G
  Disp1.5 = Digit3.3; //Digit 3 - Segment D
  Disp1.6 = Digit3.5; //Digit 3 - Segment F
  //Disp1.7 = Digit3.3; //Digit 2 - Segment ?
  
  CLOCK_ROW0 = 0;
  CLOCK_ROW1 = 0;
  //mcp0_write(GPIOA,0x00);
  mcp0_write(GPIOB,Disp0);
  mcp0_write(GPIOA,Disp1);
  CLOCK_ROW0 = 1;

}

//76543210
// gfedcba
void CLKDisplay_Row1(char Digit0,char Digit1,char Digit2, char Digit3,char Misc)
{
  char Disp0 = 0;
  char Disp1 = 0;

  if(Digit0 == 0x3f){Digit0 = 0;}  
  Disp0.0 = Digit0.1; //Digit 0 - Segment B
  Disp0.1 = Digit0.6; //Digit 0 - Segment G
  Disp0.2 = Digit0.4; //Digit 0 - Segment E
  Disp0.3 = Digit0.2; //Digit 0 - Segment C
  Disp0.4 = Digit1.1; //Digit 1 - Segment B
  Disp0.5 = Digit1.2; //Digit 1 - Segment C
  Disp0.6 = Digit1.0; //Digit 1 - Segment A
  
  Disp1.0 = Digit2.5; //Digit 2 - Segment F
  Disp1.1 = Digit2.6; //Digit 2 - Segment G
  Disp1.2 = Digit2.3; //Digit 2 - Segment D
  Disp1.3 = Digit2.4; //Digit 2 - Segment E
  Disp1.4 = Digit3.1; //Digit 3 - Segment B
  Disp1.5 = Digit3.2; //Digit 3 - Segment C
  Disp1.6 = ! Digit3.0; //Digit 3 - Segment A - Inverted
  //Disp1.7 = Digit3.7; //Digit 2 - Segment ?

  CLOCK_ROW0 = 0;
  CLOCK_ROW1 = 0;
  //mcp0_write(GPIOA,0x00);
  mcp0_write(GPIOB,Disp0);
  mcp0_write(GPIOA,Disp1 ^ 64);
  CLOCK_ROW1 = 1;
}

Eerst roep ik functie CLKDisplay_Row0 aan en een paar ms later CLKDisplay_Row1

In iedere Digit parameter zit een byte uit de volgende array:


const char _7segments[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6F};

De compiler maakt voor iedere bit het volgende blok aan


  BCF CLKDisplay_00016_1_Disp0,0
  BTFSC CLKDisplay_00016_arg_Digit0,1
  BSF CLKDisplay_00016_1_Disp0,0

Dit komt neer op ongeveer 130 asm instructies voor deze twee functies en dat vind ik best veel, daarom mijn vraag of dit op een andere manier beter kan. Mijn kennis van C is daar niet goed genoeg voor, ik heb altijd geprogrammeerd in Proton Basic.

Op 23 april 2009 18:52:29 schreef Archer:
Er zal vast over dit display nagedacht zijn, maar ik zie de logica er niet van.

Die manier van aansturen wordt duplex genoemd.

Het is een nogal tricky systeempje. Je kan het proberen met twee lookup tables voor kathode 1 en 2, maar aan flink wat code ontkom je niet. Die dingen zijn nou eenmaal specifiek gemaakt voor die wekkerradio chips.

Op 23 april 2009 19:05:10 schreef klein is fijn:
... aan flink wat code ontkom je niet.

Daar was ik al bang voor, het kan waarschijnlijk niet veel beter dan ik nu heb gedaan.

Ik zat ook te denken aan een lookup table maar dan moet ik minstens 60 records in die tabel stoppen, en dan kan ik niet eens "vreemde tekens" zoals A-F of H weergeven. Dat kan nu wel behalve op het eerste segment vanwege het ontbreken van 1 led.

Ik zal het met deze code moeten doen, en als ik meer FLASH ruimte nodig heb moet ik gewoon een grotere PIC gebruiken.

Bedankt voor de hulp.