|
Датчик DS18B20, Нужен совет |
|
|
|
Sep 16 2010, 03:04
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
to zalg Цитата(zalg @ Sep 15 2010, 23:04)  У меня такая проблема. Писал код "с нуля" на ассемблере, все согласно даташиту. В итоге датчик реагирует, но как то странно. При включении показывает температуру +85 С(0550h в первых двух считанных байтах, затем считывание прекращаю, подавая "ресет" ). Насколько я понял, так и должно быть, НО затем он начинает фиксировать изменения температуры относительно этого значения, как будто калибруется при подаче питания. И еще одна странность - младший бит байта 0 - всегда ноль, т.е. при нагреве (если коснуться датчика пальцами) температура начинает расти так - 0550h,0552h,0554h и т.д. Перепроверял все по нескольку раз, симулировал в Proteus - работает как надо, уже грешу на датчик. Может кто сталкивался? 1. При чтении значения (тем более при первом) необходимо дождаться завершения измерения температуры, но перед этим необходимо подать команду на старт 2. Скажите какой датчик, может у него точность измерения температуры по умолчанию задана с дискретом в один градус? 3. Лучше сделать новый топик! To Letis. Пишу с использованием WinAVR (на AVR-асме не пишу более 5 лет) В одной проге было два ds18s20 на одном порту Вот моя реализация. В вашем случае достаточно переделать макросы onew_input, onew_out_hi, onew_out_lo под большее количество датчиков В ds18s20.h Код #define DS18S_PORT PORTE #define DS18S_DDR DDRE #define DS18S_PIN PINE #define PIN_DS18S_1WR (_BV(2)) #define PIN_DS18S_1RD (_BV(3)) #define PIN_DS18S_2WR (_BV(4)) #define PIN_DS18S_2RD (_BV(5))
#define onew_input(par) (DS18S_PIN & (par ? PIN_DS18S_2RD : PIN_DS18S_1RD)) #define onew_out_hi(par) DS18S_PORT &= ~(par ? PIN_DS18S_2WR : PIN_DS18S_1WR) #define onew_out_lo(par) DS18S_PORT |= (par ? PIN_DS18S_2WR : PIN_DS18S_1WR) В ds18s20.c Код //***************************************************************************** // Layer 1 - Transmit/Receive Bit void onew_set_lo(byte ch) { byte s = SREG; cli(); onew_out_lo (ch); _delay_us (65); onew_out_hi (ch); _delay_us (10); //5 SREG = s; } //============================================================================= void onew_set_hi(byte ch) { byte s = SREG; cli(); onew_out_lo (ch); _delay_us (7); // onew_out_hi (ch); _delay_us (70); // 65 SREG = s; } //============================================================================= byte onew_get_bit(byte ch) { byte t = 0; byte s = SREG; cli(); onew_out_lo (ch); _delay_us (2); onew_out_hi (ch); _delay_us (12); //11 if(onew_input(ch)) t=1; SREG = s; _delay_us (60); //45 return t; } //============================================================================= byte onew_reset(byte ch) { byte t = 0; byte s = SREG; cli(); onew_out_lo (ch); _delay_us (480); onew_out_hi (ch); _delay_us (65); if(!onew_input(ch)) t=1; sei(); SREG = s; _delay_us (415); return t; } //*****************************************************************************
Сообщение отредактировал alexeyv - Sep 16 2010, 03:06
|
|
|
|
|
Sep 16 2010, 08:04
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 19-11-08
Из: Moscow region
Пользователь №: 41 766

|
to zalg: Если младший бит "0", может всё же проверить кофигурационную ячейку разрешения датчика
|
|
|
|
|
Sep 16 2010, 09:20
|
Частый гость
 
Группа: Участник
Сообщений: 124
Регистрация: 10-07-07
Пользователь №: 29 027

|
Цитата и сам не один вариант написал для обмена 1-wire, в том числе и для "многопортового" подключения нескольких датчиков... если надо - поищу исходники - но портировать в CVAVR не буду - это уже самостоятельно вы... Виложите пожалуста код
|
|
|
|
|
Sep 16 2010, 11:42
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(Letis @ Sep 16 2010, 13:20)  Виложите пожалуста код ну как бы вот... комментариев много - разберетесь, надеюсь.
Прикрепленные файлы
MyLib.rar ( 7.79 килобайт )
Кол-во скачиваний: 72
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Sep 17 2010, 09:56
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Letis @ Sep 17 2010, 01:18)  Код несколько не понятен в силу того что пишу в Code Vision. І вот первый вопрос. /// УКАЗАТЕЛЬ НА ПОРТ ВВОДА-ВЫВОДА typedef volatile uint8_t* io_ptr;
ошибка: declaration syntax error. Посмотрите в мануале Code Vision, понимает ли он uint8_t. Если не понимает, то или typedef unsigned char uint8_t; или замените все uint8_t на unsigned char.
|
|
|
|
|
Sep 17 2010, 17:59
|

Местный
  
Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986

