У меня есть счетчик монет (SC350/360), который подключается к компьютеру через интерфейс RS232C. У меня есть техническая документация, в которой описаны протоколы связи, а также включена работающая программа на Паскале для управления машиной. Я скопировал код Pascal и протестировал его на Turbo Pascal, используя DosBox, для Windows 7 64 бит, и код успешно компилируется. Чего я хотел добиться сейчас, так это преобразовать эти паскаль-коды в С#.Net, но мне было трудно преобразовать несколько строк в С#, так как у меня нет большого опыта в программировании последовательного порта.
Это был код на Паскале для инициализации связи с машиной. (Установите скорость передачи данных на 9600, 8 бит, без четности, 1 стоповый бит)
uses crt;
const
{ COM1: RS232 port address }
RXTX = $3F8; { $2F8 if COM2: is used }
ACK = 6;
NAK = 21;
ESC = 27;
var
dummy,
checkSum : integer;
key : char;
protocol : integer;
var i : integer;
begin
i := 1843200 div 9600 div 16;
port[RXTX + 3] := $80;
port[RXTX + 1] := hi(i);
port[RXTX]:= lo(i);
port[RXTX + 3] := 3;
port[RXTX + 4] := $A;
while odd(port[RXTX + 5]) do
begin
dummy := port[RXTX];
delay(10);
end;
end; { InitComm }
Соответствующий С# для приведенного выше кода, который я придумал, был; (Пожалуйста, поправьте меня, если я ошибаюсь)
SerialPort port=new SerialPort("COM1",9600,Parity.None,8,StopBits.One);
Но я не мог понять, как преобразовать остальные паскаль-процедуры. Некоторые из этих процедур, с которыми у меня были трудности:
procedure Tx(data : integer);
{ Transmit a character on serial channel }
begin
while port[RXTX + 5] and $20 = 0 do;
port[RXTX] := data and $FF;
end; { Tx }
function RxWait : integer;
{ Waits for a character from serial channel }
begin
while not odd(port[RXTX + 5]) do;
RxWait := port[RXTX];
end; { RxWait }
procedure Tx2(data : integer);
{ Transmit a char on serial channel + Calculate check sum }
begin
Tx(data);
checkSum := (checkSum + data) and $FF;
end; { Tx2 }
Не могли бы вы, ребята, помочь мне, как преобразовать эти коды Паскаля в эквивалентный С#? Я знаю, что могу писать в порт, используя метод «port.Write», но это не может точно соответствовать коду Turbo Pascal с массивом портов (например, port[RXTX + 3] := $80;
). Я не знаю, что такое индекс массива портов «RXTX+3». ' относится к С#.
Я был бы очень признателен, если бы вы могли помочь мне в этом, и я надеюсь, что научусь преобразовывать остальные коды Паскаля самостоятельно. :)
Я написал следующий эквивалентный код C# для программы на паскале, используя помощь хороших людей. Пожалуйста, поправьте меня, если я допустил ошибку в своем коде.
public void Tx(int data)
{
if (!port.IsOpen)
port.Open();
port.Write(new byte[] { (byte)(data & 0xFF) }, 0, 1);
port.Close();
}
/// <summary>
/// Wait for a character from serial channel
/// </summary>
/// <returns></returns>
public int RxWait()
{
if (!port.IsOpen)
port.Open();
int readByte = port.ReadByte();
port.Close();
return readByte;
}
/// <summary>
/// Transmit a char on serial channel + Calculate check sum
/// </summary>
/// <param name="data"></param>
public void Tx2(int data)
{
Tx(data);
checkSum = (checkSum + data) & 0xFF;
}
Кстати вот протокол, описанный в документации устройства.
Computer SC 350/360
–––––––> ESC (message start)
–––––––> Command
<––––––> Data (direction depends on command)
<––––––> Check sum (direction depends on command)
<––––––– Receipt:
- ACK (if check sum is correct) or
- NAK (if check sum is incorrect)
И, кроме того, здесь я предоставил остальную часть кода с примером отправки команды для подсчета количества монет.
/// <summary>
/// Transmit command (no data) on serial channel
/// </summary>
/// <param name="c1"></param>
/// <param name="c2"></param>
/// <param name="sendCheckSum"></param>
public void TxCommand(char c1, char c2, bool sendCheckSum)
{
Tx(ESC);
checkSum = 0;
Tx2((int)c1);
Tx2((int)c2);
if (sendCheckSum)
{
Tx2(checkSum);
dummy = RxWait();
}
}
/// <summary>
/// Read n bytes from serial channel
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
public double ReadNumber(int n)
{
double number;
int i;
number = checkSum = 0;
for (i = 0; i < n; i++)
number = number * 256 + RxWait();
dummy = RxWait();
return number;
}
/// <summary>
/// Read the number of Coins counted
/// </summary>
/// <returns>Number of Coins</returns>
public double ReadCountReg()
{
TxCommand('R', 'C', false);
double coinsCounted = ReadNumber(4);
dummy = RxWait();
return coinsCounted;
}
отправить команду на подсчет монет;
double coinsCounted = ReadCountReg();
Console.WriteLine(Math.Round(coinsCounted, 0) + " coins counted");
Протокол чтения регистра счетчика:
Computer SC 350/360
–––––––> ESC
–––––––> “R”
–––––––> “C”
<––––––– CountRegister (CR)
<––––––– (CR ^ FF00,000016 + CR ^ FF,000016 + CR ^ FF0016 +
CR ^ FF16) ^ FF16
<––––––– ACK