Ви не увійшли.
Сторінки 1
Коли відточите навички читання/записування сторінок, спробуйте ось цей мій пристрій.
Завдяки вашим посиланням на документацію по DS2450 та Googl-перекладачу, вдалось зрозуміти алгоритми взаємодії між МК та модулем. Особливо закручено було в записі даних в модуль, тільки переклавши з англійської на українську алгоритм виконання команди WRITE MEMORY [55H], вдалось зрозуміти роботу вашої функції "uint8_t write(uint8_t *addr, uint8_t *buf, uint8_t start, uint8_t cnt)" яку ви, люб'язно, надали для ознайомлення.
"Спілкування" з модулем працює, тепер буду, по тихеньку, вивчати/освоювати його функціонал.
Щиро вдячний за поради!
Ага, читав про "емуляцію", але, коли буде потреба, бажання і натхнення, то зможу, під Windows, на Delphi7, написати програму для налаштування DS2423, чи якогось іншого.
Проблема не в пінах МК(сімейство C8051F300...F380 та інші), вони мають толерантність до 5В, а в тому, що напруга джерела живлення схеми не перевищує 4,2В. Бо схема розроблялась коли я ще не знав про ваш модуль і для простоти живлення, вибрав варіант джерела від одного елемента акума. Чому від акума, бо треба було забезпечити автономність контролера, бо датчик з газ.лічильника - геркон і треба було мати постійну можливість його контролювати. Тепер, автономність забезпечує ваш модуль. І потреба в акумі відпадає, але переробляти вже не буду. Ну то таке..., добре що були в наявності мініатюрні модулі DC-DCповишалки.
Ще стикнувся з проблемою...МК контролера 3,2 вольтове, тому живлення відбувається від одного літіонового акума 3,6В, а лінію DQ треба "підвязати" до +5В...звідки взяти? Прийшлось "приліпити" маленьку повишалку(DC-DC 2,5..4,2В --> 5,1В). Добре що в коробочці контролера ще було вільне місце.
Адаптувати програму контролера було легше ніж присобачити модуль DS2423. Получилось ось так....
Доброго дня.
Завершив створення алгоритму читати/писати в сторінки модуля DS2423..., все грає та співає!
В кінцевому варіанті реалізовано всього три функції:
U8 DS2423_getCounters (U8 nomCounters); //зчитую значення лічильника та значення напруги батарейки живлення модуля.
U8 DS2423_ReadRAM_COUNTER (U16 vAdr, U8 vKolB); //зчитую сторінку повністю(vKolB=42), або частково(vKolB<42).
U8 DS2423_WriteRAM (U16 vAdr, U8 *vRAM, U8 vKolB);//запис в сторінку "write_Scratchpad"+"read_Scratchpad"+"copy_Scratchpad".
Тепер залишилось модуль прилаштувати до газового лічильника, підключити до контролера і там модернізувати програму(під цей модуль).
Ще "погрався" з читанням/запису в користувацьку область(24байта) пам'яті модуля...чудово, можна де що зберігати.
Щиро вдячний за допомогу!
Всім здоров'я та вдачі!
Встановив ваші, рекомендовані, таймінги...все Ок! Буду з ними працювати...це ж буде по феншую!
З підрахунком CRC визначився, все "грає та співає" !!!
Вдячний за ваші поради та підказки.
Інтуїтивно розумію, що треба, але про всяк випадок спитаю...
Тепер, коли буду щось писати в сторінку, то теж, в підрахунок CRC включати байти команди та адреса, я правильно розумію?
Так, я вас правильно зрозумів. Якраз з цією паузою(delay_us( 1);) і посилено працював. Через те що мій переносний осцилл не може нормально, на таких тривалостях, працювати, синхронізуватись, я не можу сказати, що вказавши паузу в 1мкс, то вона дійсно буде в 1мкс....підозрюю, що там буде трохи більше і тому протокол працює без проблем. Зараз запущу домашній осцилл і ретельніше все перевірю.
З 2019 року реалізував дома щось типу "розумний дім". Срільнуло мені в голову зробити керування батареями опалення контролерами і показувати їхню роботу на ПК(планшет). Так і зробив і вже 5 років система працює. Контролери батарей мають по три датчики DS18B20(температура кімнати, температура батареї, температура теплотраси) і керує електроклапаном(12В) який то відкриває батарею, то закриває в залежності від заданої температури. Я до чого веду....обкатавши нові таймінги протоколу 1Wire, прописав їх в контролери(7шт) і вже тиждень все працює нормально. Але менш з тим...зараз попробую реалізувати ваші поради.
Напевно, вхід DQ має певну ємність, більша ніж у DS18B20, яка "поволі" заряджається і часу в 5мкс між слотами(старий варіант формування імпульсів), коли лінія звільнена, не встигає досягти +5В. А от коли час між слотами збільшив до 90мкс, то все стало нормально. Да, можна було зменшити опір резистора і можливо все теж стало-б нормальок.
У вас трохи неправильні таймінги.......
Так, я знаю...ви маєте рацію!
Раніше формував їх по специфікації на DS18B20. Тепер, коли "вирівнював" рівні імпульсів, емпірично, підігнав їх до стабільної роботи протоколу. Тобто щоб затримки були мінімально-оптимальні.
При нагоді, ще раз їх перегляну.
Цікаво, цікаво...., планую прикупити ще 3шт ваших DS2423-аналогів і за одно прикуплю парочку модулів розширення портів.
В процесі освоєння модуля DS2423-аналога, виявив те що він чутливий до рівня напруги в шині(використовував паразитне живлення модуля). При "стандартних" формуваннях часових затримок імпульсів для слотів читання/запису, цей модуль, час від часу, перезавантажувався(зчитував 0xFFFFFFFF лічильника), а DS18B20 працював без боїв. Підключивши осциллок, побачив, що є нестабільність, просадка рівня імпульсів, нижче 4,5В(шина підтягнута до +5В резистором 1кОм), через що модуль перезавантажувався. Тоді, "погрався" з тивалостями імпульсів(трохи збільшив) до тих пір щоб рівень був одинакових, що на передачу, що на прийом, і не нижчий за 4,8В. Проблема зникла! Обкатав на кабелі 10м більше доби, збоїв не було.
Може комусь пригодиться, формування сигналів....
#define inBit1Wire(inBit)
LineWire =0; delay_us( 8);
LineWire =1; delay_us( 1);
inBit =LineWire; delay_us(40);
LineWire =1; delay_us(90);
#define ouBit1Wire(ouBit)
LineWire =0; delay_us( 9);
LineWire =ouBit; delay_us(40);
LineWire =1; delay_us(90);
А це були формування "старих" сигналів....
#define inBit1Wire(inBit)
pin_1Wire =0; delay_us(2);
pin_1Wire =1; delay_us(12);
inBit =pin_1Wire; delay_us(70);
pin_1Wire =1; delay_us(5);
#define ouBit1Wire(ouBit)
pin_1Wire =0; delay_us(5);
pin_1Wire =ouBit; delay_us(70);
pin_1Wire =1; delay_us(5);
pin_1Wire - біт порта МК, до якого підєднані датчики.
inBit, ouBit - програмний біт, читання/передачі, які групуються в байти.
Ага, цікаво получається...., не сподівався що ще треба включати в підрахунок код команди та адрес сторінки. Попробую.
Дякую за поради!!!
Взагалі-то мені підрахунок CRC потрібно для того щоб щось прописувати в RAM-сторінки..., готуюсь до таких операцій. Якщо тільки зчитувати лічильники, то можна обходитись і без CRC.
Дуже вдячний за допомогу! Вечерком буду пробувати.
Всім миру та добра.
Працюю з МК Silabs (C8051F310, ...F320, ...F330, ...F340, ...F480) в середовищі "Silicon Labs Simplicity Studio v3 Keil", тому створюю самостійно "бібліотеки" для роботи з різними периферійними модулями. Недавно тут, на arduino.ua магазині, придбав модуль Honey для того щоб зчитувати та зберігати значення газового лічильника.
По даташиту розібрався як зчитувати значення лічильників...
//======================================================================================//
U8 DS2423_getCounters(U8 *vROM, U8 nomCounters)
{
lng xClk;
U8 data vB;
vDS2423_Err=1; //якщо перевірка буде хибна, то помилка 0х01.
if (*vROM!=0xFF) //перевіряю, чи в масиві є S/N.
{ //в масиві є прописаний S/N, тоді...
vDS2423_Err++; //якщо перевірка буде хибна, то помилка 0х02.
if (*vROM==0x1D) //перевіряю, чи це S/N датчиків DS2423.
{ //так, це S/N цих датчиків температури, тоді...
if (lWire_Macth_ROM(vROM)==0) // зброс всіх датчиків і передача S/N потрібного датчика.
{ // якщо вдало, то.....
vDS2423_Err=0; // помилок не має.
lWire_WR(0xA5); // запис команди "READ_MEM_COUNTER"
if (nomCounters==0) lWire_WR(0xC0); // запис молодшого адресу сторінки лічильника "А"
else lWire_WR(0xE0); // ------------------------------------------ "В"
lWire_WR(0x01); // запис старшого адресу сторінки (16 сторінок по 32 байта)
for (vB=0; vB<42; vB++) vArrayRAM[vB]=lWire_RD();// зчитую з датчика в буфер vArrayRAM[], 42 байта.
//........тепер розбираю байти масива vArrayRAM[].....................................................//
// vArrayRAM[ 0]...vArrayRAM[31] - 32 байта RAM-сторінки.
xClk.b[3]=vArrayRAM[32]; // 4 байта
xClk.b[2]=vArrayRAM[33]; // лічильника
xClk.b[1]=vArrayRAM[34]; //
xClk.b[0]=vArrayRAM[35]; //
// vArrayRAM[36]...vArrayRAM[39] - 4 байта з нульовими значеннями.
// vArrayRAM[40]...vArrayRAM[41] - 2 байта CRC.
if (xClk.l==0xFFFFFFFF) vDS2423_Err=2; // помилка зчитування RAM.
else // інакше - все ОК, тоді...
{
vDS2423_Counter.l =xClk.l; // зберігаю значення лічильника та
vDS2423_Bat =((5.0-0.68)*vArrayRAM[24]/256)*1000;// значення батареї живлення DS2423.
}
}
else vDS2423_Err=lWire_Err; // помилка збросу датчиків(0х80-лінія зайнята;0х81-датчики відсутні;0х82-лінія зайнята)
}
}
return(vDS2423_Err);
}
//======================================================================================//
, а от як підраховувати CRC щось ні як не получається.
Допоможіть, будь ласка, з алгоритмом підрахунку CRC, бо сам осилити поліном Х16+Х15+Х2+1 не зможу.
Пробував функцію "DS2423.prototype._check_crc16 = function (buf)" яка є в пост#10 першої сторінки цієї теми, тохи перероблено...
U16 crc16(const U8 * input, U16 len)
{
static const U8 oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
U16 cdata;
U16 xCRC;
U16 iInx;
xCRC=0;
for (iInx = 0 ; iInx < len ; iInx++)
{
// Even though we're just copying a byte from the input, we'll be doing 16-bit computation with it.
cdata = input[iInx];
cdata = (cdata ^ xCRC) & 0xFF;
xCRC >>= 8;
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) xCRC ^= 0xC001;
cdata <<= 6;
xCRC ^= cdata;
cdata <<= 1;
xCRC ^= cdata;
}
return xCRC;
}
щось не те получається.
Знайшов ще таку реалізацію...
U16 CalcCRCbyAlgorithm(U8 * pDataBuffer, U16 usDataLen)
{
/* Use the Modbus algorithm as detailed in the Watlow comms guide */
//const U16 POLYNOMIAL = 0xA001;
const U16 POLYNOMIAL = 0xA001;
U16 wCrc;
U16 iByte, iBit;
/* Initialize CRC */
wCrc = 0xFFFF;
for (iByte = 0; iByte < usDataLen; iByte++)
{
wCrc ^= *(pDataBuffer + iByte); /* Exclusive-OR the byte with the CRC */
for (iBit = 0; iBit <= 7; iBit++) /* Loop through all 8 data bits */
{
/* If the LSB is 1, shift the CRC and XOR the polynomial mask with the CRC */
/* Note - the bit test is performed before the rotation, so can't move the << here */
if (wCrc & 0x0001)
{
wCrc >>= 1;
wCrc ^= POLYNOMIAL;
}
else
{
wCrc >>= 1; /* Just rotate it */
}
}
}
return wCrc;
}
Теж не той результат.
Прошу вашої допомоги.
Наперед...Дякую.
Сторінки 1