Hallo, alle miteinander. Ich versuche, kontinuierlich Daten von meinem
XMC4500 Relax Kit via UDP an meinen PC zu senden. Der Sendevorgang
findet in der Interrupt-Service-Routine eines Timers statt. Ich benutze
Dave V4 und die ETH_lwIP App. Ich brauche eure Hilfe, weil der
Übertragungsprozess nicht funktioniert. Mein Quellcode:
#include <DAVE.h> //Declarations from DAVE Code Generation
(includes SFR declaration)
#define TRANSMIT_PORT_DESTINATION (45175)
#define LOCAL_PORT_TRANSMIT (45174)
int main(void)
{
DAVE_Init(); // Initialization of DAVE Apps
//Start the lwIP stack
ETH_LWIP_STATUS_t init_status;
init_status = ETH_LWIP_Init(Ð_LWIP_0);
while(1)
{
/*Function called below, checks for timeout of different protocol
timers and
executes relevant handler functions
*/
sys_check_timeouts();
}
}
void UserIRQHandler(void)
{
ip_addr_t ip_computer;
IP4_ADDR(&ip_computer,192,168,0,40);
struct udp_pcb *pcb_tr;
pcb_tr = udp_new();
udp_bind(pcb_tr,IP4_ADDR_ANY,LOCAL_PORT_TRANSMIT);
char msg1[]="testingUDPtransmit";
struct pbuf *ppp;
ppp = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg1),PBUF_RAM);
memcpy (ppp->payload, msg1, sizeof(msg1));
udp_sendto(pcb_tr,ppp,&ip_computer,TRANSMIT_PORT_DESTINATION);
pbuf_free(ppp);
}
Hallo,
was funktioniert denn nicht?
Ein paar Punkte die mir auffallen ...
1.sollte man das nicht innerhalb einer ISR versenden
2.dein Socket solltest du am Ende schließen, oder besser noch in der
Main nur 1 Mal anlegen und für alle Vorgänge nutzen
3.ein Bind brauchst du nur wenn du auch empfangen willst, und auch hier
kannst du ein Bind auf einen Port nur 1x ausführen, ohne das Socket
freizugeben wird jedes weitere Bind auf den selben Port zu einem Fehler
führen
Sascha
Vielen Dank schonmal für die Antwort. Ein paar deiner Vorschläge habe
ich jetzt berücksichtigt und die UDP Pakete werden bei jedem Aufruf der
ISR versendet. Welche Möglichkeit besteht denn, abgesehen von einer ISR,
Daten im Sekundentakt per UDP zu versenden?
Für weitere Anmerkungen und Verbesserungsvorschläge bin ich sehr
dankbar, da ich zum ersten mal mit UDP arbeite. Mein aktueller,
angepasster Quellcode:
#include <DAVE.h> //Declarations from DAVE Code Generation
(includes SFR declaration)
#define TRANSMIT_PORT_DESTINATION (45175)
struct udp_pcb *pcb_tr;
char msg1[]="testingUDPtransmit";
struct pbuf *ppp;
ip_addr_t ip_computer;
int main(void)
{
DAVE_Init(); // Initialization of DAVE Apps
//Start the lwIP stack
ETH_LWIP_STATUS_t init_status;
init_status = ETH_LWIP_Init(Ð_LWIP_0);
pcb_tr = udp_new();
IP4_ADDR(&ip_computer,192,168,0,40);
while(1)
{
/*Function called below, checks for timeout of different protocol
timers and
executes relevant handler functions
*/
sys_check_timeouts();
}
}
void UserIRQHandler(void)
{
ppp = pbuf_alloc(PBUF_TRANSPORT,sizeof(msg1),PBUF_RAM);
memcpy (ppp->payload, msg1, sizeof(msg1));
udp_sendto(pcb_tr,ppp,&ip_computer,TRANSMIT_PORT_DESTINATION);
pbuf_free(ppp);
}
Wilhelm R. schrieb:> Vielen Dank schonmal für die Antwort. Ein paar deiner Vorschläge habe> ich jetzt berücksichtigt und die UDP Pakete werden bei jedem Aufruf der> ISR versendet.
das sieht ja schon mal gut aus
> Welche Möglichkeit besteht denn, abgesehen von einer ISR,> Daten im Sekundentakt per UDP zu versenden?
in dem du in der ISR nur ein Flag setzt und dieses in der Main-loop
abfragst.
Es geht ja primär darum die Bearbeitungsdauer der ISR auf das
notwendigste zu begrenzen. Auch wenn das vielleicht jetzt bei einem
Aufruf pro Sekunde kein Problem zu sein scheint, so kann das je nach
Architektur des Controllers in Verbindung mit anderen zeitkritischen
ISRs zu Problemen führen.
Beim AVR z.B. unterbrechen sich ISRs (wenn man es nicht erzwingt) nicht
gegenseitig. Wenn nun die eine ISR ein Mal pro Sekunde10ms dauert eine
zweite jedoch jede Millisekunde einen Zähler erhöhen soll "verliert"
diese wenigstens 9 Aufrufe pro Sekunde.
> Für weitere Anmerkungen und Verbesserungsvorschläge bin ich sehr> dankbar, da ich zum ersten mal mit UDP arbeite.
Auch den Puffer brauchst du nur 1x mit der größt möglichen Länge der
Nachricht anzulegen.
Das hat aber alles nichts speziell mit dem versenden von UDP-Paketen zu
tun.
Sascha
Wilhelm R. schrieb:> Welche Möglichkeit besteht denn, abgesehen von einer ISR,> Daten im Sekundentakt per UDP zu versenden?
Arbeitest Du mit einem RTOS? Die übliche Vorgehensweise dort ist, eine
Sendetask suspendiert zu halten und periodisch aufzuwecken (Stichtwort
Signal oder Event, oft durch Semaphoren realisiert). Der Timer ISR setzt
das Signal, womit das RTOS die Task aufweckt.
Eine andere sehr typische (ähnliche, aber nicht identische)
Implementationsweise ist über eine Message Pump - dort würden nicht nur
Signale des Timer ISR, sondern auch andere events abgearbeitet werden.
Man kann Netzwerksoftware ohne RTOS benutzen (lwip ist sogar explizit
dafür vorgesehen), aber typischerweise macht ein System mehr als nur
über das Netzwerk zu kommunizieren. In solchen Fällen macht ein RTOS
sehr schnell Sinn.
Wie schon vorher gesagt ist das Aufrufen von Netzwerkfunktionen im ISR
in aller Regel ein absolutes No-no - u.A. deshalb, weil Funktionen wie
udp_sendto in der Regel so realisiert sind, dass sie in verschiedenen
Szenarien den Aufrufer suspendieren können, und das ist in ISRs nicht
möglich, Punkt.
Ruediger A. schrieb:> Arbeitest Du mit einem RTOS? Die übliche Vorgehensweise dort ist, eine> Sendetask suspendiert zu halten und periodisch aufzuwecken (Stichtwort> Signal oder Event, oft durch Semaphoren realisiert). Der Timer ISR setzt> das Signal, womit das RTOS die Task aufweckt.>
Ich arbeitet nicht mit einem RTOS. Die Aufgabe meines Mikrocontrollers
soll darin bestehen Messwerte mit Hilfe einer FFT zu analysieren und die
berechneten Werte anschließend per UDP an MATLAB (R2016b) zu senden.
MATLAB ist vorerst nur zur grafischen Auswertung dieser Daten zuständig.
Eine eigene Frage?
Dieser Thread ist über 8 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.