PDA

Ver la Versión Completa : Delphi y intelhex


JoseFco
22-03-2008, 18:33:17
"Tolomeo se mudo al Polo Norte"

MaMu
22-03-2008, 18:41:14
Imagino que para mostrar sólo los datos válidos, tenes que jugar con el retorno de la función ReadLine, es decir:


while (readline(memo1.line[i],buf)=0) do
begin
end;

JoseFco
22-03-2008, 18:58:57
"Tolomeo se mudo al Polo Norte"

MaMu
22-03-2008, 19:15:39
La función de ReadLine, llena un buffer línea a línea del contenido del HEX, y va traduciendo la lectura según esta conformada la linea. La explicación es sencilla, y se basa en el formato Hex de Intel


Intel Hex is a common format to store binaries to be loaded into EPROM for
CPU's. It is a readable textformat that is line oriented. A line is built as

':', rec len, address, rec type, [data], checksum
whereas :
':' is start of record = 0x3A
reclen is the number of databytes as 2 digit hex
address is 4 digit hex, where the data starts
rec type is '00' for normal data, '01' end of file, '02' extended adress
[data] is a data packet encoded as hex
checksum is the 2's complement of the sum over the record excl the ':' modulo 256 as hex


Donde deja un ejemplo claro



:1005AA00000102030405060708090A0B0C0D0E0F88
rec len = 0x10 = 16
address = 0x05AA
data = 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
checksum = 0x88 = 256 -sum(0x00+..+0x0F)= 256- 0x78


Y a tomar encuenta el mapeo según el tipo de Eprom

There are extended formats, and there is the chance that the EPROM
is not located at 0x0000, but at 0xF0000 or similar.

Al encontrarse con un dato no válido, la función retorna el código de error #integer, sino devueve 0=OK.


Saludos

JoseFco
22-03-2008, 19:25:19
"Tolomeo se mudo al Polo Norte"

eduarcol
22-03-2008, 19:29:22
Podrias explicarnos a que te refieres con linea valida?, y porque el readln no te sirve, quizas asi muchos podriamos colaborar

JoseFco
22-03-2008, 19:35:56
"Tolomeo se mudo al Polo Norte"

MaMu
22-03-2008, 19:38:40
Hola mamu.

Mi problema no es como entender IntelHex. Con eso no tengo problema, puedo leerlo y interpretarlo.
http://www.kmitl.ac.th/~kswichit%20/illustrate/hex.htm

Mi problema es con Delphi, que no lo domino.Tengo muy poco tiempo estudiandolo, para ser mas exactos solo tengo unas semanas en Delphi.

Un Saludo.

Ah, osea que tu problema con Delphi, es la falta de domino de Pascal.


function AprendoDelphi(yo:string):boolean;
begin
if PracticoMucho(yo) then Result:=True else Result:=False;
end;

begin
if AprendoMucho('Pepe')
then showmessage('Anda la osa!!!')
else showmessage('Me quiero volver chango!!!');
end.



:D

JoseFco
22-03-2008, 22:26:10
"Tolomeo se mudo al Polo Norte"

mario2000
23-03-2008, 00:32:30
Pues he aca la solucion: No voy a inventar que yo lo hise por que pa que, estoy estudiando esto pero si uds quieren adelanten para que despues me ayuden, vallan a este link:
http://www.sixca.com/delphi/article/readhex.html
y en la pagina prinsipal mucho mas:
http://www.sixca.com/delphi/index.html

ademas e conseguido el codigo de varios grabadores en delphi tal ves lo suba para que lo estudien.

Solo me falta el del icprog y el del winpic800 para completar la coleccion.
:D

JoseFco
23-03-2008, 01:15:52
"Tolomeo se mudo al Polo Norte"

JoseFco
23-03-2008, 01:31:43
"Tolomeo se mudo al Polo Norte"

JoseFco
23-03-2008, 02:57:12
"Tolomeo se mudo al Polo Norte"

