Hi zusammen, Ich bin neuling auf dem gebiet und mache es aus spaß und Hobby. Bitte entschuldigt für mein Missverständiss in verschiedenen sachen. ich bin grade dabei mit einem PIC 18F45k20 (PICKIT 3 Starterkit) eine Wetterstation zu basteln. Mein PIC soll eine umsetzung von I2c auf seriell tun da die Sensormodule die ich benutze möchte I2c sind. Zum Ablauf: Per button soll eine anfrage an den Pic für die Module gesendetwerden damit ich die beötigten Daten bekomme. Ich habe die oberfläche soweit fertig und bin an der Seriellen Kommunikation dran. Über die Oberfläche sende ich als test einen Character den der Pic auch richtig empfängt. Den empfang gebe ich aus in dem ich Die LED´s auf dem Demoboard in der codierung anzeigen lasse. Nun sendet der pic die Daten auch zurück aber nicht 1 Zeichen sondern mehrere. ich möchte aber nur das eine zeichen was ich gesendet habe auch wiedergegben haben. C# Programm: public partial class MainWindow : Window { //********************************************************************** ** //================================VARIABLEN============================= == //********************************************************************** ** SerialPort mySerial; //Variable von Klasser SerialPort Thread rxThread; string message; //Empfangs Message //********************************************************************** ** //==================================MAIN================================ == //********************************************************************** ** public MainWindow() { InitializeComponent(); mySerial = new SerialPort(); } //********************************************************************** ** //=========================SERIAL ONFIGURATION=========================== //********************************************************************** ** public void serialConfig() { mySerial.PortName = "COM3"; mySerial.BaudRate = 9600; mySerial.DataBits = 8; mySerial.StopBits = StopBits.One; mySerial.Parity = Parity.None; mySerial.ReceivedBytesThreshold = 1; mySerial.ReadBufferSize = 64; mySerial.WriteBufferSize = 64; } //********************************************************************** * //==================================BUTTONS============================= == //********************************************************************** ** private void btn_temp_Click(object sender, RoutedEventArgs e) { anzeigenSchliesen(); // Alte Anzeigen schliesen anzeige_temp.Visibility = Visibility.Visible; // Anzeige für temperatur Anzeigen serialConfig(); mySerial.Open(); mySerial.Write("a"); Thread.Sleep(100); //Kein sleep = undifiniertes symbol wird mit gesendet message = Convert.ToString(mySerial.Read()); tb_temp.Text = message; // Ausgabe der empfangenen Daten in der Textbox mySerial.Close(); anzeige_temp.Minimum = -120; // min Wert der Temp Anzeige anzeige_temp.Maximum = 120; // Max Wert der Temp Anzeige } PIC Programm: /* * File: RxTxMain.c * Author: floryd * * Created on 7. August 2014, 12:34 */ #include <xc.h> #include <pic18f45k20.h> #include <stdio.h> #include <stdlib.h> #include "C:\Program Files (x86)\Microchip\xc8\v1.32\include\plib\usart.h" #include "C:\Program Files (x86)\Microchip\xc8\v1.32\include\plib\delays.h" /*========================================================= * PIC CONFIGURATION *=========================================================*/ #pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF // CONFIG1H #pragma config PWRT = ON, BOREN = SBORDIS, BORV = 30 // CONFIG2L #pragma config WDTEN = OFF, WDTPS = 32768 // CONFIG2H #pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC // CONFIG3H #pragma config STVREN = ON, LVP = OFF, XINST = OFF // CONFIG4L #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // CONFIG5L #pragma config CPB = OFF, CPD = OFF // CONFIG5H #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // CONFIG6L #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF // CONFIG6H #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // CONFIG7L #pragma config EBTRB = OFF // CONFIG7H void SetupClock(); // Taktfrequenz interner OSci void BootLoad(); // Anzeige das das Programm gestartet ist. (LED einmal durchlaufen) void uartOpen();// Configuration des UART Laden /* * */ unsigned int i = 0; unsigned int j = 0; unsigned char empfang; int main(int argc, char** argv) { SetupClock(); TRISD = 0x00; // LEDs OUTPUT BootLoad(); RXLOOP: uartOpen(); while(!DataRdyUSART()){ Delay10KTCYx(2); empfang = ReadUSART(); Delay10KTCYx(2); LATD = empfang; // empfangene Datei ausgeben mit leuchtend er LED Delay10KTCYx(3); WriteUSART(empfang); // zurück senden der empfangenen Datein } CloseUSART(); goto RXLOOP; return (EXIT_SUCCESS); } //Clock Speed void SetupClock(){ asm("BANKSEL OSCCON"); asm("MOVLW 0x60"); asm("MOVWF OSCCON"); } // The PIC is Starting void BootLoad(){ for(i;i<=255;i++){ Delay10TCYx(200); LATD = i; } //LED Blinken lassen wenn test durchlauf Finished if(LATD == 0xFF){ for(i=0;i<5;i++){ LATD = 0xFF; Delay10KTCYx(50); // 0,25s (250ms) LATD = 0x00; Delay10KTCYx(50); } } } // UART Confuguration void uartOpen(){ OpenUSART(USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_TX_INT_OFF & USART_RX_INT_OFF & USART_BRGH_HIGH,51); } Danke Im Vorraus Mit freundlchen Grüßen -Tim-
1 | message = Convert.ToString(mySerial.Read()); |
Wie schaffst du das denn? Die SerialPort-Klasse aus dem .NET-Framework hat gar kein parameterloses .Read()? Ich würde noch den Zeichensatz setzen (via mySerial.Encoding)
Tim Halbach schrieb: > mySerial.Write("a"); > Thread.Sleep(100); //Kein sleep = undifiniertes symbol wird > mit gesendet warum sollte ohne Sleep etwas undefiniertes gesendet werden. Eventuell hast du ja noch irgendwelche Hardware Probleme. .Net sendet zumindest nur das was man senden will.
hi danke für dei schnellen antworten, ja das mit dem Read habe ich mich vertan habe ReadLine() reingeschreiben mit dem entcoding werd ich mal Probieren. Undifiniertes Senden: Ich sehe das noch andere sachen gesendet werden da die LED´s wie verrückt blinken. sobald ich das slepp einfüge funktioniert es ohne probleme. habe gelesen das bei einem string ein line feed oder carriage return (\n,\r) gesendet wird. leider kann ich das nicht kontrollieren ob das der fall ist. das andere ist ich weis nicht wie man in c (beim Pic) einen carragie return rausfiltert. villt liegt es auch daran das der buffer überläuft da gesendete daten noch nciht ganz raus sind. habe auch mit .DiscardOutBuffer versucht es zu beheben. irgendwie sendet er aber dann trozdem ncoh blödsin mit.
SerialPort.Write("xyz") sendet nur "xyz" ohne CR/LF. SerialPort.WriteLine("xyz") würde (auf Windows-Maschinen) "xyz\r\n" senden. D.h. wenn du aktuell vom PC aus nur "a" sendest und der PIC alles was reinkommt 1:1 zurückschickt, müsste deine Anwendung bei .ReadLine() eigentlich blockieren, da es unendlich lange auf ein "\r\n" wartet (da kein Timeout gesetzt wurde) Ich würde zunächst mal prüfen, was denn tatsächlich rausgesandt wird und den PIC erstmal außen vor lassen. z.B. COM3 mit anderem freien COM-Port passend verbinden und mit putty o.ä. schauen was tatsächlich aus COM3 raus kommt. Oder z.B. via com0com virtuelle COM-Ports passend verbinden (signierter Treiber ist hier zu finden: https://code.google.com/p/powersdr-iq/downloads/list)
danke das mit dem Readline() wusste ich nicht das es auf ein CR und LF wartet. Getestet habe ich schon wie folgt: FTDI Kablel RX mit einer Büroklammer an TX angeschlossen, dann Putty geöffnet. Es Funktioniert und kommt auch richtig an.
Tim Halbach schrieb: > danke das mit dem Readline() wusste ich nicht das es auf ein CR und LF > wartet. was soll denn sonst bei ReadLine passieren? woher soll er wissen das die Line zu ende ist?
als du es sagtest war es mir klar. Weil bei Console.WriteLine(); macht er auch eine neue zeile. die übertragung stimmt jetzt ich bekomme das zeichen was ich haben wollte allerdings immer noch so 8 mal. kann das villt daran liegen das beim PIC erstabgeschickt wird wenn der buffer gefüllt ist? müsste das mit einem timer gelöst werden? Wenn ja. wie berechne ich die Zeit das der pic es genau zum richtigen zeitpunkt verschickt.
Ich habe euch mal einen screenshot gemacht wie es aussieht und wie die rückgabe aussieht. Wie man auf dem bild erkennt bekomme ich den wert a richtig zurückgegeben allerdings 3 mal anstatt nur einmal wie ich ihn gesendet habe. und da komme ich nciht weiter DIe kommunikation funktioniert. kann senden und auch empfangen allerdings bekomme ich nciht die richtige anzahl wieder. danke im voraus
Bin kein Pic'ler aber das sieht mir ein wenig seltsam aus. Sicher das diese Zeile ( in rxloop ) so richtig ist ? while(!DataRdyUSART()) (MPLAB® C18 C Compiler Libraries) DataRdyUSART Return Value: 1 if data is available 0 if data is not available Wenn ich das Übersetze würde doch "wenn NICHT DataRdyUSART() == 1 " herauskommen ? Hoffe das ich gerade keinen Knoten im Kopf habe.
das ständige öffnen und schließen vom com-port in C# ist Unsinn. Das macht man einfach nicht. Auch wartest du nicht bis alle Daten empfangen wurden, du liest einfach alles was das ist (ReadExisting) und hoffst das alles das ist. Das garantiert dir aber niemand.
Wie Kontrolier ich das den? es sollte doch alles da sein ich brauche zum senden von einem byte 104µs ink startund stop bit (1s /9600baudrate * 10bit 1 startbit 1 stopbit 8 datenbits). wenn der Buffer mit 64 definiert ist habe ich 104µs * 64 = 6656 µs also 6,6ms. selbst wen der pic dann ncoh mal 1 ms pro byte schieben ins TXREG brauch sind es 70,6 ms ich habe bei mir eine thread sleep von 100ms bis er den empfang abfragen sollte. Da gehe ich mal aus das alles da sein sollte. Aber wie mache ich den dann eine abfrage ob alle daten empfangen sind? Beim Pic frage cih das einfach mit dem Flag bit ab TXIF nur bei C# keine ahnung. Das ander ist das von dem 64 Buffersize ja nur das 1byte gefüllt sein dürfte, da dies das zeichen ist was ich zurücksende und die anderen sollten 0 sein und nicht auch a.
Tim schrieb: > Beim Pic frage cih das einfach mit dem Flag bit ab TXIF nur bei C# keine > ahnung. TXIF=1 sagt doch nur, dass der Transmit-Buffer leer ist und das nächste Byte zum Versand in den Buffer geschrieben werden kann? Dass das Byte auch von der Gegenstelle empfangen wurde kann man daraus nicht direkt schließen. In C# ist TXIF nicht nötig. Das System wird alle Bytes raussenden oder bei .Write* eine Exception werfen. >Getestet habe ich schon wie folgt: >FTDI Kablel RX mit einer Büroklammer an TX angeschlossen, dann Putty >geöffnet. Damit die C#-Anwendung getestet oder die Kommunikation mit dem PIC?
Tim schrieb: > Wie Kontrolier ich das den? in dem du eine Endezeichen festlegst. Und die Liest so lange bis das ende erreicht ist. Für ASCII Übertragung bietet sich ein \r[\n] an, dann kannst du auch wieder ReadLine verwenden. Du kannst auch ein \0 als ende Festlegen und dann liest du einfach ein einer schleife bis eine \0 kommt. Dann muss man auch nicht irgendwie mit Sleep arbeiten, was früher oder später schief geht. RS232 kann selber nie ein ende feststellen.
Tim schrieb: > Wie Kontrolier ich das den? In dem man ein bestimmtes Protokoll definiert, das beide Gegenstellen nutzen. Im einfachsten Fall kann z.B. ein '\n'-Zeichen bedeuten, dass ein Befehl/Paket abgeschlossen ist. Die Buffersize von 64 sagt nur, dass die SerialPort-Klasse nur 64 Bytes zum Puffern nutzen soll. Der Treiber selbst kann aber auch noch Puffer besitzen. Und das ein "Paket" 64 Bytes groß ist sagt man damit auch nicht. D.h. ein .ReadExisting() liest keine 64 Bytes ein, sondern das was gerade schon im Empfangspuffer angekommen ist. Wenn der µC z.B. "HALLO\r\n" sendet und auf PC-Seite .ReadLine() aufgerufen wird, wartet .ReadLine() solange bis "\r\n" angekommen ist und liefert dann "HALLO" zurück. Man könnte z.B. damit anfangen auf dem µC in Schleife "HALLO\r\n" zu senden und dann z.B. via putty zu schauen, ob im Terminal lauter "HALLO" untereinander erscheinen. Anschließend kann man schauen, dass auch die C#-Anwendung lauter HALLO's empfängt.
bluppdidupp schrieb: > Damit die C#-Anwendung getestet oder die Kommunikation mit dem PIC? Die Kommunikation von der c# Anwendung. bluppdidupp schrieb: > TXIF=1 sagt doch nur, dass der Transmit-Buffer leer ist und das nächste > Byte zum Versand in den Buffer geschrieben werden kann? Damit hast du recht ich mache mir da einen Counter der zählt wie oft das TXIF bit gesetzt wurde. z.B. definier ich mir immer ein char da es genau 1 byte oder ein char ARRAY mit fest definierter index größe (char Zeichen[5]) und sage ihm wenn das TXIF bit gesetzt wurde der counter +1 wird und wenn er 5 erreicht hat soll er nicht mehr senden und nichts mehr in den TXREG schieben. Peter II schrieb: > Für ASCII Übertragung bietet sich ein \r[\n] an, dann > kannst du auch wieder ReadLine verwenden. Du kannst auch ein \0 als ende > Festlegen und dann liest du einfach ein einer schleife bis eine \0 > kommt. Vielen Danke Peter an sowas habe ich garnicht gedacht. Programmier noch nicht so lange aber es macht mir einen heiden spaß zu lernen und das verständinis dafür zu entwickeln. bluppdidupp schrieb: > Man könnte z.B. damit anfangen auf dem µC in Schleife "HALLO\r\n" z.B. so? int i= 0; char tx_Hallo[7] = {'H','a','l','l','o','\r','\n'}; for(i;i<=7;i++){ WriteUSART(Hallo[i]); Delay_ms(1); } bluppdidupp schrieb: > In dem man ein bestimmtes Protokoll definiert So ein Protokoll?! schreib ich das in eine separate Funktion? Könntest du mir villt. erklären wie man sowas aufbaut und worauf man achten muss. BITTE aber keinen fertigen code maximal Pseudocode. Danke allen für ihre gedult
Tim Halbach schrieb: > z.B. so? Jo das sieht doch gut aus, noch ein while(true) drum herum und dann mal schauen, was am PC (z.B. in putty o.ä.) ankommt. Wenn da HALLO nicht ordentlich ankommt, stimmt vermutlich was mit dem PIC-Code nicht und das "µC & Elektronik"-Forum wäre dafür wohl dann doch geeigneter als "PC-Programmierung". Wenn das HALLO sauber ankommt, könnte man dann mal schauen dass die C#-Anwendung das ebenfalls sauber einliest. Quasi eins nach dem andern ;D Wie das Protokoll konkret aussehen könnte, wird man vermutlich von der Anwendung abhängig machen. In deinem Fall, würde ich auf dem µC wohl sowas basteln:
1 | while(true) |
2 | { |
3 | cmd=readLineFromUART(); |
4 | if (cmd=="TEMPERATURE") |
5 | { |
6 | temperature_value=readTemperatureFromSensor(); |
7 | sendToUART("TEMPERATURE: "+temperature_value+"\r\n"); |
8 | } |
9 | else if (cmd=="HUMIDITY") |
10 | { |
11 | humidity_value=readHumidityFromSensor(); |
12 | sendToUART("HUMIDITY: "+humidity_value+"\r\n"); |
13 | } |
14 | else |
15 | { |
16 | // Unknown command |
17 | } |
18 | } |
(...oder evtl. auch gar nicht auf Befehle vom PC warten und die Sensorwerte einfach ununterbrochen nacheinander raussenden ;D)
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.