2010-09-01 15 views
3

J'ai quelques problèmes en essayant de comprendre la communication asynchrone sur un objet serialport et j'espérais obtenir de l'aide. Je suis encore à apprendre des choses Async alors soyez gentil :)  SerialPort.BaseStream.BeginWrite & Questions BeginRead

 

j'ai besoin essentiellement de faire en sorte que la mémoire tampon ne soit pas pleine avant d'écrire sur le port série et aussi toutes les données ont été lues avant plus de données sont écrites pour éviter la collision de paquets. Malheureusement, le microcontrôleur sur lequel j'écris n'a pas de handshaking ou de CTSEnabled, donc je dois le copier dans le code  .  

 

 

public partial class Form2 : Form 
{ 
    System.IO.Ports.SerialPort port = new System.IO.Ports.SerialPort(); 
    System.Timers.Timer tmrPolling = new System.Timers.Timer(200); 
    static byte [] inputPacket = new byte[2] { (byte)255, (byte)0 }; // Byte to send to SerialPort when input polling timer is activated. 

    AsyncCallback callback; 
    IAsyncResult result; 

    Form2() 
    { 
     InitializeComponent(); 
     port.PortName = "COM9"; 
     port.BaudRate = 38400; 
     port.DataBits = 8; 
     port.StopBits = System.IO.Ports.StopBits.One; 
     port.Parity = System.IO.Ports.Parity.None; 
     port.ReadTimeout = 1; 
     port.ReceivedBytesThreshold = 5; 
     port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived); 
     callback = new AsyncCallback(ReadComplete); 
     port.ReadBufferSize = (byte)60; 
     port.WriteBufferSize = (byte)60; 
     port.Open(); 
     tmrPolling.Elapsed += new System.Timers.ElapsedEventHandler(tmrPolling_Elapsed); 
    } 

    void WritePacket(byte[] packet) 
    { 
     result = port.BaseStream.BeginWrite(packet, 0, packet.Count(), callback, port); // writes the input packet to the SerialPort - needed to read the IO values 
    } 

    void ReadComplete(IAsyncResult result) 
    { 

    } 


    void tmrPolling_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     WritePacket(inputPacket); // writes the input packet to the SerialPort - needed to read the IO values 
    } 

    void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) 
    { 
     port.BaseStream.EndWrite(result); 
     // Reads the data coming in from the serial port and calls the thread safe delegate to update the values on the form. 
     byte [] received = new byte[port.BytesToRead]; 
     result = port.BaseStream.BeginRead(received, 0, received.Count(), callback, port); 
     port.BaseStream.EndRead(result); 
    } 

    private void UpdateValues() 
    { 
     byte[] b = new byte[] { (byte)255, (byte)6, (byte)hsbPan.Value, (byte)vsbTilt.Value, (byte)0, 
     (byte)0, (byte)0, (byte)0, (byte)13, (byte)10 }; 
     WritePacket(b); 
    } 

    private void chkEnablePolling_CheckedChanged(object sender, EventArgs e) 
    { 
     tmrPolling.Enabled = chkEnablePolling.Checked; 
     test.Enabled = chkEnablePolling.Checked; 
     vsbInputInterval.Enabled = chkEnablePolling.Checked; 
     vsbInputInterval.Value = Convert.ToInt32(tmrPolling.Interval); 
     txtInputInterval.Enabled = chkEnablePolling.Checked; 
     txtInputInterval.Text = ((float)tmrPolling.Interval/(float)1000).ToString() + " sec"; 
    } 

    private void vsbInputInterval_Scroll(object sender, ScrollEventArgs e) 
    { 
     // adjusts the tick frequency of the Timer for input polling. 
     txtInputInterval.Text = ((float)tmrPolling.Interval/(float)1000).ToString() + " sec"; 
     tmrPolling.Interval = vsbInputInterval.Value; 
    } 

    private void vsbTilt_Scroll(object sender, ScrollEventArgs e) 
    { 
     UpdateValues(); 
    } 

    private void hsbPan_Scroll(object sender, ScrollEventArgs e) 
    { 
     UpdateValues(); 
    } 
} 
+0

Peut-être que l'utilisation d'un modèle de conception producteur-consommateur serait utile? Voir http://stackoverflow.com/questions/1656404/c-sharp-producer-consumer – Roger

Répondre

-1

Je suis un peu en retard, mais je tente quand même :)

J'ai besoin essentiellement de faire en sorte que la mémoire tampon ne soit pas pleine avant à l'écriture sur le port série également toutes les données ont été lues avant que d'autres données soient écrites pour éviter la collision de paquets

vous pouvez vérifier s'il y a des données encore dans le tampon avec le drapeau:

if(port.BytesToRead > 0){ // do something} 
if(port.BytesToWrite > 0){ // do something} 

si vous voulez effacer l'en compétition ou hors tampon, vous pouvez utiliser:

port.DiscardInBuffer(); // for the In-Buffer 
port.DiscardOutBuffer(); // for the Out-Buffer 

si fondamentalement, vous l'utiliseriez dans votre méthode WritePacket. Pour imiter un comportement de prise de contact, j'aurais besoin d'un peu plus d'informations sur le périphérique à portée de main.

+0

Voulez-vous commenter le downvote? anonyme? –