eduarcol
23-03-2008, 04:04:08
Segun lo poco que entendi tengo unas propuestas, son dos lineas basicamente las puse en rojo para que las identifiques. En la primera devuelvo cero si el resultado es correcto, y en la segunda lo agrego al memo

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Label1: TLabel;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type buffer=array of byte; //assign as Dynamic array
var HexBuf:buffer;
function ByteToHex(InByte:byte):shortstring;
const Digits:array[0..15] of char='0123456789ABCDEF';
begin
result:=digits[InByte shr 4]+digits[InByte and $0F];
end;
function readline(HexLine:string; var Buf:buffer):integer;
var ADDR,count:integer;
CHKSUM,SUMLINE,RECLEN,RECTYPE,DATA:byte; t:shortstring;
begin
// Array length may be change, here is 100,000
SetLength(HexBuf,100000);
if HexLine[1]=':' then begin
t:='$'+copy(HexLine,2,2); // get length
RECLEN:=strtoint(t);
CHKSUM:=0;
CHKSUM:=CHKSUM+RECLEN;
t:='$'+copy(HexLine,4,4); // get address
ADDR:=strtoint(t);
CHKSUM:=CHKSUM+lo(ADDR)+hi(ADDR);
t:='$'+copy(HexLine,8,2);
RECTYPE:=strtoint(t);
CHKSUM:=CHKSUM+RECTYPE;
case RECTYPE of
0:begin // datablock
count:=0;
while (count < RECLEN) do begin
t:='$'+copy(HexLine,10+2*count,2);
DATA:=strtoint(t);
CHKSUM:=CHKSUM+DATA;
Buf[ADDR+count]:=DATA;
inc(count);
end;
t:='$'+copy(HexLine,10+2*count,2);
SUMLINE:=strtoint(t);
Result := 0;
end;
1:begin // end of file
t:='$'+copy(HexLine,10,2);
SUMLINE:=strtoint(t);
result:=1;
end;
else
begin
result := -2; // invalid record type
exit;
end;
end; //case
// test checksum
DATA:=SUMLINE+CHKSUM;
if (DATA<>0) then result:=-3; // checksum error
end
else result:=-1; // no record
end;
procedure TForm1.Button1Click(Sender: TObject);
var Fname,line:string;
Fp : textfile;
ErrorCode:integer;
begin
Fname:='test.hex';
AssignFile(Fp,Fname); { File selected in dialog }
Reset(Fp);
while not eof(Fp) do
begin
Readln(Fp,line);{ Read first line of file }
ErrorCode := readline(line,HexBuf);
if (ErrorCode=0) then
begin
// Do some thing if read one line OK
// such send data to serial port,parallel port etc.
Memo1.Lines.Add(ByteToHex(HexBuf));
end
else
begin
// Error handle here
// 0 = No error
// -1 = File not Intel Hex format
// -2 = Invalid record type
// -3 = Checksum error
end;
end;
CloseFile(Fp);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
Label1.Caption:=OpenDialog1.FileName;
end;
end;
end.

JoseFco
23-03-2008, 14:23:48
"Tolomeo se mudo al Polo Norte"

JoseFco
23-03-2008, 14:49:30
"Tolomeo se mudo al Polo Norte"

eduarcol
23-03-2008, 15:02:49
es que el asunto radica , segun lo que entendi la linea que necesitas esta en HexBuf que es de tipo Byte, el asunto es convertirlo a string por eso utilize la funcion que agregue al principio

seoane
23-03-2008, 16:10:25
Si lo que quieres es solamente eliminar lo que no son datos de cada linea, podemos usar una función como esta:

function Strip(Str: String): String;
var
i,j,k: Integer;
begin
Result:= EmptyStr;
Str:= Trim(Str);
if Copy(Str,1,1) = ':' then
if TryStrToInt('$' + Copy(Str,2,2),i) then
if Length(Str) = ((2*i) + 11) then
if TryStrToInt('$' + Copy(Str,4,4),j) then
if TryStrToInt('$' + Copy(Str,8,2),k) then
if k = 0 then
Result:= Copy(Str,10,2*i);
end;


Y si queremos cargar todo en un memo:

var
i: Integer;
Str: String;
begin
with TStringList.Create do
try
LoadFromFile('d:\test.hex');
for i:= 0 to Count - 1 do
begin
Str:= Strip(Strings[i]);
if Str <> EmptyStr then
Memo1.Lines.Add(Str);
end;
finally
Free;
end;
end;


