|
Виж темите без отговор | Виж активните теми
Дата и час: Пон Юли 27, 2026 6:11 pm
Софтуерно четене на 24Cхx памети-откриване на топлата вода..
| Автор |
Съобщение |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
 Софтуерно четене на 24Cхx памети-откриване на топлата вода..
От разгледаното по форума разбрах, че тук има хора с доста солидни знания и опит, затова взех, че се регистрирах и аз.....Може пък и аз да кажа нещо ново....
1. Имам програма, с която чета 24С08, но ми трябва собствено разработена библиотека за четене на този вид памети.:
Опитвам се да прочета памет Атмел24С08 (със схемата, която съм прикачил) през RS232 и не става и не става. Правя го с Delphi 7. Молбата ми е ако има някой готов код (на Pascal/Delphi) за четене на i2c схеми - да видя къде бъркам. Съмнява ме тактовата честота дето подавам дали е правилна или Aкnolig сигнала, който се връща - не ми е ясно как ще върне Ак=0 когато линията е със стойност 0 и как ще се разбере дали въобще схемата отговаря?!?!?
Ел. схемата и паметта работят - тествам ги с PonyProg и няма проблеми.
Дайте някаква идея.
Благодаря предварително на всички.
Последна промяна krasisoft на Сря Дек 20, 2006 12:11 am, променена общо 1 път
|
| Вто Дек 19, 2006 11:00 pm |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
Тактовата честота би трябвало да е ОК и без това с Делфи-то неможеш да изгенерираш по-голяма от колкото може да понесе паметта. По-добре се съсредоточи върху времената на сигналите един спрямо друг. Някъде из архивите трябва да имам код за софтуерно I2C на С за микроконтролер, но то е същото - важното е да схванеш алгоритъма. Като го изнамеря, ще го постна ако мислиш, че ще ти свърши работа.
|
| Вто Дек 19, 2006 11:37 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30685 Местоположение: София
|
Проблема мможе да се окаже не толкова в делфито, колкото в винбоза, какво плваш за управление на порта, API или компонент, който ползва API? Ако екомпонент едва ли имаш някакви гаранции за времето за изпълнение на фунциите на компонента, а дори и сам да си го правиш през API пак не знам доколко можеш да определиш кое кога и за како време се изпълява. Ако имаш осцилоскоп няма да е лошо да видиш какво излиза, дали нямаш разминаване във продължителностите.
|
| Сря Дек 20, 2006 9:32 am |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Бавната скорост не е проблем, I2C протокола е синхронен протокол, докато високата скорост би объркала паметта, обаче надали ще можеш с Windows и четене/писане през порт, да извадиш повече от 100kHz.
Mного удобни за създаване на точни времезакъснения ( ако можем да използваме термина точност в многозадачна операционна система ) са функциите QueryPerformanceFrequency() и QueryPerformanceCounter() от Win32 API. С тях можеш да създаваш времеинтервали от микросекунди. Аз ги използвам в код за Win32 за I/O през паралелния порт. Нямам забележки към тях, работят си коректно ( само, че не използвам Делфи  )
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Сря Дек 20, 2006 10:55 am |
|
 |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
ОК. Не знаех, че по-бавната скорост не е проблем...Аз се опитвах да вдигна честотата. Скоростта на четене/запис не ме интересува за сега. Проблема е да я прочета един път. Ето кода, с който се боря вече 2 дена (Той е микс между моя и нещо, което намерих във форума на C++ за LPT, но идеята е същата). Къде бъркам. Грешката е в мене. Как да разбера, че 24С08 въобще приема нещо? Куца комуникацията - или аз не подавам правилната последователност от байтове, или честотата не е синхронизирана(според мен съм ги синхронизирал, ама знае ли човек PC-то на какво мнение е.....С Windows....трудно е да се правят точни предположения...)
Махнах кода, защото вече не е актуален и хората се бъркат.....има го постнат по-надолу.
[code][/code]
Последна промяна krasisoft на Съб Дек 23, 2006 5:32 pm, променена общо 2 пъти
|
| Сря Дек 20, 2006 7:09 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Процедурата на четена на I2C памети е следната:
старт сигнал;
адресира паметта с нейния I2C адрес;
мастера чете акнолидж;
запис на адреса в паметта, от който ще се чете;
мастера чете акнолидж;
повторен старт;
адресиране на паметта с нейния I2C адрес, с бит 0 вдигнат, т.е. вече ще се чете;
мастера чете акнолидж;
четене на един байт;
мастер изпраща нот акнолидж, ако ще чете само този байт, в противен случай изпраща акнолидж и се чете следващият байт;
генерира се стоп сигнала;
Така като гледам кода на Делфи, четеш от произволен адрес, защото нямаш запис на адрес в паметта от който ще четеш, адресираш директно паметта с нейния I2C адрес и четеш. Освен това не четеш акнолиджа, генерираш допълнителния клок за него, но не го четеш, т.е. ако наистина не знаеш на каква скорост работиш, задължително трябва да го четеш, тъй като паметта може на всеки такт да ти сваля клока, т.е. тя нагажда скоростта на мастер устройството според нейната маскимална скорост. Така на една I2C шина могат да се навържат и бавни и бързи устройства, това което е бавно ще накара мастера да се съобрази с него.
Вземи си разпиши като блок схема протокола на обмен и ще ти станат ясни нещата. Този протокол е много добре обяснен в дейта-чаршафите на MicroChip-пските I2C памети.
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Сря Дек 20, 2006 7:32 pm |
|
 |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