|
Для нескольких термометров делал так: Код //---------------------------------------------------------------------------- //--------------------------- Цифровые датчики: ------------------------------ //----------------------------------------------------------------------------
//Используются термометры DS18B20 (S20), которые подключены к портам OWPn. //Считывание и повторный запуск преобразования производится //в момент считывание таходатчика того же канала. //Считываются только два байта температуры, CRC не проверяется. //Суммарное время опроса всех термометров должно быть больше //времени преобразования, т.е. длительность интервала счета тахометра //не должна быть меньше 750 мс / CHANNELS. //Считанное значение температуры заносится в массив Temp[], //температура представлена в десятых долях градуса. //Диапазон возможных температур составляет от TEMP_MIN до TEMP_MAX //градусов. При отсутствии термометра показания равны TEMP_MIN.
//------------------------------- Константы: ---------------------------------
#define OWP0 (1 << PC0) //порт цифрового термометра 0 #define OWP1 (1 << PC1) //порт цифрового термометра 1 #define OWP2 (1 << PC2) //порт цифрового термометра 2 #define OWP3 (1 << PC3) //порт цифрового термометра 3 #define OWP4 (1 << PC4) //порт цифрового термометра 4 #define OWP5 (1 << PC5) //порт цифрового термометра 5 //Направление: #define I_DDRC (0) //Подтягивающие резисторы / начальное состояние: #define I_PORTC (0) //Макроопределения для работы с портами: #define Port_OWP_0(m) (DDRC |= m) #define Port_OWP_Z(m) (DDRC &= ~m) #define Pin_OWP(m) (PINC & m)
//Маски термометров: const __flash char Masks[CHANNELS] = {OWP0, OWP1, OWP2, OWP3, OWP4, OWP5};
//------------------------------- Переменные: --------------------------------
static int Temp[CHANNELS]; //текущая температура static bool Present[CHANNELS]; //флаги присутствия термометров
//---------------------------- Прототипы функций: ----------------------------
void Start(char n); //старт термометра void Read(char n); //чиение термометра void TReset(char n); //генерация импульса сброса char TByte(char n, char dat); //запись/чтение байта bool TBit(char n, bool b); //запись/чтение бита void Do_Crc(char b, char *crc); //вычисление CRC
//------------------ Инициализация измерителя температуры: -------------------
void Therm_Init(void) { ACSR = (1<<ACD); //запрещение аналогового компаратора for(char i = 0; i < CHANNELS; i++) { Temp[i] = TEMP_MIN; //инициализация температуры Start(i); //старт всех термометров } }
//------------------------ Измерение температуры: ----------------------------
void Therm_Exe(char n) { Read(n); //чтение термометра - самое первое измерение Start(n); //старт термометра }
//-------------------------- Старт термометра: -------------------------------
void Start(char n) { TReset(n); //импульс сброса if(Present[n]) { TByte(n, 0xCC); //skip ROM TByte(n, 0x44); //convert T } }
//------------------------- Чтение термометра: -------------------------------
void Read(char n) { if(Present[n]) { TReset(n); //импульс сброса if(Present[n]) { TByte(n, 0xCC); //skip ROM TByte(n, 0xBE); //read scratchpad #ifdef DS18B20 char l = TByte(n, 0xFF); //чтение младшего байта char h = TByte(n, 0xFF); //чтение старшего байта int t = WORD(h, l); //температура с дискретностью 0.0625°C t = (t * 10) / 16; //температура с дискретностью 0.1°C #else char Data[9]; //данные термометра char Crc = 0; //инициализация CRC for(char i = 0; i < 9; i++) { char b = TByte(n, 0xFF); //чтение данных Do_Crc(b, &Crc); //обновление CRC Data[i] = b; //сохранение данных } int t = TEMP_MIN; if(!Crc) { t = WORD(Data[1], Data[0]) / 2; t = (t * 20 - 5 + (int)(Data[7] - Data[6]) * 20 / Data[7]) / 2; } #endif Temp[n] = t; return; } } Temp[n] = TEMP_MIN; //термометр отсутствует return; }
//--------------------- Генерация импульса сброса: ---------------------------
void TReset(char n) { char m = Masks[n]; char si; Present[n] = 0; //сброс флага присутствия термометра Port_OWP_0(m); //OWP <- 0 Delay_us(500); //delay 500 uS si = __save_interrupt(); __disable_interrupt(); //запрещение прерываний Port_OWP_Z(m); //OWP <- 1 Delay_us(14); //delay 14 uS if(Pin_OWP(m)) //если OWP = 0, то ошибка { Delay_us(52); //delay 52 uS if(!Pin_OWP(m)) //если OWP = 1, то ошибка { __restore_interrupt(si); //восстанавление прерываний Delay_us(250); //delay 250 uS if(Pin_OWP(m)) //если OWP = 0, то ошибка { Present[n] = 1; //если ошибок нет, термометр присутствует } } } __restore_interrupt(si); //восстанавление прерываний в случае ошибки }
//-------------- Запись/чтение байта по однопроводной шине: ------------------
char TByte(char n, char dat) { char res; char m = Masks[n]; for(char i = 0; i < 8; i++) { res = res >> 1; if(TBit(m, dat & 1)) res |= 0x80; else res &= ~0x80; dat = dat >> 1; } return(res); }
//--------------- Запись/чтение бита по однопроводной шине: ------------------
bool TBit(char m, bool b) { char si; si = __save_interrupt(); __disable_interrupt(); //запрещение прерываний Port_OWP_0(m); //OWP <- 0 Delay_us(2); //delay 2 uS if(b) Port_OWP_Z(m); //bit = 1, OWP <- 1 Delay_us(13); //delay 13 uS bool owp = Pin_OWP(m); //чтение порта Delay_us(45); //delay 45 uS Port_OWP_Z(m); //OWP <- 1 __restore_interrupt(si); //восстанавление прерываний Delay_us(2); //delay 2 uS return(owp); }
//--------------------- Вычисление контрольной суммы: ------------------------
void Do_Crc(char b, char *crc) { for(char i = 0; i < 8; b = b >> 1, i++) if((b ^ *crc) & 1) *crc = ((*crc ^ 0x18) >> 1) | 0x80; else *crc = (*crc >> 1) & ~0x80; }
--------------------
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|