Hallo liebe Freunde,
ich habe ein Impulsförmiges SENT Signal (Single Edge Nibble Transmission
Siehe Bild) zu analysieren und durch eine serielle Schnittstelle aufm
PC Messwerte anzuzeigen.
Das impulsförmige Signal enthält verschiedene Message, diese können
richtig oder falsch übertragen werden. Durch die Checksumme wird gegeben
ob ein Message korrekt übertragen wurde oder nicht.
(ein Nibble ist 4 Bit groß und fängt bei fallender Flanke an und endet
bei der nächsten fallenden Flanke also 0 und 1 Impuls)
Ein Message Enthält 9 Nibble (siehe Bild):
1- Synchronization (4 bit)
2- Status & Communication (4 bit)
3- Data 1 (4 bit)
4- Data 2 (4 bit)
5- Data 3 (4 bit)
6- Data 4 (4 bit)
7- Data 5 (4 bit)
8- Data 6 (4 bit)
9- Checksum (4 bit)
Zuerst muss der µC den Synchronisation Bereich finden, dass bei jeder
fallenden Flanke ein Interrupt ausgelöst wird und die Zeit zwischen zwei
fallenden Flanken misst und verglichen wird. Wenn der Synchronisation
Bereich gefunden ist, müssen dann die nächsten 8 Perioden (oder Nibble)
gespeichert werden, also nur 8 Werte müssen gespeichert. Mithilfe der
Cheksumme kann man sicherstellen, ob die Daten richtig übertragen wurden
oder nicht.
Das Problem jetzt:
Ich weiß ganz genau, dass mein Signal 5 Message enthält (kein reelles
Signal aber nur zum Testen), 4 richtige Message mit richtig berechneter
Checksumme und 1 falsches Message.
Das Signal sieht dann so aus:
Msg1Richtig_IFG_Msg2Richtig_IFG_Msg3Richtig_IFG_Msg4Falsch_IFG_MSG5Richt
ig_IFG_
IFG= Inter frame Gape
Dieses Signal wiederholt sich dann immer wie die o. g. Reihenfolge.
Der Code soll dann nur die 4 richtig übertragenen Message ausgeben,
d. h. es sollen die Dezimalwerte von jedem Nibble (insgesamt 8
Dezimalwerte) seriell ausgegeben.
und so muss es z. B. aussehen:
Msg1 5 6 7 8 3 1 4 5
Msg2 5 3 6 2 0 6 5 2
Msg3 7 9 0 2 3 7 8 8
Msg5 3 3 1 3 4 5 5 6
Diese Reihenfolge soll eigentlich wiederholt werden, wenn alles richtig
gemacht wird. Weil nur die 4 Message richtig sind.
Msg1 5 6 7 8 3 1 4 5
Msg2 5 3 6 2 0 6 5 2
Msg3 7 9 0 2 3 7 8 8
Msg5 3 3 1 3 4 5 5 6
Msg1 5 6 7 8 3 1 4 5
Msg2 5 3 6 2 0 6 5 2
Msg3 7 9 0 2 3 7 8 8
Msg5 3 3 1 3 4 5 5 6
Msg1 5 6 7 8 3 1 4 5
Msg2 5 3 6 2 0 6 5 2
Msg3 7 9 0 2 3 7 8 8
Msg5 3 3 1 3 4 5 5 6
Msg1 5 6 7 8 3 1 4 5
Msg2 5 3 6 2 0 6 5 2
Msg3 7 9 0 2 3 7 8 8
Msg5 3 3 1 3 4 5 5 6
usw..
Was mein Code ausgibt ist leider was anders :(
die Message-Werte werden bei mir in dieser Form ausgegeben:
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg3 7 9 0 2 3 7 8 8
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg5 3 3 1 3 4 5 5 6
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Msg1 5 6 7 8 3 1 4 5
Die Reihenfolge stimmt in meinem Code irgendwie nicht :(
und hier ist mein Code:
int x=0;
int i;
int n=0;
int checksum, checksum16;
int tempCs=0;
int clock_tick;
int perioden_dauer;
float const ticks= 0.0179; // 1/56
int nibble_anzahl=8;
int nibble_lengthinticks[8];
float messwerte_interrupt[8];
int druck [3];
int tepmeratur [3];
uint8_t messwerte_Druck [255];
uint8_t messwerte_Temperatur[255];
int messwerte_checksum;
float const zeit_in_us= 0.0167; // 0,0167= 1/60 (prescaler=1)
bool synchronisiert_b = false;
bool message_complete_b= false;
bool message_succeeded = false;
bool zaehler = false;
bool interrupt=false;
int sync_clk_tick =56;
int nibble_min;
int nibble_max;
int sync_min= 10080; // 168 �s
int sync_max = 12000; //200 �s
//int sync_max_1= 231;
int n_nibble = 0;
int Abweichung=10;
float nibble_in_tick;
uint8_t message[8]; //Werte in diesem Array reichen von 0 bis 15
int messwerte[8];
uint8_t value;
uint8_t value1;
****************************************
ISR (TCC0_OVF_vect)
{
if (interrupt)
{
TCC0.CNT=0 ;
}
}
****************************************
void zaehler_auswerten(void)
{
if (PORTC.PIN3CTRL==PORT_ISC_FALLING_gc)
{
perioden_dauer = TCC0.CNT;
TCC0.CNT= 0;
zaehler=true;
}
}
****************************************
ISR(PORTC_INT0_vect) // interrupt fuer I/O Port
{
cli();
zaehler_auswerten();
interrupt=true;
if (perioden_dauer >= sync_min && perioden_dauer <= sync_max) //
synchronization and Communication
{
synchronisiert_b = true;
clock_tick = perioden_dauer*ticks;
n_nibble = 0;
}
sei();
}
****************************************
void messwerte_vergleich(void)
{
if(synchronisiert_b && zaehler)
// synchronisiert ?
{
nibble_min=12*clock_tick;
nibble_max=27*clock_tick;
if((perioden_dauer >= nibble_min && perioden_dauer <= nibble_max))
// zeit entspricht einer nibble Periode ?
{
messwerte[n_nibble] = perioden_dauer;
n_nibble++;
zaehler=false;
}
if (n_nibble >= nibble_anzahl) //
ein message soll nicht laenger als 9 nibble sein
{
n_nibble = 0;
message_complete_b = true;
}
}
else
{
synchronisiert_b = false;
}
}
************************************************
void messwerte_auswerten(void)
{
int i;
for(i = 0; i< nibble_anzahl; i++)
{
message[i] = round ((messwerte[i]-nibble_min)/clock_tick); //
Nibblewert in dezimalzahlen zwischen 0..15 speichern
}
}
************************************************
int checksum_legacy()
{
checksum=5;
for (i=1;i<nibble_anzahl-1;i++)
{
tempCs=message[i]+(checksum*16);
checksum=CRC4legacy_table[tempCs];
}
// checksum with an extra "0" value
/*tempCs=checksum*16;
checksum=CRC4legacy_table[tempCs+1];*/
return checksum;
}
************************************************
int checksum_recomended()
{
checksum16=5;
for (i=1;i<nibble_anzahl-1;i++)
{
//checksum16= bitxor((message[i]),(CRC4Recom_table(checksum16+1)));
checksum16= (message[i])^(CRC4Recom_table[checksum16]);
}
checksum16= 0 ^ CRC4Recom_table[checksum16];
return checksum16;
}
//**********************************************************************
************************************************************************
************
/* output value when system is idle */
void SetIdleValue(void)
{
if(Port == SER_PORT_AO0)
{
/* set AO0 */
DACB.CH0DATA = IdleValue & 0x0FFF; // limit output to 4095
}
else
{
int Port_bm;
if(Port == SER_PORT_DO0)
{
Port_bm = PIN2_bm;
}
else
{
Port_bm = PIN3_bm;
}
if(IdleValue == 0)
{
PORTA.OUTCLR = Port_bm;
}
else
{
PORTA.OUTSET = Port_bm;
}
}
}
int main (void)
{
sei();
/* set system clock -> also change F_CPU definition in SENT2SERIAL.h!
*/
funct_clock_init_PLL_60M(); // clock initialization 60
MHz
funct_DACB_single0_enable(DAC_REFSEL_AVCC_gc); // initialize DAC
with internal Vcc OR
uart_InitUsartDriver(); // initialize RS232
communication
IdleValue = DEFAULT_IDLE_VAL; // analog output -> 5 V
(max.: 0x0FFF, 12 bit)
Port = SER_PORT_AO0; // set analog output as idle
port
errorOut = true; // turn off error messages
by default
debugOut = true; // turn off debug messages by
default
if (debugOut)
{
uart_send_string(version);
// send version number via RS232
uart_send_string("\nSignalgenerator laeuft\n");
}
uart_send_string("\nSignalgenerator wurde initialisiert\n");
func_glob_interrupt();
funct_timer0_init();
uart_send_string("\nENDE INITIALISIERUNGEN\n");
/* main loop */
while(1)
{
uart_StateMachine();
if(synchronisiert_b && zaehler)
{
//uart_send_string("\nSignalgenerator Synchronisiert\n");
messwerte_vergleich();
if(message_complete_b)
{
zaehler=false;
messwerte_auswerten();
checksum_recomended();
//uart_send_string("\n message_complete\n");
//uart_send_data(message,8);
if(checksum16==message[8])
{
//uart_send_string("\nMESSAGES Succeeded ON:\n");
uart_send_string("\n-");
uart_send_data(message,8);
}else
{
//uart_send_string("\nERROR Message ON:\n");
//uart_send_data(message, 8);
}
}
}
}
return 0;
}
Es könnte vielleicht sein dass während der µC die Messwerte speichert
und ausgibt, werden schon die nächsten Message verpasst.
Oder vielleicht haben die Datentyp einen Einfluss auf den Code, ich
meine jetzt mit float, integer, unint8, unint16 usw. ...
Es muss auch sicher gestellt werden, dass das gespeicherte Message
direkt ausgegeben wird.
Hat jemand vielleicht eine Idee wie man den Code korrigiert, ich stehe
seit eine Woche aufm Schlauch und komme nicht voran.
Anbei findet ihr den Code im Text Datei.
Danke euch im Voraus
Hat jemand vielleicht eine Idee !!
SENT ist ziemlich exotisch. Ich konnte noch keine Bauteile finden die ich wirklich auch kaufen könnte, wobei die Suche auch durch den Namen behindert wird. Woher kommt überhaupt das Signal und warum bist Du so sicher, dass es genau so kodiert ist wie Du es beschreibst?
Hallo, Sent ist sehr zeitkritisch. Ich würde dabei keine Subroutine verwenden um den Pin zu pollen sondern in einer interrupt-Routine die Zeitstempel der CCP-Unit in einen Ringpuffer schreiben und dann im Hauptprogramm auswerten. Die Synchronisation ist kein "Nibble" sondern die Zeitbasis mit der der Sender Sendet. Sent hat auf der Senderseite sehr große Toleranzen. Der Empfänger muß aus der Synchronisation die tatsächliche tick-Breite bestimmen und auch bei den empfangenen Nibbles "verrechnen" Gruß Anja
Rudolph R. schrieb: > SENT ist ziemlich exotisch. > Ich konnte noch keine Bauteile finden die ich wirklich auch kaufen > könnte, wobei die Suche auch durch den Namen behindert wird. > > Woher kommt überhaupt das Signal und warum bist Du so sicher, dass es > genau so kodiert ist wie Du es beschreibst? Hallo Rudolph, das Signal kommt eigentlich von einem SENT Druck und Temperatur Sensor. Da ich kein Sensor verfüge, habe ich selber ein SENT Signal nachprogrammiert, klingt komisch aber es war nur zum testen. Wenn es so richtig funktioniert dann sollte auch beim SENT Sensor auch funktionieren.
Anja schrieb: Danke Anja für deine Antwort, > Ich würde dabei keine Subroutine verwenden um den Pin zu pollen > sondern in einer interrupt-Routine die Zeitstempel der CCP-Unit in einen Ringpuffer schreiben und dann im Hauptprogramm auswerten. Ich habe leider nicht so gut verstanden was du genau meinst, kannst du bitte bezüglich meinem Code konkreter erklären !! > Die Synchronisation ist kein "Nibble" sondern die Zeitbasis mit der der > Sender Sendet. Sent hat auf der Senderseite sehr große Toleranzen. Der > Empfänger muß aus der Synchronisation die tatsächliche tick-Breite > bestimmen und auch bei den empfangenen Nibbles "verrechnen" > > Gruß Anja genau die Synchronisation wird auch nicht am PC angezeigt, dadurch wird nur die Tick Länge ausgerechnet und für die weiteren "Nibble" benutzt. Daher ist auch die Tick Länge keine konstante sonder sie variiert zwischen 3 µs und 90 µs.
Hat jemand noch vielleicht eine Idee ??
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.

