|
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 ;)
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 20)
|
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 ;)
|
|
|
|
|
Jul 26 2006, 09:15
|

Участник

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

|
Ну вот, купил специально второй датчик для проверок в CodeVision Код #include <mega16.h> // 1 Wire Bus functions #asm .equ __w1_port=0x1B;PORTA .equ __w1_bit=4 #endasm #include <1wire.h> #include <ds18b20.h> #include <stdio.h> void main(void) { // USART initialization UCSRA=0x00; UCSRB=0x08; UCSRC=0x86; UBRRH=0x00; UBRRL=0x0C;
// 1 Wire Bus initialization w1_init(); if (ds18b20_init(NULL,0,0,DS18B20_12BIT_RES)) { while (1) { /* measure and display the temperature(s) */ printf("t=%+.3f\xf8C\n\r", ds18b20_temperature(NULL)); }; } else printf("error!");
while (1); } выдает ошибку на обоих датчиках... от куда беруться такие напряжения (4.28В, см. выше)? Какие есть идеи? Просто схема подключения элементарная, ну где там можно ошибиться....
Сообщение отредактировал Labinskiy Nikolay - Jul 26 2006, 09:15
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 27 2006, 05:13
|

Участник

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

|
Да, через УАРТ, но там ошибок нету, я через гиперткрминал посылаю команды контроллеру на которые он успешно отвечает мигая светодиодами и т.д., и одна из этих команд - опрос датчика... Дебагил по шагам через JTAG ICE и мерял напряжения на ножках... До сих пор не пойму почему там не появляется на выходе 0...
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
|
Jul 27 2006, 05:45
|
Участник

Группа: Свой
Сообщений: 34
Регистрация: 26-07-06
Пользователь №: 19 098

|
Код /* Multipoint thermometer with LCD display using the Maxim DS18B20 1 Wire bus temperature sensors
CodeVisionAVR C Compiler (C) 2000-2005 HP InfoTech S.R.L. www.hpinfotech.ro
Chip: ATmega8515 Memory Model: SMALL Data Stack Size: 128 bytes THE ATmega8515 CLOCK FREQUENCY MUST BE 3.6864 MHz
The DS18B20 sensors are connected to bit 6 of PORTA of the ATmega8515 as follows:
[DS18B20] [STK500 PORTA HEADER] 1 GND - 9 GND 2 DQ - 7 PA6 3 VDD - 10 +5V
All the temperature sensors must be connected in parallel AN 4.7k PULLUP RESISTOR MUST BE CONNECTED BETWEEN DQ (PA6) AND +5V ! */ #asm .equ __w1_port=0x1b .equ __w1_bit=6 #endasm
/* Use an 2x16 alphanumeric LCD connected to PORTC as follows:
[LCD] [STK500 PORTC HEADER] 1 GND- 9 GND 2 +5V- 10 VCC 3 VLC- LCD contrast control voltage 0..1V 4 RS - 1 PC0 5 RD - 2 PC1 6 EN - 3 PC2 11 D4 - 5 PC4 12 D5 - 6 PC5 13 D6 - 7 PC6 14 D7 - 8 PC7 */
#asm .equ __lcd_port=0x15 #endasm
#include <lcd.h> // LCD driver routines #include <ds18b20.h> #include <delay.h> #include <stdio.h>
char lcd_buffer[33];
/* maximum number of DS18B20 connected to the 1 Wire bus */ #define MAX_DEVICES 8
/* DS18B20 devices ROM code storage area */ unsigned char rom_code[MAX_DEVICES][9];
main() { unsigned char i,j,devices;
lcd_init(16); lcd_putsf("CodeVisionAVR\n1 Wire Bus Demo"); delay_ms(2000); lcd_clear();
/* detect how many DS18B20 devices are connected to the 1 Wire bus */ devices=w1_search(0xf0,rom_code); sprintf(lcd_buffer,"%u DS18B20\nDevice detected",devices); lcd_puts(lcd_buffer); delay_ms(2000);
/* display the ROM codes for each device */ if (devices) { for (i=0;i<devices;i++) { sprintf(lcd_buffer,"Device #%u ROM\nCode is:",i+1); lcd_clear(); lcd_puts(lcd_buffer); delay_ms(2000); lcd_clear(); for (j=0;j<8;j++) { sprintf(lcd_buffer,"%02X ",rom_code[i][j]); lcd_puts(lcd_buffer); if (j==3) lcd_gotoxy(0,1); }; delay_ms(5000); }; } else while (1); /* stop here if no devices were found */
/* configure each DS18B20 device for 12 bit temperature measurement resolution */ for (i=0;i<devices;) if (!ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES)) { sprintf(lcd_buffer,"Init error for\ndevice #%u",i); lcd_clear(); lcd_puts(lcd_buffer); while (1); /* stop here if init error */ };
/* measure and display the temperature(s) */ while (1) { j=1; for (i=0;i<devices;i++) { sprintf(lcd_buffer,"t%u=%+.3f\xdfC",j++,ds18b20_temperature(&rom_code[i][0])); lcd_clear(); lcd_puts(lcd_buffer); delay_ms(500); }; }; } У меня вот этот пример из кодевижена работает. Посмотрите на эту строчку (!ds18b20_init(&rom_code[i++][0],20,30,DS18B20_12BIT_RES)) Вроду нада поискать датччики и определмить их адрес, ну уж потом делать инит
|
|
|
|
|
Jul 27 2006, 17:06
|

Участник

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

|
Цитата Вроду нада поискать датччики и определмить их адрес, ну уж потом делать инит Это если на 1wire шине их несколько, если же датчик один, его поиск (чтение заводского ROM кода) не обязателен. Но я все равно проверю, спасибо.
--------------------
If you can't make it good - don't make it look good ;)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|