PDA

View Full Version : حرفه ای: پورت سریال و مشکل همزمانی



M.YasPro
دوشنبه 17 تیر 1392, 17:24 عصر
سلام
وقت بخیر
با یه دستگاه دارم کار می کنم که با پورت سریال تو سی شارپ بهش کانکت میشم
من باید یه آرایه از نوع بایت براش بفرستم تا اون یه جواب به من بده ، بعد با توجه به جوابی که داده یه دستور دیگه براش بفرستم تا جواب نهایی رو بگیرم(این کار باید بصورت متناوب مثلا در هر 30 ثانیه تکرار بشه) به اینصورت:
void timer_tick()
{
//send command1
}
void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (Flag)
{
//read data
return;
}
if (serialPort.ReadExisting().Length == 150)
{
//do code
//if return data is true send command2
//flag=true
//return
}
}
همیشه بار اول درست اطلاعات برگشتی از دستور اول و دوم درست هست و دستور اول رو هم هر بار درست میفرسته اما اطلاعات دستور دوم رو نمیتونه درست برگردونه و ارورهایی مثل port openو access denied و ..
میده، من فکر میکنم که به خاطر این هست که برنامه به دوتا نخ تبدیل میشه و ما هم دوتا دستور داریم و این باعث میشه که مثلا وقتی تیک تایمر اتفاق میفته همون لحظه پورت توسط ایونت دیتارسیو داره استفاده میشه و اطلاعات برگشتی مطلوب ما نیست
ممنون از توجهتون

hamid_hr
دوشنبه 17 تیر 1392, 17:32 عصر
پورت سريال به طور همزمان فقط توسط يك دستور بايد باز باشه اگه وقتي باز هست دوباره بخواي با ديتور ديگه بازش كني خطا ميده
بايد دقت كني اصلا همزمان دو جا بازش نكني
اگه مراحل ارسال و دريافت منظم هست همه رو داخل يك تابع پشت سر هم بنويس

M.YasPro
دوشنبه 17 تیر 1392, 20:07 عصر
ممنون از جوابت
من همزمان دو جا بازش نمی کنم
نمیشه همه رو پشت سر هم بنویسم چون تیک تایمر و ایونت دیتا رسیو جدا هستند و نمیشه مانع اجرا شدنشون بشم

M.YasPro
سه شنبه 18 تیر 1392, 08:51 صبح
استفاده از یه ترد دیگه میتونه این مشکل رو رفع کنه؟

hamid_hr
چهارشنبه 19 تیر 1392, 08:31 صبح
ببين
بايد فقط يك متغيير برا باز كردن پورت داشته باشي اونو سراسري تعريف كني بقيه بتونن استفاده كنن
منظورتو از يك ترد ديگه نميفهمم

بعدشم سوالتون گنگ هستش وگرنه بچه ها فعال هستن هنوز
كد هم كه نزاشتي كسي بررسي كنه
فقط يه جواب دادم من كه اونم رو حدس و گمان بود

M.YasPro
چهارشنبه 19 تیر 1392, 15:11 عصر
کد من اینه
private void timerSendCommand_Tick(object sender, EventArgs e)
{

serialPort1 = new System.IO.Ports.SerialPort(this.components);
this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(thi s.serialPort1_DataReceived);
this.serialPort1.Open();

CurrentVega = 1;
byte[] ch = new byte[] { 0x02, 0x30, 0x30, 0x31, 0x31, 0x30, 0x30, 0x30, 0x34, 0x35, 0x0D };

byte[] num = System.Text.ASCIIEncoding.ASCII.GetBytes(CurrentVe ga.ToString("D3"));
ch[1] = num[0];
ch[2] = num[1];
ch[3] = num[2];

byte[] chksm = Checksum(ch, 0, 8);
ch[8] = chksm[0];
ch[9] = chksm[1];

serialPort1.Write(ch, 0, ch.Length);
}

و
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{

if (flag)
{
if (serialPort1.BytesToRead > 242)
{
#region Command2
string buf1 = string.Empty;
buf1=serialPort1.ReadExisting();
//serialPort1.Close();
upd2 u2 = updateTable2;
Invoke(u2, buf1);

byte[] readstrt = new byte[8];
for (int i = 0; i < 8; i++)
readstrt[i] = (byte)buf1[108 + i];

byte[] readend = new byte[8];
for (int i = 0; i < 8; i++)
readend[i] = (byte)buf1[132 + i];

byte[] readwgt = new byte[11];
for (int i = 0; i < 11; i++)
readwgt[i] = (byte)buf1[156 + i];

data d = new data();
d.BatchNumber = LastTransaction;
d.Start = int.Parse(System.Text.ASCIIEncoding.ASCII.GetStrin g(readstrt));
d.End = int.Parse(System.Text.ASCIIEncoding.ASCII.GetStrin g(readend));
d.Deliver = int.Parse(System.Text.ASCIIEncoding.ASCII.GetStrin g(readwgt));
DataList.Add(d);

flag = false;
//serialPort1.Close();

if (serialPort1 != null)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
}
serialPort1.Dispose();
}

upd u = updateTable;
Invoke(u, DataList);

System.Threading.Thread.Sleep(new TimeSpan(0, 1, 0));
#endregion

}