Por otro lado lo que podemos querer en realidad es obtener todos los bytes que se van a grabar (incluidos los que no aparecen el archivo que yo supongo como ceros) y además ordenados. Eso ya es un poco, solo un poco, mas complicado ¿es eso lo que quieres? :confused:

JoseFco
23-03-2008, 16:45:44
"Tolomeo se mudo al Polo Norte"

seoane
23-03-2008, 16:48:45
Bueno, siguiendo con mi respuesta anterior:

type
TBuffer = array[$0000..$FFFF] of Byte;

// Insertamos la linea de datos en un buffer
function Insertar(Str: String; var Buffer: TBuffer): String;
var
i,j,k: Integer;
begin
Result:= EmptyStr;
Str:= Trim(Str);
if Copy(Str,1,1) = ':' then
if TryStrToInt('$' + Copy(Str,2,2),i) then
if Length(Str) = ((2*i) + 11) then
if TryStrToInt('$' + Copy(Str,4,4),j) then
if TryStrToInt('$' + Copy(Str,8,2),k) then
if k = 0 then
begin
Str:= Copy(Str,10,2*i);
for k:= j to (j + i - 1) do
begin
Buffer[k]:= StrToInt('$' + Copy(Str,1,2));
Delete(Str,1,2);
end;
end;
end;