Много благодаря за съветите. Отидох, четох и вече записвам без проблеми на който адрес си искам. Ама за четенето несто не става - паметта малчи и не отговаря нищо. Погледнете процедурата за четене, може би бъркам в протокола на обмен (не пращам това дето трябва). Схемата даже и не се опитва да направи нещо - сякаш на нея не се говори...Какво ли не пробвах вече....
Благодаря предварително.
procedure TForm1.ReadBtnClick(Sender: TObject);
var
Temp : integer;
begin
i2c_start();
i2c_write($A1); //$A1 Команда : ще четем
// i2c_write($00); // Адрес на, от който ще четеме --???? и с тоя ред и без него все същото
Temp := i2c_read(True);
i2c_stop();
i2c_Delay;
end;
Ето това е за писане и работи.
procedure TForm1.WriteBtnClick(Sender: TObject);
begin
i2c_start();
i2c_write($A0); //$A0 Команда: ще записваме
i2c_write($00); // Адрес, на който ще записваме
i2c_write($00); // Данни
i2c_write($01);
i2c_write($02);
i2c_write($03);
i2c_stop();
end;
|
| Чет Дек 21, 2006 5:09 am |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
Мисля, че трябва така да бъде:
procedure TForm1.ReadBtnClick(Sender: TObject);
var
Temp : integer;
begin
i2c_start();
i2c_write($A0); //!!!!!!$A0 Команда : ще записваме адреса от който четем !!!!!!!!
i2c_write($00); // Адрес от който ще четеме
i2c_start(); // !!!!!Пак стартов бит !!!!!
i2c_write($A1); //!!!!!$A1 Командата ще четем е чак тук !!!!!
Temp := i2c_read(True);
i2c_stop();
i2c_Delay; //-> от това няма нужда, даже можеш всички delay да махнеш от кода
end;
Ама не съм ти погледнал самата процедура за четене на байта, че ме домързя - пробвай това и ако нестане пак ще погледна 
|
| Чет Дек 21, 2006 6:46 am |
|
 |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
Ами за разлика от по-преди - пак нищо. Иначе като махнах i2c_Delay() започна да пише с мълниеносна скорост, но това не е главната цел за момента...
Проблема е, че в lpModemStatus винаги имаме 0-сякаш паметта въобще не реагира на това дето и се подава.....HELP.
Ето това са процедурите за четене на байт:
Благодаря.
Последна промяна krasisoft на Съб Дек 23, 2006 5:02 pm, променена общо 2 пъти
|
| Чет Дек 21, 2006 7:56 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
Постни целия I2C код и захрани паметта от външо захранване, докато ти тръгнат нещата.
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Пет Дек 22, 2006 10:24 am |
|
 |
|
bobyk
Ранг: Ориентиран
Регистриран на: Пон Яну 09, 2006 11:32 am Мнения: 276 Местоположение: Kozloduy
|
Ами от това което си написал не разбрах прочел ли си даташита на поне няколко памети, при по големите адреса е 2 байта, поне аз такива малки с еднобайтов адрес не съм ползвал. Как разбираш че записа ти е бил успешен, само по ACK? Ако си успял да пишеш сигурно захр на паметта е добре.
Успех, пиши какво става.
|
| Пет Дек 22, 2006 11:55 am |
|
 |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
Относно 2-байтовия адрес....Ползвам 24С04, която е 512 байта и се адресира като 2 страници от по 256 байта, т.е. еднобайтов адрес за отместаване в страницата е достатъчен. Мерси за мнението.
Ето това е целият i2c-код:
 |  |  |  | Код: implementation
{$R *.dfm}
procedure TTForm24C04.i2c_Delay; begin Sleep(0); end;
//************************************************************** //**************** Predavame prez DTR ************************* //**************** Priemame prez CTS ************************* //**************** Taktuvame prez RTS ************************* //**************************************************************
procedure TTForm24C04.ReadBtnClick(Sender: TObject); var Temp : integer; begin MyInitComm(strComPort, BoundRate, BiteCount, nStopBits); // Vrasta hCom_ComRW na otvoreniq COM-port fReading := True; bStop5VThread_ComRW := False; bExitThread := False; StartCommThread(Self, TForm24C04.WindowHandle); // Podava 5v zaxranvane na shemata i2c_Delay;
//*********** Cetene ot pametta *****************
i2c_Start; i2c_Write($A0); //!!!!!!$A0 Komanda : ste zapisvame adresa ot koito ceteme --> Page 0!!!!!!!! i2c_Write($00); // Address/offset ot koito ste ceteme --> Page 0 address $00 i2c_Start; // !!!!!Startov bit !!!!! i2c_Write($A1); //!!!!!$A1 Komanda - ste cetem !!!!! i2c_Delay; Temp := i2c_Read(True); // True --> cetem samo 1 byte i2c_SendNotAck; i2c_Stop;
bStop5VThread_ComRW := True; bExitThread := True; fReading := False;
Edit1.Text := Edit1.Text + ' ' + IntToHex(Temp,2); CloseHandle(hCom_ComRW); end;
function TTForm24C04.i2c_Read(Last : Boolean ) : Byte; var Byt : string; i : integer; begin SetDTR_SDA(0); //CLEAR_SDA(); i2c_Delay; //* Initialize byte value */ Byt := ''; //* Receive BYTE, MSB first */ for i:=1 to 8 do begin i2c_Delay; SetRTS_SCL(1); // SET_SCL(); SCL = 1 i2c_Delay; if GetCTS = 1 then i2c_Delay; Byt := Byt + IntToStr(CTS_Signal);
SetRTS_SCL(0); //CLEAR_SCL(); SCL = 0 i2c_Delay; if GetCTS = 1 then i2c_Delay; end;
// Get ready for acknowledge: is it the last byte to read ? */ if( Last ) then SetDTR_SDA(1) // SET_SDA(); else begin //------------ Acknolige --------------------- SetDTR_SDA(0); // CLEAR_SDA(); i2c_delay; //* Get the acknowledge */ SetRTS_SCL(1); // SET_SCL(); i2c_delay;
if GetCTS=1 then Error_NoACK := True else Error_NoACK := False;
SetRTS_SCL(0); //CLEAR_SCL(); i2c_delay; //------------ Acknolige --------------------- end; Result := BinToInt(Byt); end;
procedure TTForm24C04.i2c_write(byt : Byte); { Write a byte to the I2C bus; errors are stored in I2C_Status and can be inspected by calling i2c_status() */ } var i, Comp : integer; begin Num := Byt; //* Send BYTE, MSB first */ for i:=1 to 8 do begin Comp := Num and $80; if Comp > 0 then SetDTR_SDA(1) // SET_SDA(); else SetDTR_SDA(0); // CLEAR_SDA(); //* Get ready for next bit */ Num := Num Shl 1; //// //byt <<= 1; if Num>$FF then Num := Lo(Num); //// Pravi go do byte
SetRTS_SCL(1); // SET_SCL(); i2c_delay; SetRTS_SCL(0); //CLEAR_SCL(); i2c_delay; Application.ProcessMessages; end;
SetDTR_SDA(0); // CLEAR_SDA(); i2c_delay; //* Get the acknowledge */ SetRTS_SCL(1); // SET_SCL(); i2c_delay; Application.ProcessMessages; if GetCTS=1 then Error_NoACK := True else Error_NoACK := False;
SetRTS_SCL(0); //CLEAR_SCL(); i2c_delay; end;
//* ------------------------------------------------------------------------ */
function TTForm24C04.GetCTS : integer; var lpModemStatus : DWORD ; begin GetCommModemStatus(hCom_ComRW, lpModemStatus); if (lpModemStatus = MS_CTS_ON) then //Tova e casten slucaj samo za CTS ne e universalno CTS_Signal := 1 else CTS_Signal := 0; Result := CTS_Signal; end;
procedure TTForm24C04.i2c_Start; begin //* Generate I2C START condition */ SetDTR_SDA(1); //SDA = 1 SetRTS_SCL(1); // SCL = 1 i2c_delay; SetDTR_SDA(0); //SDA = 0 i2c_delay; SetRTS_SCL(0); // SCL = 0 i2c_delay; end;
procedure TTForm24C04.i2c_Stop; begin //* Generate I2C STOP condition */ SetDTR_SDA(0); // CLEAR_SDA(); i2c_delay; SetRTS_SCL(1); // SET_SCL(); i2c_delay; SetDTR_SDA(1); // SET_SDA(); i2c_delay; end;
// Master in receive mode must generate AckNo signal for slave procedure TTForm24C04.i2c_SendAck; begin SetDTR_SDA(0); // _SDA = 0; i2c_Delay; SetRTS_SCL(1); // _SCL = 1; i2c_Delay; SetRTS_SCL(0); // _SCL = 0; i2c_Delay; end;
procedure TTForm24C04.i2c_SendNotAck; begin SetDTR_SDA(1); // _SDA = 1; i2c_Delay; SetRTS_SCL(1); // _SCL = 1; i2c_Delay; SetRTS_SCL(0); // _SCL = 0; i2c_Delay; end;
procedure TTForm24C04.i2c_RepStart(i2cslave : Byte); begin i2cslave := $A1; // The device address is 1010 0001b Address = $00 s posleden bit=1 za cetene SetDTR_SDA(1); // _SDA = 1; i2c_Delay; i2c_Start; // Write device address for read operation i2c_Write(i2cslave); end;
procedure TTForm24C04.FormCreate(Sender: TObject); begin fReading := False; WriteCount := 1; //********************************************************************* Error_NoACK := False; strComPort := 'COM1'; BoundRate := 19200; BiteCount := 8; nStopBits := ONESTOPBIT; bExitThread := False; bStop5VThread_ComRW := False;
MainWnd := TForm24C04.WindowHandle; // Pokazva na Thread-a za BarCodReader-a na koj prozorec da prati saobstenieto // MyInitComm(strComPort, BoundRate, BiteCount, nStopBits);
// StartCommThread(Self, TForm24C04.WindowHandle); // Caka za signal po CTS
//********************************************************************* Num := 13;
end;
procedure TTForm24C04.OnMyMessage(var Msg: TMessage); begin if CTS_Signal = 1 then CTSShape.Brush.Color := clLime else CTSShape.Brush.Color := clSilver;
end;
procedure TTForm24C04.ExitThreadBtnClick(Sender: TObject); begin bStop5VThread_ComRW := True; bExitThread := True; end;
procedure TTForm24C04.SetDtrBtnClick(Sender: TObject); begin fReading := True; SetDTR_SDA(1); Sleep(1); if CTS_Signal = 1 then CTSShape.Brush.Color := clLime else CTSShape.Brush.Color := clSilver; Application.ProcessMessages; Edit1.Text := 'Start'; fReading := False; end;
procedure TTForm24C04.ClearDTRBtnClick(Sender: TObject); begin fReading := True; SetDTR_SDA(0); fReading := False; end;
procedure TTForm24C04.StarThreadBtnClick(Sender: TObject); begin bStop5VThread_ComRW := False; bExitThread := False; StartCommThread(Self, TForm24C04.WindowHandle); // Caka za signal po CTS end;
function TTForm24C04.BinToInt(Value : string) : longInt; function Stepen(Value : Real;Stp : integer) : real; var i : integer; begin Result := 1; for i:=1 to Stp do Result := Result*Value; end;
var i, Len : integer; Str : string; begin Result := 0; Len := 0; Str := ''; for i:= 1 to Length(Value) do if not(Value[i] = ' ') then begin Inc(Len); Str := Str + Value[i]; end; Value := Str; for i:= 1 to Len do Result :=Result+StrToInt(Value[i])*Round(Stepen(2,Length(Value)-i)); end;
function TTForm24C04.IntToBin(Value : LongInt; FillByte : integer):string; var EndConvert : Boolean; i : integer; begin EndConvert := False; Result := ''; while not EndConvert do begin if (Value mod 2)=0 then Result := '0'+ Result else Result := '1'+ Result; Value := Value div 2; if Value = 0 then EndConvert := True; end; if Length(Result) < FillByte then for i:= Length(Result)+1 to FillByte do Result := '0' + Result; end;
procedure TTForm24C04.WriteBtnClick(Sender: TObject); var // sBufToSend, sBufRead : String; // i : integer; Temp : integer; Offset : Byte; begin Temp := 12; fReading := True; bStop5VThread_ComRW := False; bExitThread := False;
MyInitComm(strComPort, BoundRate, BiteCount, nStopBits);
StartCommThread(Self, TForm24C04.WindowHandle); // Caka za signal po CTS
i2c_Delay;
for WriteCount:=1 to 32 do begin i2c_start(); if WriteCount<=16 then begin i2c_write($A0); //$A0 êîìàíäà : ùå çàïèñâàìå Page 0 Application.ProcessMessages; Sleep(40); Offset := 1; end else begin i2c_write($A2); //$A0 êîìàíäà : ùå çàïèñâàìå Page 1 Application.ProcessMessages; Sleep(40); Offset := 17; end; i2c_write((WriteCount - Offset)*$10); // Àäðåñ íà, êîéòî ùå çàïèñâàìå i2c_write($00); // Äàííè i2c_write($01); i2c_write($02); i2c_write($03); i2c_write($04); i2c_write($05); i2c_write($06); i2c_write($07); i2c_write($08); i2c_write($09); i2c_write($10); i2c_write($11); i2c_write($12); i2c_write($13); i2c_write($14); i2c_write($15); i2c_stop(); Application.ProcessMessages; Sleep(40); i2c_Delay; end;
bStop5VThread_ComRW := True; bExitThread := True; fReading := False;
Edit1.Text := IntToHex(Temp,2); CloseHandle(hCom_ComRW);
end;
end. |  |  |  |  |
Последна промяна krasisoft на Съб Дек 23, 2006 5:00 pm, променена общо 1 път
|
| Съб Дек 23, 2006 11:03 am |
|
 |
