|
DS18B20 + WinAVR, не инициализируется датчик :( |
|
|
|
Jul 22 2006, 07:20
|

Участник

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606

|
DQ подтянут 4к7 на +5 вольт. Датчик один, питание полное(на датчик тоже идет +5В) Код #include <avr/io.h> #include <avr/eeprom.h> #include <inttypes.h> #include <stdio.h> #include <string.h>
#define F_CPU 1000000UL // 1 MHz #include <util/delay.h>
void delay_us(uint16_t t) { int i; if (t > 10) for (i=0;i<t/10;i++) _delay_us(10); else _delay_us(t); }
void delay_ms(uint16_t t) { int i; if (t > 10) for (i=0;i<t/10;i++) _delay_ms(10); else _delay_ms(t); }
int ds_reset() { int r=0; PORTA &= ~(1<<4); DDRA |= (1<<4); // DQ = 0; delay_us(500); // 480us minimum DDRA &= ~(1<<4); // DQ in delay_us(80); // waits 15-60us and then r = (PINA & (1<<4)); // capture the presence pulse (60-240us) delay_us(400); return !r; } все время возвращает 0. В чем может быть проблема? Если в датчике то как его можно быстро и просто проверить?
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 22 2006, 09:24
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Labinskiy Nikolay @ Jul 22 2006, 11:20)  DQ подтянут 4к7 на +5 вольт. Датчик один, питание полное(на датчик тоже идет +5В) Код #include <avr/io.h> #include <avr/eeprom.h> #include <inttypes.h> #include <stdio.h> #include <string.h>
#define F_CPU 1000000UL // 1 MHz #include <util/delay.h>
void delay_us(uint16_t t) { int i; if (t > 10) for (i=0;i<t/10;i++) _delay_us(10); else _delay_us(t); }
void delay_ms(uint16_t t) { int i; if (t > 10) for (i=0;i<t/10;i++) _delay_ms(10); else _delay_ms(t); }
int ds_reset() { int r=0; PORTA &= ~(1<<4); DDRA |= (1<<4); // DQ = 0; delay_us(500); // 480us minimum DDRA &= ~(1<<4); // DQ in
delay_us(80); // waits 15-60us and then
r = (PINA & (1<<4)); // capture the presence pulse (60-240us) delay_us(400); return !r; } все время возвращает 0. В чем может быть проблема? Если в датчике то как его можно быстро и просто проверить? Проблема в 80 мкс задержке. В даташитах на ванварь черным по английски сказано: Presence Detect Sample Time tMSP min=60us, max=75usсо сноской: Note 1: System requirement.В функции delay_us не учитываются задержки на вызов и возврат из функции. Это делает ее совершенно бессмысленной для задержек менее 10 мкс и относительно разумной для задержек менее 30-40 мкс при F_CPU 1000000UL.
Сообщение отредактировал xemul - Jul 22 2006, 09:25
|
|
|
|
|
Jul 22 2006, 09:43
|

Участник

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606

|
Цитата(xemul @ Jul 22 2006, 12:24)  Проблема в 80 мкс задержке. В даташитах на ванварь черным по английски сказано: Presence Detect Sample Time tMSP min=60us, max=75us со сноской: Note 1: System requirement.
В функции delay_us не учитываются задержки на вызов и возврат из функции. Это делает ее совершенно бессмысленной для задержек менее 10 мкс и относительно разумной для задержек менее 30-40 мкс при F_CPU 1000000UL.
Как тогда корректно делать задержки?
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 22 2006, 09:54
|

Профессионал
    
Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380

|
Цитата Как тогда корректно делать задержки? Прерыванием. Еще частота низковата 1МГц - 1(2)мкс на команду, 5-7 команд на процедуру, тут дай бог на асме уложиться.
--------------------
Вони шукають те, чого нема, Щоб довести, що його не існує.
|
|
|
|
|
Jul 22 2006, 10:22
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(Labinskiy Nikolay @ Jul 22 2006, 11:20)  Код #include <avr/io.h>
void delay_us(uint16_t t) int i; if (t > 10) for (i=0;i<t/10;i++) _delay_us(10); else _delay_us(t); }
} В этой функции 2 ошибки: 1. Вы используете деление в цикле: "for (i=0;i<t/10;i++)", на эту операцию требуеться примернр 200 циклов (AVR200: Multiply and Divide Routines). Следовательно вы получаете дополнительную задежку в 200us к каждым 10. 2. _delay_us(t); -так нельзя. Используйте '_delay_us' (и '_delay_мs') только с константами, или вы получите дополнительную задежку на несколько операций с плавуещей точкой: Код \note When using _delay_us() and _delay_ms(), the expressions passed as arguments to these functions shall be compile-time constants, otherwise the floating-point calculations to setup the loops will be done at run-time, thereby drastically increasing both the resulting code size, as well as the time required to setup the loops. В вашем случае вы можете применять '_delay_us' для задежек до 768us. Читайте описание '_delay_us'. Анатолий.
Сообщение отредактировал aesok - Jul 22 2006, 10:37
|
|
|
|
|
Jul 22 2006, 10:31
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Labinskiy Nikolay @ Jul 22 2006, 13:43)  Цитата(xemul @ Jul 22 2006, 12:24)  Проблема в 80 мкс задержке. В даташитах на ванварь черным по английски сказано: Presence Detect Sample Time tMSP min=60us, max=75us со сноской: Note 1: System requirement.
В функции delay_us не учитываются задержки на вызов и возврат из функции. Это делает ее совершенно бессмысленной для задержек менее 10 мкс и относительно разумной для задержек менее 30-40 мкс при F_CPU 1000000UL.
Как тогда корректно делать задержки? Извините, не посмотрел, что для датчиков температуры ворота по Presence Pulse гораздо шире, чем для iButton. Тем не менее, если программу написать под стандартные тайминги для iButton, она будет работать и с остальными ванварными девайсами. Посмотрите AN126.pdfЯ делал задержки более 70 мкс кратными этим самым 70 мкс (т.е., н-р, сброс = 7*70) и отрабатывал их по 70-мкс таймерному прерыванию. Мелкие задержки при Fclk=1MHz приходилось делать nop'ами, goto $+1 (синтаксис PIC'ов) и циклами ожидания.
|
|
|
|
|
Jul 22 2006, 11:04
|