// Aqui leemos el archivo y mostramos la informacion en un memo
var
i,j: Integer;
Str: String;
Buffer: TBuffer;
begin
Memo1.Clear;
with TStringList.Create do
try
LoadFromFile('d:\test.hex');
// Llenamos todo el buffer con ceros
FillChar(Buffer,Sizeof(Buffer),#0);
// Leemos el archivo linea a linea e insertamos los datos en el buffer
for i:= 0 to Count - 1 do
Insertar(Strings[i],Buffer);
Str:= EmptyStr;
j:= Sizeof(Buffer) - 1;
// Buscamos el ultimo dato que no es un cero
while (Buffer[j] = 0) and (j > 0) do
dec(j);
// Mostramos el contenido del buffer en un memo
for i:= 0 to j do
begin
Str:= Str + #32 + IntToHex(Buffer[i],2);
// 16 bytes por linea
if ((i+1) mod 16 = 0) then
begin
Memo1.Lines.Add(Str);
Str:= EmptyStr;
end;
end;
finally
Free;
end;
end;


Solo quedaría añadir algunas cosillas, como la comprobación de la "suma de comprobación".

JoseFco
23-03-2008, 17:07:10
"Tolomeo se mudo al Polo Norte"

seoane
23-03-2008, 17:09:27
Memo1 es el nombre de un memo que debes tener colocado en tu formulario

JoseFco
23-03-2008, 17:13:50
"Tolomeo se mudo al Polo Norte"

seoane
23-03-2008, 17:17:27
Creo que no me explique bien, el código no debe escribirse directamente en la unit, se debe encerrar dentro de algún evento como por ejemplo hacer click sobre un botón:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

type
TBuffer = array[$0000..$FFFF] of Byte;

function Insertar(Str: String; var Buffer: TBuffer): String;
var
i,j,k: Integer;
begin
Result:= EmptyStr;
Str:= Trim(Str);
if Copy(Str,1,1) = ':' then
if TryStrToInt('$' + Copy(Str,2,2),i) then
if Length(Str) = ((2*i) + 11) then
if TryStrToInt('$' + Copy(Str,4,4),j) then
if TryStrToInt('$' + Copy(Str,8,2),k) then
if k = 0 then
begin
Str:= Copy(Str,10,2*i);
for k:= j to (j + i - 1) do
begin
Buffer[k]:= StrToInt('$' + Copy(Str,1,2));
Delete(Str,1,2);
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i,j: Integer;
Str: String;
Buffer: TBuffer;
begin
Memo1.Clear;
with TStringList.Create do
try
LoadFromFile('d:\test.hex');
FillChar(Buffer,Sizeof(Buffer),#0);
for i:= 0 to Count - 1 do
Insertar(Strings[i],Buffer);
Str:= EmptyStr;
j:= Sizeof(Buffer) - 1;
while (Buffer[j] = 0) and (j > 0) do
dec(j);
for i:= 0 to j do
begin
Str:= Str + #32 + IntToHex(Buffer[i],2);
if ((i+1) mod 16 = 0) then
begin
Memo1.Lines.Add(Str);
Str:= EmptyStr;
end;
end;
finally
Free;
end;
end;

end.

JoseFco
23-03-2008, 17:29:16
"Tolomeo se mudo al Polo Norte"

JoseFco
23-03-2008, 17:32:01
"Tolomeo se mudo al Polo Norte"

JoseFco
23-03-2008, 17:45:43
"Tolomeo se mudo al Polo Norte"

seoane
23-03-2008, 17:51:44
Tienes razón, solo hace falta una pequeña corrección:

var
i,j: Integer;
Str: String;
Buffer: TBuffer;
begin
Memo1.Clear;
with TStringList.Create do
try
LoadFromFile('d:\test.hex');
FillChar(Buffer,Sizeof(Buffer),#0);
for i:= 0 to Count - 1 do
Insertar(Strings[i],Buffer);
Str:= EmptyStr;
j:= Sizeof(Buffer) - 1;
while (Buffer[j] = 0) and (j > 0) do
dec(j);
for i:= 0 to j do
begin
Str:= Str + #32 + IntToHex(Buffer[i],2);
if ((i+1) mod 16 = 0) then
begin
Memo1.Lines.Add(Str);
Str:= EmptyStr;
end;
end;
// ---- Solo hay que añadir estas dos lineas ---
if Str <> EmptyStr then
Memo1.Lines.Add(Str);
finally
Free;
end;
end;

JoseFco
23-03-2008, 18:17:28
"Tolomeo se mudo al Polo Norte"

mario2000
23-03-2008, 22:38:50
Hola JoseFco, y no era un programador de pics? :confused:
aunque el que quieras esta bien pero no hagas como algunos que despues no comparten la informacion, aunque por lo visto te gusta compartir. :D

JoseFco
23-03-2008, 22:57:20
"Tolomeo se mudo al Polo Norte"

mario2000
24-03-2008, 15:08:12
Gracias JoseFco, eres una gran persona.

Solo queria preguntarte si despues piensas colocar los datos del hex en un stringrid tal como los programadores como winpic800 o icprog?

Tambien ya que quieres utilisar un puerto diferente al paralelo puedes utilizar un adactador que se consigue para convertir de usb a 232 FS232, y en la pagina del chip hay ejemplos de control para delphi podrias utilisarlo. :rolleyes:

JoseFco
24-03-2008, 21:18:54
"Tolomeo se mudo al Polo Norte"

JoseFco
24-03-2008, 21:33:04
"Tolomeo se mudo al Polo Norte"

JoseFco
25-03-2008, 01:43:54
"Tolomeo se mudo al Polo Norte"

ArdiIIa
25-03-2008, 14:41:09
Hola amigos.

Una consulta: Partiendo de este file que estara en un memo:


Una ayudadita a ver por donde arranco.



Tal vez un hilo que se publicó (http://www.clubdelphi.com/foros/showthread.php?t=39871) hace tiempo pueda orientarte en el asunto y con unas pequeñas modificaciones del código que se puso, podrías hallar la respuesta...

seoane
25-03-2008, 15:07:54
Creo que lo estas enfocando de una manera equivocada JoseFco, para que quieres andar jugando con los datos en un memo cuando ya tienes todos los bytes guardados en un array.

Analicemos el código:

var
i,j: Integer;
Str: String;
Buffer: TBuffer;
begin
if OpenDialog1.Execute then
begin
Label1.caption:=OpenDialog1.FileName;
// Borramos el memo
Memo1.Clear;
with TStringList.Create do
try
LoadFromFile(Label1.Caption);
// Llenamos el buffer con ceros, si prefieres rellenar con FF usa #$FF en vez de #0
FillChar(Buffer,Sizeof(Buffer),#0);
// Leemos cada un de las lineas del fichero
for i:= 0 to Count - 1 do
Insertar(Strings[i],Buffer);
// Ahora dentro del buffer tenemos todos los bytes

{ Este trozo de codigo servia para decidir cuanto bytes mostrar
j:= Sizeof(Buffer) - 1;
while (Buffer[j] = 0) and (j > 0) do
dec(j);
}

// Pero si ya sabes cuantos bytes quieres mostrar
j:= StrToInt(Label2.caption);

Str:= EmptyStr;
for i:= 0 to j do
begin
Str:= Str + #32 + IntToHex(Buffer[i],2);
if ((i+1) mod 16 = 0) then
begin
Memo1.Lines.Add(Str);
Str:= EmptyStr;
end;
end;
if Str <> EmptyStr then
Memo1.Lines.Add(Str);
finally
Free;
end;
end;
end;


Fíjate que en buffer ya tenemos los bytes tal cual se tienen que mandar al programador, así que cuando hagas la rutina de envío no vayas a coger los datos del memo y convertirlos a bytes, seria hacer el mismo trabajo dos veces. :)

JoseFco
25-03-2008, 22:04:41
"Tolomeo se mudo al Polo Norte"

seoane
25-03-2008, 22:37:56
Venga una modificación :D:

for i:= 0 to j - 1 do

El problema viene porque el buffer empieza a numerar los bytes desde cero.

Por cierto hablando sobre programadores http://www.ic-prog.com/ es uno de los mejores que he visto (aunque no he visto demasiados :p ), y además esta hecho en delphi :D ... lo malo es que no muestra el código fuente :(

JoseFco
25-03-2008, 23:03:27
"Tolomeo se mudo al Polo Norte"

FGarcia
26-03-2008, 05:49:27
GRRRRRR!!!

Va de nuez!!!

GUI es la abreviatura (acronimo ¿seria lo correcto?) de Graphical User Interfase es decir en castellano: Interface de Usuario Grafica y ¡NO es un lenguaje de programacion!

Todos los programas en Windows independiente del lenguaje son GUI. Delphi te permite hacer GUI que son todas las ventanas y formularios que crea tu aplicación.

JoseFco
27-03-2008, 00:42:13
"Tolomeo se mudo al Polo Norte"

seoane
27-03-2008, 14:59:58
:eek: Caramba !!! ¿ya lo tienes terminado? Yo pensé que solo estabas empezando.

¿Se puede echar un vistazo al código? :)

JoseFco
27-03-2008, 19:18:51
"Tolomeo se mudo al Polo Norte"

JoseFco
28-03-2008, 03:56:21
"Tolomeo se mudo al Polo Norte"

FGarcia
28-03-2008, 05:33:17
Continuando con el relajo de los bytes.

Fíjate que en buffer ya tenemos los bytes tal cual se tienen que mandar al programador, así que cuando hagas la rutina de envío no vayas a coger los datos del memo y convertirlos a bytes, seria hacer el mismo trabajo dos veces.


Sabiendo que el file a mandar estara en el buffer y estando amarrado al procedure ComPortRxChar con el ComPort.WriteStr.
ComDataPacket esta descartado que no se puede usar, segun lo que he mirado en otros hilos.
La cosa es que el contenido del buffer saldra por el serial port de uno en uno y cada vez que salga uno el chip master del programador me retornara un byte "53" para dejarme saber que ya termino su tarea y esta disponible a que le mande el siguiente.En esta rutina como en la de "Borrar el chip" tambien me devolvera "01" con eso no tengo problema se le asignara (cuenta= #).Ya sabemos que la cantidad de bytes en el buffer son 4096 bytes.
Aqui la pregunta tengo que crear una rutina que este incrementando esa cuenta para saber cuando parar o el buffer es capaz de hacer esta tarea por si solo?

A ver los maestros una ayudadita por donde comenzar.

Un Saludo.

Creo que eso deberia de continuar aqui (http://www.clubdelphi.com/foros/showthread.php?t=54671)donde empezo. Esto para no desvirtuar (http://www.clubdelphi.com/foros/showthread.php?t=53377) este hilo.:eek: