Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Проблем с четенето на RTC DS1307
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=5197
Страница 1 от 1

Автор:  the_electronic_m@n [ Сря Дек 12, 2007 5:21 pm ]
Заглавие:  Проблем с четенето на RTC DS1307

Здравейте :) Имам проблем с комуникацията между PIC2520 и DS1307. В самото начало RTC-то въобще ни ми "отговаряше"(не генерираше АСК). След 1 седмица главоблъсканица проблема се оправи (оказа се, че програмата ми не е била написана както трябва :) ). Имам изключително големи съмнения(след още 2 седмици главоблъсканица), че и програмата ми за четене не е направена както трябва, затова Ви моля, ако някой има някаква примерна програма за четене на RTC-то, но да НЕ се използва вградения в PIC-а MSSP модул, ще му бъда много благодарен за помощта.

Автор:  Zdrav [ Сря Дек 12, 2007 5:41 pm ]
Заглавие: 

Нямам програмка за DS1307. А и звучиш малко объркано за да се опита човек да ти помогне.Но... освен софтуерните проблеми търсил ли си и хардуерни? Какви са напреженията на VCC и VBAT измерени директно върху крачетата на чипа?

Автор:  stanleyhacker [ Сря Дек 12, 2007 6:02 pm ]
Заглавие: 

eedatap = 0x00; //seconds;
i2cSend(0xD0, 0x00, 1, 1, &eedatap);
ms_spin(5);
eedatap = RtcTime.minutes;
i2cSend(0xD0, 0x01, 1, 1, &eedatap);
ms_spin(5);
eedatap = RtcTime.hours;
i2cSend(0xD0, 0x02, 1, 1, &eedatap);
ms_spin(5);
eedatap = RtcTime.day;
i2cSend(0xD0, 0x04, 1, 1, &eedatap);
ms_spin(5);
eedatap = RtcTime.month;
i2cSend(0xD0, 0x05, 1, 1, &eedatap);
ms_spin(5);
eedatap = (RtcTime.year - 2000);
i2cSend(0xD0, 0x06, 1, 1, &eedatap);

Праща се пакет с два адреса - D0 адрес на DS1307 и веднага след това адрес минути, секунди, те са описани. за данни е ясно какво пращаш.


самото пращане:

//! Send a byte sequence on the I2C bus
void i2cSend(u08 device, u16 subAddr,u08 addrlength, u08 length, u08 *data)
{
I2C_START; // старт кондишън
i2cPutbyte(device); // адрес на устройството
if (addrlength == 2) i2cPutbyte(subAddr >> 8); // and the subaddress ако е 2 байта, а той не е !!!
if (addrlength > 0) i2cPutbyte(subAddr); // and the subaddress low byte
// send the data
while (length--) //докато свършат байтовете данни, пращай
i2cPutbyte(*data++);

I2C_SDL_LO; // clear data line and
I2C_STOP; // send STOP transition
}


Старт и стоп кондишън и i2cPutbyte ти ги оставям за домашно. Ако не се справиш ще ти пратя и i2cPutbyte.
Всъщност програмата е за АТМЕГА, но принципа си е същия.

По същия начин четене:

i2cReceive(0xD0, 0x00, 1, 1, &eedatap);
RtcTime.seconds = eedatap;
i2cReceive(0xD0, 0x01, 1, 1, &eedatap);
RtcTime.minutes = eedatap;
i2cReceive(0xD0, 0x02, 1, 1, &eedatap);
RtcTime.hours = eedatap;
i2cReceive(0xD0, 0x04, 1, 1, &eedatap);
RtcTime.day = eedatap;
i2cReceive(0xD0, 0x05, 1, 1, &eedatap);
RtcTime.month = eedatap;
i2cReceive(0xD0, 0x06, 1, 1, &eedatap);
RtcTime.year = eedatap + 2000;

Автор:  stanleyhacker [ Сря Дек 12, 2007 6:19 pm ]
Заглавие: 

Ето и путбайт и гетбайт.


UINT i2cPutbyte(u08 b)
{
int i;

for (i=7;i>=0;i--)
{
if ( b & (1<<i) )
I2C_SDL_HI;
else
I2C_SDL_LO; // address bit
I2C_SCL_TOGGLE; // clock HI, delay, then LO
}

I2C_SDL_HI; // leave SDL HI
// added
//cbi(SDADDR, SDA); // change direction to input on SDA line (may not be needed)
//I2C_SDL_HI; // make sure pullups are ativated

HDEL;
I2C_SCL_HI; // clock back up
b = inb(SDAPIN) & (1<<SDA); // get the ACK bit


HDEL;
I2C_SCL_LO; // not really ??
//sbi(SDADDR, SDA); // change direction back to output
HDEL;
return (b == 0); // return ACK value
}


u08 i2cGetbyte(UINT last)
{
int i;
u08 c,b = 0;


cbi(SDADDR, SDA); // change direction to input on SDA line (may not be needed)

for(i=7;i>=0;i--)
{
HDEL;
I2C_SCL_HI; // clock HI
c = inb(SDAPIN) & (1<<SDA);
b <<= 1;
if(c) b |= 1;
HDEL;
I2C_SCL_LO; // clock LO
}


if (last)
I2C_SDL_HI; // set NAK
else
I2C_SDL_LO; // set ACK

I2C_SCL_TOGGLE; // clock pulse
I2C_SDL_HI; // leave with SDL HI
return b; // return received byte
}


#define QDEL us_spin(3); // i2c quarter-bit delay
#define HDEL us_spin(6); // i2c half-bit delay


#define I2C_SDL_LO sbi(SDADDR, SDA)
#define I2C_SDL_HI cbi(SDADDR, SDA)

#define I2C_SCL_LO cbi( SCLPORT, SCL)
#define I2C_SCL_HI sbi( SCLPORT, SCL)

#define I2C_SCL_TOGGLE HDEL; I2C_SCL_HI; HDEL; I2C_SCL_LO;
#define I2C_START I2C_SDL_LO; QDEL; I2C_SCL_LO;
#define I2C_STOP HDEL; I2C_SCL_HI; QDEL; I2C_SDL_HI; HDEL;

дефинетата ще си ги направиш за пик. Напр. sbi(SDADDR, SDA) ти сетва посоката на дата линията която е на крак SDA дефиниран преди това (например крак '0') SDADDR е регистъра за посока на данни на порт SDAPORT, които се дефинират преди това Напр. PORTA i DDRA
освен това да знаеш че разчитам за пулъпа за високо ниво и никога не сетвам дата линията в '1' (само крака го правя вход), така че пулъп няколко колома е задължителен за дата линията, както си е по даташит. SDAPIN е регистъра от който се четат данни когато порта е вход, при пиковетe това го няма, там си четеш от регистъра SDAPORT.

Автор:  the_electronic_m@n [ Сря Дек 12, 2007 6:19 pm ]
Заглавие: 

Забравих да отбележа, че програмката трябва да е на асемблер(далеч съм от С все още). Напреженията ми са ОК-Vcc е 5V, а крачето за батерията е свързано към маса

Автор:  stanleyhacker [ Сря Дек 12, 2007 6:45 pm ]
Заглавие: 

Мисля че ако се зачетеш подробно и няколко пъти ще разбереш алгоритъма и ще видиш къде бъркаш, по-важно е да разбреш начина, програмата е по-лесната част.

Автор:  the_electronic_m@n [ Сря Дек 12, 2007 9:49 pm ]
Заглавие: 

Сега като се зачетох схванах за какво става въпрос, но нещо ме притеснява тази част от кода:


По същия начин четене:

i2cReceive(0xD0, 0x00, 1, 1, &eedatap);
RtcTime.seconds = eedatap;
i2cReceive(0xD0, 0x01, 1, 1, &eedatap);
RtcTime.minutes = eedatap;
i2cReceive(0xD0, 0x02, 1, 1, &eedatap);
RtcTime.hours = eedatap;
i2cReceive(0xD0, 0x04, 1, 1, &eedatap);
RtcTime.day = eedatap;
i2cReceive(0xD0, 0x05, 1, 1, &eedatap);
RtcTime.month = eedatap;
i2cReceive(0xD0, 0x06, 1, 1, &eedatap);
RtcTime.year = eedatap + 2000

При четене не трябва ли контролния байт на RTC-то да е 0xD1?

Автор:  Predator_MF [ Чет Дек 13, 2007 11:16 am ]
Заглавие: 

Обърни внимание на каква честота е I2C-то, не надхвърляй 100KHz иначе няма да работи

Автор:  stanleyhacker [ Чет Дек 13, 2007 11:41 am ]
Заглавие: 

Трябва, да! Но това се прави вътре във функцията i2cReceive.

i2cPutbyte(device | READ); // resend DEVICE, with READ bit set, където READ е 1 и от D0 става D1, "|" e = на лог."OR"

Автор:  Топ [ Чет Дек 13, 2007 6:52 pm ]
Заглавие: 

Чипа си работи без проблеми, вече стотици устройства работят с него и нито с един няма проблеми. Документацията е достатъчно ясна, ако имаш проблеми с това какво да се направи, питай. Мога да извадя процедурата за инициализация, да ти сваля времедиаграми от комуникацията с чипа и т.н. Но конкретно с пик (чета) не се занимавам и не мога да помогна.

Автор:  the_electronic_m@n [ Чет Дек 13, 2007 8:47 pm ]
Заглавие: 

Голямо благодарско на всички, които се отзоваха! Днес най-после всичко тръгна както трябва! :prayer: :supz:

Страница 1 от 1 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/