return;
}
if (serialPort1.BytesToRead < 155){ i++; return; }
#region Command1
try
{
string buf = serialPort1.ReadExisting();
byte[] read = new byte[6];

for (int i = 0; i < 6; i++)
{
read[i] = (byte)buf[33 + i];
}


byte[] read1 = new byte[6];
int j = 0;
foreach (var item in read)
{
if (item == 0x20)
read1[j] = 0x30;
else
read1[j] = item;
j++;
}


LastTransaction = int.Parse(System.Text.ASCIIEncoding.ASCII.GetStrin g(read1));

byte[] b17b = new byte[17] { 0x02, 0x30, 0x30, 0x31, 0x31, 0x30, 0x31, 0x36,
read1[0] , read1[1], read1[2], read1[3],read1[4],read1[5], 0x0, 0x0, 0x0D};

byte[] num = System.Text.ASCIIEncoding.ASCII.GetBytes(CurrentVe ga.ToString("D3"));
b17b[1] = num[0];
b17b[2] = num[1];
b17b[3] = num[2];
byte[] ch = Checksum(b17b, 0, 14);
b17b[14] = ch[0];
b17b[15] = ch[1];


serialPort1.Write(b17b, 0, b17b.Length);
flag = true;
this.k++;
#endregion
}
catch
{ }
}

hamid_hr
چهارشنبه 19 تیر 1392, 15:50 عصر
serialPort1 = new System.IO.Ports.SerialPort(this.components);
this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(thi s.serialPort1_DataReceived);
this.serialPort1.Open();
اينا رو ببر خارج از تايمرت و تو لود فرمت اونو openكن
اينطوري كه نوشتي هر بار مياد پورت سريال و باز كنه ولي close نميكني

M.YasPro
چهارشنبه 19 تیر 1392, 23:49 عصر
اینکارو قبلا کرده بودم اما هر بار که میخواست جواب دستور دوم رو بخونه انگار اطلاعات ناقص خونده میشد

hamid_hr
پنج شنبه 20 تیر 1392, 08:31 صبح
من برا خوندن از پورت سريال اين كارو ميكنم
private void PortReader()
{
while (true)
{
string ret = spo.ReadLine();
listBox1.Items.Add(ret);
}
}
اين تابعو به صورت thread بعد از اينكه پورت باز شد اجرا ميكنم
فقط اول اطلاعات بفرست ببين دريافتي چطور انجام ميشه
اون serialport_recived رو غري فعال كن

M.YasPro
شنبه 22 تیر 1392, 09:56 صبح
این حلقه همیشه اجرا میشه؟
متوجه نشدم

hamid_hr
شنبه 22 تیر 1392, 09:59 صبح
اره
هميشه اجرا ميشه
تو خط readline ميمونه تا يه چيزي روي پورت سريال نوشته بشه

M.YasPro
شنبه 22 تیر 1392, 11:37 صبح
من خیلی دارم اذیتت می کنم ، معذرت
اما مسئله من اینه


دستور اول رو میفرستم
جواب دستور اول خونده میشه
یک رشته با استفاده از جواب برگشتی مرحله اول ساخته میشه
این رشته به عنوان دستور دوم به دستگاه فرستاده میشه
جواب دستور دوم خونده میشه
دوباره بعد از مثلا سی ثانیه همون دستور اول1 دوباره فرستاده میشه
جواب دستور اول خونده میشه
اگر با جواب دستور مرحله 1 فرق داشت :‌دستور دوم دوباره ساخته میشه و به دستگاه فرستاده میشه اگر با جواب دستور دوم فرق نداشت از ادامه اجرا تا سی ثانیه بعدی رف نظر می کنه
و بعد از سی ثانیه دوباره دستور اول ....

M.YasPro
یک شنبه 23 تیر 1392, 11:39 صبح
دوستان راهنمایی کنید لطفا

hamid_hr
یک شنبه 23 تیر 1392, 11:43 صبح
while (true)
{
spo.Write("")
string ret = spo.ReadLine();
//پردازشها
thread.sleep(30000);
}

M.YasPro
چهارشنبه 09 مرداد 1392, 11:15 صبح
مشکلم حل شد ممنون اشکال این بود که تو ایونت رسیو ، به همون پورت دیتا میفرستادم من دوبار دستور میفرستادم که دوبار رو توی تیک تایمر گذاشتم .