Участник

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606

|
Цитата(virtuality @ Jul 22 2006, 13:11)  Вставлю свою лепту - у меня, да и судя по постам у других людей на форуме была проблема с датчиком из-за того, что контроллер работал на внутреннем RC-генераторе на частоте 1 МГц, а программа была настроена на 8 МГц. Зажгите светодиод на 1 секунду, и проверьте, соответствует ли... все ок aesok, xemul, спасибо.
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 22 2006, 11:27
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Labinskiy Nikolay @ Jul 22 2006, 15:04)  все ок И это здОрово  . Кста, длительность Presence Pulse и время выборки все-таки одинаковы для всех ванварных девайсов для стандартной скорости обмена: Presence Detect High Time 15-60 us Presence Detect Low Time 60-240 us Presence Detect Sample Time 60-75 us
|
|
|
|
|
Jul 22 2006, 11:55
|

Участник

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606

|
вот что получилось: Код #include <avr/io.h> #include <avr/eeprom.h> #include <inttypes.h> #include <stdio.h> #include <string.h>
#define F_CPU 1000000UL // 1 MHz #include <util/delay.h>
void delay_ms(uint16_t t) { uint8_t i; if (t > 10) for (i=0;i<t/10;i++) _delay_ms(10); else _delay_ms(t); }
int ds_reset() { uint8_t r=0; PORTA &= ~(1<<4); DDRA |= (1<<4); // DQ = 0; _delay_us(480); DDRA &= ~(1<<4); // DQ pull up _delay_us(70); r = (PINA & (1<<4)); // Capture the presence pulse _delay_us(410); return !r; }
void ds_write_bit(uint8_t b) { if (b) { PORTA &= ~(1<<4); DDRA |= (1<<4); // DQ = 0; _delay_us(6); DDRA &= ~(1<<4); // DQ pull up _delay_us(64); } else { PORTA &= ~(1<<4); DDRA |= (1<<4); // DQ = 0; _delay_us(60); DDRA &= ~(1<<4); // DQ pull up _delay_us(10); }; }
uint8_t ds_read_bit() { uint8_t r=0; PORTA &= ~(1<<4); DDRA |= (1<<4); // DQ = 0; _delay_us(6); DDRA &= ~(1<<4); // DQ pull up _delay_us(9); r = (PINA & (1<<4)); _delay_us(55); if (r) return 1; else return 0; }
void ds_write_byte(uint8_t data) { uint8_t loop; // Loop to write each bit in the byte, LS-bit first for (loop = 0; loop < 8; loop++) { ds_write_bit(data & 0x01); // shift the data byte for the next bit data >>= 1; } }
uint8_t ds_read_byte() { uint8_t loop, result=0; for (loop = 0; loop < 8; loop++) { // shift the result to get it ready for the next bit result >>= 1; // if result is one, then set MS bit if (ds_read_bit()) result |= 0x80; } return result; }
int16_t ds_read_temperature() { int16_t r = -1; int i; uint8_t buf[9]={0};
if (ds_reset()) { ds_write_byte(0xCC); //Skip ROM command ds_write_byte(0x44); //Convert T command delay_ms(1000); // lame :) ds_write_byte(0xBE); //Read Scratchpad for (i=0; i < 10; i++) buf[i] = ds_read_byte(); r = (buf[0] | (buf[1] << 8)) >> 4;
}; return r; } но инициализация все равно не проходит... может что-то с датчиком?
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 22 2006, 14:05
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Labinskiy Nikolay @ Jul 22 2006, 15:55)  вот что получилось: [skipped] но инициализация все равно не проходит... может что-то с датчиком? Вряд ли. На сайте господина protoss'а лежат его сорцы для борьбы с ванварью: 1Wire.C1Wire.Asmза что ему большое спасибо. Я на AVR только переползаю и пока не владею особенностями генерации кода компиляторами для этой архитектуры. Тем не менее, общие соображения: 1) посмотрите ассемблерный текст и вручную посчитайте время выполнения/выполните профилирование по ванварным функциям. 2) если в программе используются прерывания, на время выполнения коротких задержек и связанных с ними манипуляций со входами/выходами их придется запрещать. И для упрощения жизни компилятору и контроллеру я бы сделал так: Код void delay_ms(uint16_t t) { uint8_t i; if (t > 10) for (i=t/10;i;i--) _delay_ms(10); else _delay_ms(t); } или так Код void delay_ms(uint16_t t) { uint8_t i; if (t >= 256) { for (i=t/256;i;i--) _delay_ms(256); t &= 255; } _delay_ms(t); }
Сообщение отредактировал xemul - Jul 22 2006, 14:07
|
|
|
|
|
Jul 22 2006, 15:03
|

Участник

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606

|
Спасибо за ссылки, ну а delay_ms у меня только и осталась чтобы сделать одну большую задержку на ~1 секунду, ну а где нужно поточнее использовал _delay_us(const)... З.Ы. прерывания не используются...
Сообщение отредактировал Labinskiy Nikolay - Jul 22 2006, 15:07
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 25 2006, 18:20
|

Участник

Группа: Новичок
Сообщений: 27
Регистрация: 5-07-06
Из: Украина, Донецк
Пользователь №: 18 606

|
Ничего не понимаю... PORTA.4(нумерация с нуля) Mega16(внутренний 1 МГц) подключон через 4к7 к +5 и от туда же (прямо от порта перед резистором) подключон DQ DS18B20, еще две ножки датчика подключены на +5 и землю (непаразитное питание).. Ошибок в схеме вроде нету, но вот на этом коде оч странные напряжения на выходе порта (меряю между землей и ножкой порта) Код int ow_reset() { uint8_t r=0; PORTA &= ~(1<<4); // +4.95В DDRA |= (1<<4); // DQ = 0; r = (PORTA & (1<<4)); //+4.28В как такое может быть??? _delay_us(480); DDRA &= ~(1<<4); // DQ pull up _delay_us(70); r = (PORTA & (1<<4)); // Capture the presence pulse _delay_us(410); return r; // +4.95В } как такое возможно?
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|