|
Predator_MF
Ранг: Форумен бог
Регистриран на: Чет Окт 07, 2004 1:22 pm Мнения: 1949 Местоположение: София
|
Съвет - постави функциите за I2C извън класа на TForm-a, или в отделен клас, или без клас. Друг съвет - с тоя sleep(10) ще чакаш цял ден да се изчете паметта, ползвай микросекунден delay, ако се затрудняваш има много примери в нета. И още един съвет докато съм се сетил - 10ms закъснение, за изчитане на 1 байт от паметта ти трябват 150-250ms, за толкова време визуализацията на програмата ти зависва...напиши всички функции за I2C в отделен pas файл, добави един Thread в програмата си, при натискане на бутона караш Thread-а да ти изпълни кода за четене, така няма да прекъсваш визуализацията. А освен това избягвай в такива "low level" изпълнения да ползваш string-а на Delphi, специално в случая с i2c_read говоря, където обръщаш от int в str, после добавяш към друг стринг и накрая пак обръщаш string в integer с някаква функция...можеш доста по елементарно да го напишеш това...примерно:
|
| Съб Дек 23, 2006 12:51 pm |
|
 |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
Мерси за съвета - ше го направя. А това за Sleep(10) - чел си стария код - вече го махнах. Това за thred-a вече е направено, но засега не искам да давам на Виндовс-а да се занимава с нищо друго, а само с моята програмка, защото искам да избегна пращането и обработката на съобщения в това време. Кода още не е оптимизиран - това е работен вариант и там съм писал работи само и само да тръгне. Оптимизациите ги оставям накрая. Не виждам какво ще промени нещата ако изкарам всички процедури извън класа на формата (това ще го направя естествено - накрая ще сложа всичко като готова библиотека за четене на i2c памети за Делфи и ще го постна във форума. Така следващия дето иска да си прави собствена библиотек няма да загуби няколко дена като мене....).
Така-а-а на проблема.... Мисля, че грешката е точно в момента когато подготвям COM-порта за приемане на данни.(От схемата се вижда, че като вдигам SDA се вдига и CTS - свързани са на една линия). Та когато чакам данни по CTS аз свалям състоянието на SDA=0. И точно в тоя момент схемата се шашка и млъква. Може би приема някакъв съгнал който я обърква.......или се рестартира....Ще пробвам и с външно захранване...ама щом мога да записвам значи трябва да е добре.
Благодаря предварително.
|
| Съб Дек 23, 2006 5:22 pm |
|
 |
|
krasisoft
Ранг: Минаващ
Регистриран на: Вто Дек 19, 2006 10:39 pm Мнения: 8
|
Значи...сложих външно захранване и се държи доста по-стабилно, но проблема с четенето си остава. Утре ще гледам сигналите с осцилоскоп, че един проятел ще донесе двулъчев. Предполагам, че получава някой пик дето не трябва да го има.
Иначе според мен всичко си е ОК вече.
|
| Пон Дек 25, 2006 10:58 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 0 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|