Sodale.
Der Code ist fertig und funktioniert(zumindest bei mir). Eigentlich sollte ich dafür Geld nehmen. *g*
Naja, Scherz beiseite. Mir war grad langweilig, da habe ich das Schnipselchen eben gehackt. Ich hasse Feiertage.
Ich schreibe mit E-LAB. Das ist Pascal-syntax. Die Version für den ATMega8 gibt’s auf der E-LAB webside kostenlos. Also falls du den Ehrgeiz entwickeln solltest, an dem Code selbst mal rumhacken zu wollen, steht dem nichts im Wege.
Hier das fertig kompilierte Projekt: http://thorservers.is-a-geek.com/Relaiskarte%20f%c3%…
Das hex-File liegt mit drin. Das Ei wird aber nicht ewig auf dem Server liegen. In einer Woche lösche ich das wieder.
Für’s Archiv hier das main.pas:
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
//
// Projekt : Relaiskarte für mollyman
// Erstellt am : 13.5.2010
// Erstellt durch : Alexander Schröder alias Thor
// Veröffentlicht : Wer-Weiss-Was.de-Forum am 13.5.2010
//
// Beschreibung:
// Snipet zum Fernsteuern von 8 Relais. Das Protokoll ist dem von
// Conradbausatz BstNr 197720 und 197730 nachempfunden. Entwickelt wurde es
// als Alternative für eben diese boards.
//
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
program Relaiskarte\_fuer\_mollyman;
Device = mega8, VCC=5;
Import SerPort;
From System Import ;
Define
ProcClock = 14745600; {Hertz}
StackSize = $0032, iData;
FrameSize = $0032, iData;
SerPort = 19200, Stop1; // 19,2kBaud und ein Stop bit
RxBuffer = 16, iData; // 16Byte Rx buffer sollte hier reichen
TxBuffer = 16, iData; // "
Implementation
{$PDATA}
var
// IFace
USARTLED [@PortB, 1] : bit; // die Rx Tx LED
USARTLED\_DDR [@DDRB, 1] : bit;
PWRLED [@PortB, 2] : bit; // Hach, immer diese Spielereien, diese Effekthascherei...
PWRLED\_DDR [@DDRB, 2] : bit; // Die Power LED
// Relais
R1 [@PortC, 0] : bit; // Relais 1
R1\_DDR [@DDRC, 0] : bit;
R2 [@PortC, 1] : bit; // ...
R2\_DDR [@DDRC, 1] : bit;
R3 [@PortC, 2] : bit;
R3\_DDR [@DDRC, 2] : bit;
R4 [@PortC, 3] : bit;
R4\_DDR [@DDRC, 3] : bit;
R5 [@PortC, 4] : bit;
R5\_DDR [@DDRC, 4] : bit;
R6 [@PortC, 5] : bit;
R6\_DDR [@DDRC, 5] : bit;
R7 [@PortD, 6] : bit;
R7\_DDR [@DDRD, 6] : bit;
R8 [@PortD, 7] : bit;
R8\_DDR [@DDRD, 7] : bit;
// USART
TX\_DDR [@DDRD, 1] : bit; // DDR für Tx
{$IDATA}
const
MaxUSARTTime: byte = 56; // Zeit bis das nächste Byte da sein muss als 56,25Hz/TimeOut
var
CycleEnable: boolean; // Für eine stabile Zeitbasis
USARTimeOut: byte; // USART TimeOut Zähler
Package: array[0..3] of byte; // Datenpacket buffer
Option: byte; // Optionen
PackageI: byte; // interner Zeiger
SelfAddr: byte; // Die eigene Adresse
USARTLEDCounter: byte;
CountingUp: boolean;
interrupt Timer0;
begin
CycleEnable:= true; // alle 18ms ausgeführt
end;
interrupt Timer1;
begin
if CountingUp then // up- und downconter für die Power LED
if OCR1B 0 then
dec(OCR1B);
else
CountingUp:= true;
endif;
endif;
end;
procedure InitSYS;
begin
USARTLED:= false; // Outputs klar machen
USARTLED\_DDR:= true;
PWRLED:= false;
PWRLED\_DDR:= true;
R1:= false;
R1\_DDR:= true;
R2:= false;
R2\_DDR:= true;
R3:= false;
R3\_DDR:= true;
R4:= false;
R4\_DDR:= true;
R5:= false;
R5\_DDR:= true;
R6:= false;
R6\_DDR:= true;
R7:= false;
R7\_DDR:= true;
R8:= false;
R8\_DDR:= true;
TX\_DDR:= true;
TCCR0:= %00000101; // 56,25Hz Aktualisierungsrate
TIMSK:= %00000001; // Timer1 Overflowinterrupt an
TCCR1A:= %00100010; // COM1B auf non-invertig
TCCR1B:= %00011101; // WGM Modus 14 und prescaler auf 1024
ICR1:= 150; // 96Hz PWM für die LED
OCR1B:= 0;
TIMSK:= TIMSK or 00000100; // interrupt zum faden an
CycleEnable:= false;
SelfAddr:= 0;
Option:= 1;
USARTimeOut:= 0;
Package[0]:= 0;
Package[1]:= 0;
Package[2]:= 0;
Package[3]:= 0;
PackageI:= 0;
USARTLEDCounter:= 0;
CountingUp:= true;
EnableInts;
end;
function ValidPackage: boolean;
begin
if (Package[0] xor Package[1] xor Package[2]) = Package[3] then
return(true);
endif;
return(false);
end;
procedure SendCMD(Command, Data: byte);
begin
USARTLEDCounter:= 10;
USARTLED:= true;
SerOut(Command);
SerOut(SelfAddr);
SerOut(Data);
SerOut(Command xor SelfAddr xor Data);
end;
function MyAddress: boolean;
begin
if (Package[1] = SelfAddr) or ((Package[1] = 0) and ((Option = 1) or (Option = 3))) then
return(true);
elsif (Package[0] = 1) then
return(true);
endif;
return(false);
end;
function GetPort: byte;
var
Port: byte;
begin
SetBit(Port, 0, R1);
SetBit(Port, 1, R2);
SetBit(Port, 2, R3);
SetBit(Port, 3, R4);
SetBit(Port, 4, R5);
SetBit(Port, 5, R6);
SetBit(Port, 6, R7);
SetBit(Port, 7, R8);
return(Port);
end;
procedure SetPort(Port: byte);
begin
R1:= Bit(Port, 0);
R2:= Bit(Port, 1);
R3:= Bit(Port, 2);
R4:= Bit(Port, 3);
R5:= Bit(Port, 4);
R6:= Bit(Port, 5);
R7:= Bit(Port, 6);
R8:= Bit(Port, 7);
end;
procedure SetSIngle(Port: byte);
begin
if Bit(Port, 0) then
R1:= true;
endif;
if Bit(Port, 1) then
R2:= true;
endif;
if Bit(Port, 2) then
R3:= true;
endif;
if Bit(Port, 3) then
R4:= true;
endif;
if Bit(Port, 4) then
R5:= true;
endif;
if Bit(Port, 5) then
R6:= true;
endif;
if Bit(Port, 6) then
R7:= true;
endif;
if Bit(Port, 7) then
R8:= true;
endif;
end;
procedure DelSingle(Port: byte);
begin
if Bit(Port, 0) then
R1:= false;
endif;
if Bit(Port, 1) then
R2:= false;
endif;
if Bit(Port, 2) then
R3:= false;
endif;
if Bit(Port, 3) then
R4:= false;
endif;
if Bit(Port, 4) then
R5:= false;
endif;
if Bit(Port, 5) then
R6:= false;
endif;
if Bit(Port, 6) then
R7:= false;
endif;
if Bit(Port, 7) then
R8:= false;
endif;
end;
procedure ToggleBit(Port: byte);
begin
if Bit(Port, 0) then
R1:= not R1;
endif;
if Bit(Port, 1) then
R2:= not R2;
endif;
if Bit(Port, 2) then
R3:= not R3;
endif;
if Bit(Port, 3) then
R4:= not R4;
endif;
if Bit(Port, 4) then
R5:= not R5;
endif;
if Bit(Port, 5) then
R6:= not R6;
endif;
if Bit(Port, 6) then
R7:= not R7;
endif;
if Bit(Port, 7) then
R8:= not R8;
endif;
end;
procedure ExecuteCommand; // PC Komandos verarbeiten und ausführen
var
Command, Address, Data: byte;
begin
Command:= Package[0];
Address:= Package[1];
Data:= Package[2];
if not ValidPackage then // Prüfen ob das Packet gut übergekommen ist
SendCMD(255, 42);
return;
endif;
if not MyAddress then // Prüfen ob man angesprochen wurde
return;
endif;
case Command of // Komandoliste durchswitchen
0: SendCMD(255, 42); | // NOP
1: SelfAddr:= Address;
SendCMD(254, 1); |
2: SendCMD(253, GetPort); | // Get Port
3: SetPort(Data); // Set Port
SendCMD(252, 42); |
4: SendCMD(251, Option); | // Optionen lesen
5: Option:= Data; // Optionen schreiben
SendCMD(250, 42); |
6: SetSingle(Data); // einzelne Bits an machen
SendCMD(249, GetPort); |
7: DelSingle(Data); // und wieder aus machen
SendCMD(248, GetPort); |
8: ToggleBit(Data); // oder umschalten
SendCMD(247, GetPort); |
endcase;
end;
begin
InitSYS;
loop
if CycleEnable then // synchronisieren auf den Systemtackt
CycleEnable:= false;
if USARTLEDCounter = 1 then // Rx Tx LED Controler
USARTLEDCounter:= 0;
USARTLED:= false;
elsif USARTLEDCounter \> 0 then
dec(USARTLEDCounter);
endif;
if USARTimeOut = 1 then // TimeOut erkennen und abfangen
USARTimeOut:= 0;
SendCMD(255, 42);
PackageI:= 0;
elsif USARTimeOut \> 0 then
dec(USARTimeOut);
endif;
while SerStat and (PackageI 3 then // und bei vollständigem Packet ausführen
PackageI:= 0;
USARTimeOut:= 0;
USARTLEDCounter:= 10;
USARTLED:= true;
ExecuteCommand;
endif;
endif;
endloop;
end Relaiskarte\_fuer\_mollyman.
Thor