Also ich habs zwar, aber die optimierte Funktion (SetBits2) ist deutlich langsamer (siehe die Zeitangaben/Kommentar im Procedurekopf rechts. 42s bis 50000 heißt 42 Sekunden Programmstart bis auf 50000 gezählt wurde). SetBit und SetBit2 haben die gleiche Funktion.
Code
Program DTest;
{ MAX7219-Test }
{$NOSHADOW}
{ $WG} {global Warnings off}
Device = mega644, VCC=5;
{ $BOOTRST $07000} {Reset Jump to $07000}
Import SysTick, SPIDriver1;
From System Import LongWord;
Define
ProcClock = 20000000; {Hertz}
SysTick = 10; {msec}
StackSize = $0064, iData;
FrameSize = $0064, iData;
SPIdriver1 = PortB, 0, 1, 2; // SCK, MOSI, MISO
SPIorder1 = MSB;
SPIcPHA1 = 0;
SPIcPol1 = 0;
Implementation
{$IDATA}
{------------------------------------------------------------------------------}
{ Type Declarations }
Type
{------------------------------------------------------------------------------}
{ Const Declarations }
Const // PGFEDCBA
ShowNum : Array[0..14] of Byte = (%00111111, %00000110, %01011011, //0,1,2
%01001111, %01100110, %01101101, //3,4,5
%01111101, %00000111, %01111111, //6,7,8
%01101111, %01100011, %00100000, //9,°,`
%00100010, %00000000, %00000000); //", ,
{------------------------------------------------------------------------------}
{ Var Declarations }
Var
DispData : Array[1..8] of Byte;
Count1 : Byte;
Count2 : LongWord;
{$IDATA}
{------------------------------------------------------------------------------}
{ functions }
{ **************************************************************************** }
Procedure InitPorts;
Begin
DDRB:= %00001011; // xxxx /CS MISO MOSI SCK
PortB:= %00001000; //
End InitPorts;
{------------------------------------------------------------------------------}
{ Main Program }
{$IDATA}
Procedure SetBits(Num,Digit:Byte); // Zahl Num auf Stelle Digit
Var DigVal : Byte; // 31s bis 50000
Begin // 25s bis 50000 mit Optimizer
Case Digit of
1:DigVal:= 1;|
2:DigVal:= 2;|
3:DigVal:= 4;|
4:DigVal:= 8;|
5:DigVal:= 16;|
6:DigVal:= 32;|
7:DigVal:= 64;|
8:DigVal:=128;|
EndCase;
If (ShowNum[Num] and $01)=$01
then
DispData[1]:=DispData[1] or DigVal;
EndIf;
If (ShowNum[Num] and $02)=$02
then
DispData[2]:=DispData[2] or DigVal;
EndIf;
If (ShowNum[Num] and $04)=$04
then
DispData[3]:=DispData[3] or DigVal;
EndIf;
If (ShowNum[Num] and $08)=$08
then
DispData[4]:=DispData[4] or DigVal;
EndIf;
If (ShowNum[Num] and $10)=$10
then
DispData[5]:=DispData[5] or DigVal;
EndIf;
If (ShowNum[Num] and $20)=$20
then
DispData[6]:=DispData[6] or DigVal;
EndIf;
If (ShowNum[Num] and $40)=$40
then
DispData[7]:=DispData[7] or DigVal;
EndIf;
If (ShowNum[Num] and $80)=$80
then
DispData[8]:=DispData[8] or DigVal;
EndIf;
End SetBits;
Procedure SetBits2(Num,Digit:Byte); // Zahl Num auf Stelle Digit
Var Counter : Integer; // 42s bis 50000
DigVal : Byte; // 32s bis 50000 mit Optimizer
CompVal : Byte;
Begin
DigVal:=$01 SHL (Digit-1);
CompVal:=$01;
For Counter:=1 to 8 do
If (ShowNum[Num] and CompVal)=CompVal
then
DispData[Counter]:=DispData[Counter] or DigVal;
EndIf;
CompVal:=CompVal SHL 1;
EndFor;
End SetBits2;
Procedure SetDigit(OutString:String[8]); // Digit v.l.n.r. 1-8
Var Counter : Byte;
StrHelp : String[1];
Begin
For Counter:=1 to 8 do
DispData[Counter]:=0;
EndFor;
For Counter:=1 to 8 do
StrHelp:=Copy(OutString,Counter,1);
Case StrHelp[1] of
'0':SetBits2( 0,Counter);|
'1':SetBits2( 1,Counter);|
'2':SetBits2( 2,Counter);|
'3':SetBits2( 3,Counter);|
'4':SetBits2( 4,Counter);|
'5':SetBits2( 5,Counter);|
'6':SetBits2( 6,Counter);|
'7':SetBits2( 7,Counter);|
'8':SetBits2( 8,Counter);|
'9':SetBits2( 9,Counter);|
'°':SetBits2(10,Counter);|
'´':SetBits2(11,Counter);|
'"':SetBits2(12,Counter);|
' ':SetBits2(13,Counter);|
EndCase;
EndFor;
End SetDigit;
Procedure SPIODB(Command,Data:Byte); // SPIOut Double Byte
Begin
PortB:=PortB and %11110111; // /CS
SPIOutByte1(Command);
SPIOutByte1(Data);
PortB:=PortB or %00001000;
End SPIODB;
Begin
InitPorts;
EnableInts;
Count2:=0;
// Init MAX7219
SPIODB(%00001100,%00000001); // Normal Operation
mDelay(10);
SPIODB(%00001111,%00000001); // Display Test on
mDelay(2000);
SPIODB(%00001111,%00000000); // Display Test off
mDelay(10);
SPIODB(%00001001,%00000000); // Decode Mode: none
mDelay(10);
SPIODB(%00001010,%00000111); // Intensity $07/$0F
mDelay(10);
SPIODB(%00001011,%00000111); // Scan Limit 8 Digits
mDelay(10);
// End Init MAX7219
Loop
SetDigit(LongToStr(Count2:8)); // Zahl --> String --> Display-Array
For Count1:=1 to 8 do // Displayausgabe via SPI
SPIODB(Count1,DispData[Count1]);
EndFor;
If Count2<99999999
then
Inc(Count2);
else
Count2:=0;
EndIf;
EndLoop;
End DTest.
Falls es jemand interessiert, was das soll: Ich habe mir einen Sack voll MAX7219 aus China bestellt (30 Stück für ca. 14€) und einen Sack voll Displays hatte ich schon. Dummerweise sind alle meine Displays mit gemeinsamer Anode, der MAX benötigt aber gemeinsame Kathode. Ich habe dann den Tip bekommen meine Segmente an die Digit-Anschlüsse des MAX und die Digit-Anschlüsse an die Segmentanschlüsse des MAX anzuschliessen. Dadurch ist aber ein Datenbyte nicht mehr eine Displaystelle, sondern jeweils die gleichen Bits der 8 Datenbytes sind für eine Stelle zuständig. In meinem Beispiel ist Bit0 Digit1, Bit1 Digit2, usw. Achso: Das Display ist momentan 8-stellig und soll letztendlich 32 Stellen (2 Zeilen je 16 Stellen) haben.