реклама на сайте
подробности

 
 
> DS18b20 неправильно показывает температуру, Когда работает софтовый USB(от obdev)
Br.Misha
сообщение Nov 5 2009, 14:02
Сообщение #1


Местный
***

Группа: Validating
Сообщений: 253
Регистрация: 21-12-08
Пользователь №: 42 646



Здраствуйте!
Вобщем хочу я сделать USB термомерт используя мегу8 и DS18b20. Вобщем написал програмку, а когда запустил то по USB(CDC) начали приходить неверные данные с термометра, сначала грешил на DS18b20 но когда подключил его к другому девайсу то он там работал нормально. Потом я отключил USB (в самом коде) и отправлял даные с датчика на UART, на компе было видно реальную температуру. Дальше я написал программу так, чтобы юсб был включен но даные передавались на ЮАРТ и тут ошибка повториласьsad.gif
Вобщем насколько я понял, то комп постоянно отправляет даные на мегу8 и очень часто вызываеться прерывание по INT0 даже тогда, когда меряеться температура а так как задержки между отправкой и приемом команд к DS маленькие, несколько микросекунд(хотя задержка для измерения температуры датчиком минимум 750мс) то или при отправке комманды долго передается бит и DS перезагружаеться, или когда принимаються то МК невовремя реагирует на комманды и получает неправильные данные. Пробовал отключать глобольно прерывания(cli) перед измерением температуры и включать(sei) после измерения но тогда МК вообще не шлет даные по ЮСБ и не отвечает на комманды с ЮСБ(например когда отправляю "1" то он должен прислать "one", 2 - "two") . Ещё пробовал делать так:
------- отключил прерывания перед отправкой комманд к DS чтобы он измерил температуру.
------- включил после этих комманд потому что далее должна быть задержка 800мс.
------- спустя 800 мс отключал, отправлял комманду чтения температуры, когда он присылал даные опять включал
------- эфект тот же!

Кароче мне нада сделать так,чтобы как то отключать ЮСБ на время измерения температуры ну или ещё что нибутьsmile.gif.

Частота 12Мгц, питание от ЮСБ. Вот клавный файл и библиотека для измерения температуры которую я скачал с инета, немного переделал после чего она работает отлично, правда тока на 1 датчик http://upwap.ru/619341 .

Заранее спасиба!!!!!!!

вот кстате те самые даные с термометра:

+031.1
+125.7
+127.5
+031.3
+023.7
-000.7
+127.1
+021.3
+031.1
-000.7
-000.7
-000.7
-000.7
-000.7
+125.7
-000.7
-000.7
+119.7
+063.7
-000.7
-000.7
+125.6
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 14)
Андрей Лютько
сообщение Nov 5 2009, 14:43
Сообщение #2





Группа: Участник
Сообщений: 6
Регистрация: 26-09-07
Пользователь №: 30 853



Во время чтения/записи данных по шине 1-Wire yужно запрещать прерывания на время tREC+tRDV (см. документацию на DS18b20). В течение этого промежутка времени данные спокойно пишутся/читаются с шины. У меня нижеприведенный код вполне успешно работает совместно с прерываниями и проблем нет.

CODE
#include <iom168.h>
//#include <inavr.h>
#include <ina90.h>
#include "OneWire.h"

#define _1W_CLK 8000000
#define _1W_TKSPer10uS _1W_CLK/100000
#define MILLION 1000000
#define tRSTL 48*_1W_TKSPer10uS //480uS
#define tPDH 65*_1W_CLK/MILLION //65uS
#define tRSTH tRSTL-tPDH
#define tSAMPLE 12*_1W_CLK/MILLION
#define tSLOT 12*_1W_TKSPer10uS //120uS
#define tLOW1 0*_1W_CLK/MILLION //3uS
#define t1uS 1*_1W_CLK/MILLION //3uS
#define tLOW0 10*_1W_TKSPer10uS //120uS
#define tREC 7*_1W_CLK/MILLION //7uS

//==================================================================
//Выходы 1Wire
//1Wire port/ SCK ( D INPUT/OUTPUT)
#define OWIREIOOUT DDRC|=(1<<2)
#define OWIREIOIN DDRC&=~(1<<2)
#define OWIREIOH PORTC|=(1<<2)
#define OWIREIOL PORTC&=~(1<<2)
#define OWIRE (PINC&(1<<2))


//==================================================================
//1wire atmega DRIVERS
//
//-------------------------------------------------------------------------
//This procedure calculates the cumulative Dallas Semiconductor 1ЦWire CRC of all bytes passed to it. The result
//accumulates in the global variable CRC.
unsigned char CRC8(unsigned char inData, unsigned char seed)
{//from AVR318
unsigned char bitsLeft;
unsigned char temp;

for (bitsLeft = 8; bitsLeft > 0; bitsLeft--)
{
temp = ((seed ^ inData) & 0x01);
if (temp == 0)
{
seed >>= 1;
}
else
{
seed ^= 0x18;
seed >>= 1;
seed |= 0x80;
}
inData >>= 1;
}
return seed;
}
//-------------------------------------------------------------------------
//Сброс устройств на шине 1W и чтение Presence Pulse
// Возврат 0- ничего нет
// 1- Есть устройство
// 2- Линия в КЗ
char Reset1W(void)
{
OWIREIOOUT;
__disable_interrupt();
OWIREIOL;
__delay_cycles(tRSTL);
OWIREIOH;
OWIREIOIN;
__delay_cycles(tPDH);
if(!OWIRE)
{ __enable_interrupt();
__delay_cycles(tRSTL);
if(OWIRE)
{ return 1;//Presence pulse
}//if(OWIRE)
else
return 2;//Short circuit
}
__enable_interrupt();
__delay_cycles(tRSTL);
return 0;//Nothing
}
//-------------------------------------------------------------------------
//Проверка наличия 1W устройства
char Check1W(void)
{
if(Reset1W()==1)
{ __delay_cycles(tRSTL);
if(Reset1W()==1)
return 1;
}
return 0;
}
//-------------------------------------------------------------------------
//Передача данных по шине 1Wire
void Write1W(char d)
{ char i;
OWIREIOOUT;
for(i=0;i<8;i++)
{ __disable_interrupt();
OWIREIOL;
__delay_cycles(tLOW1);
if(d&1)
{ OWIREIOH;
__delay_cycles(tSLOT);
}
else
{ __delay_cycles(tLOW0);
OWIREIOH;
}
__enable_interrupt();
__delay_cycles(tREC);
d=d>>1;
}
OWIREIOIN;
}
//-------------------------------------------------------------------------
//Прием данных по шине 1WIRE
char Read1W(void)
{ char i,d=0;
for(i=0;i<8;i++)
{ OWIREIOOUT;
d=d>>1;
__disable_interrupt();
OWIREIOL;
__delay_cycles(t1uS);
OWIREIOH;
OWIREIOIN;
__delay_cycles(tSAMPLE);
if(OWIRE)
d|=0x80;
__enable_interrupt();
__delay_cycles(tSLOT);//tRELEASE 30uS
}
return d;
}

//---------------------------------------------------------------------------
void StartT(char BusNo)//запуск измерения температуры по одной из шин
{ Reset1W();
Write1W(SKIPROM);
Write1W(CONVERTT);
}

//---------------------------------------------------------------------------
float GetT18B20(char *x)//Считывание температуры с датчиков DS18B20,DS1822
{ char i,crc=0;
int j;
char *p;
if(Reset1W()!=1)
return -100;//Нет такого датчика
p=x;
// Write1W(SKIPROM);
Write1W(MATCHROM);
for(i=0;i<8;i++)
{ //OutChar(*p);
Write1W(*p++);//Передача 8 байт адреса
}
Write1W(READSCRATCHPAD);
p=x;
for(i=0;i<8;i++)
{ *p=Read1W();
crc=CRC8(*p,crc);
//OutChar(*p);
*p++;
}
if(Read1W()!=crc)
return -101;//CRC error
p=x;
j=p[1]<<8;
j|=p[0];
return (float)j/16.0;
}

//---------------------------------------------------------------------------
float GetT18S20(char *x)//Считывание температуры с датчика DS18S20
{ char i,crc=0;
int j;
char *p=x;
if(Reset1W()!=1)
return -100;//Нет такого датчика
Write1W(SKIPROM);
// for(i=0;i<8;i++)
// Write1W(*p++);//Передача 8 байт адреса
Write1W(READSCRATCHPAD);
p=x;
for(i=0;i<8;i++)
{ *p=Read1W();
crc=CRC8(*p,crc);
*p++;
}
if(Read1W()!=crc)
return -101;//CRC error
p=x;
j=p[0];
return (float)j/2.0;
}

Код же с http://upwap.ru/619341 абсолютно не имеет никаких критических секций и правильно работать в системе с прерываниями без модификации не будет.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 5 2009, 14:44
Сообщение #3


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Br.Misha @ Nov 5 2009, 18:02) *
Ещё пробовал делать так:
------- отключил прерывания перед отправкой комманд к DS чтобы он измерил температуру.
------- включил после этих комманд потому что далее должна быть задержка 800мс.
------- спустя 800 мс отключал, отправлял комманду чтения температуры, когда он присылал даные опять включал
------- эфект тот же!

Надо это все проделать на "молекулярном уровне" - перед приемом/передачей каждого битика отключать прерывания, затем сразу же включать. Получится прозрачно.
Go to the top of the page
 
+Quote Post
Br.Misha
сообщение Nov 5 2009, 15:56
Сообщение #4


Местный
***

Группа: Validating
Сообщений: 253
Регистрация: 21-12-08
Пользователь №: 42 646



вобщем сделал на "молекулярном уровне":

CODE
#include "therm_ds18b20.h"
#include "ascii_conv.h"
#include <avr/interrupt.h>

volatile char THERM_DQ = 0;
/*
void therm_delay(uint16_t delay)
{
while(delay--) asm volatile("nop");
}
*/

uint8_t therm_reset()
{
uint8_t i;
//Pull line low and wait for 480uS
cli();
ds_cbi(THERM_PORT,THERM_DQ);
ds_sbi(THERM_DDR,THERM_DQ);
sei();
_delay_us(480);
cli();
//Release line and wait for 60uS
ds_cbi(THERM_DDR,THERM_DQ);
sei();
_delay_us(60);
//Store line value and wait until the completion of 480uS period
cli();
i=(THERM_PIN & (1<<THERM_DQ));
sei();
_delay_us(420);
//Return the value read from the presence pulse (0=OK, 1=WRONG)
return i;
}

void therm_write_bit(uint8_t bit)
{
//Pull line low for 1uS
cli();
ds_cbi(THERM_PORT,THERM_DQ);
ds_sbi(THERM_DDR,THERM_DQ);
_delay_us(1);
//If we want to write 1, release the line (if not will keep low)
if(bit) ds_cbi(THERM_DDR,THERM_DQ);
//Wait for 60uS and release the line
sei();
_delay_us(60);
ds_cbi(THERM_DDR,THERM_DQ);
}

uint8_t therm_read_bit(void)
{
uint8_t bit=0;
cli();
//Pull line low for 1uS
ds_cbi(THERM_PORT,THERM_DQ);
ds_sbi(THERM_DDR,THERM_DQ);
_delay_us(1);
//Release line and wait for 14uS
ds_cbi(THERM_DDR,THERM_DQ);
_delay_us(14);
//Read line value
if(THERM_PIN&(1<<THERM_DQ)) bit=1;
//Wait for 45uS to end and return read value
_delay_us(45);
sei();
return bit;
}

uint8_t therm_read_byte(void)
{
uint8_t i=8, n=0;
cli();
while(i--)
{
//Shift one position right and store read value
n>>=1;
n|=(therm_read_bit()<<7);
}
sei();
return n;
}

void therm_write_byte(uint8_t byte)
{
uint8_t i=8;
cli();
while(i--)
{
//Write actual bit and shift one position right to make the next bit ready
therm_write_bit(byte&1);
byte>>=1;
}
sei();
}

void therm_read_temperature(char *buffer, volatile char PIN_DS)
{
THERM_DQ = PIN_DS;
// Buffer length must be at least 12bytes long! ["+XXX.XXXX C"]
uint8_t temperature[2];
// uint16_t temper_16bit;
int8_t digit;
uint16_t decimal;
//Reset, skip ROM and start temperature conversion
therm_reset();
therm_write_byte(THERM_CMD_SKIPROM);
therm_write_byte(THERM_CMD_CONVERTTEMP);
//Wait until conversion is complete
//while(!therm_read_bit());
_delay_ms(750);
//Reset, skip ROM and send command to read Scratchpad
therm_reset();
therm_write_byte(THERM_CMD_SKIPROM);
therm_write_byte(THERM_CMD_RSCRATCHPAD);
//Read Scratchpad (only 2 first bytes)
temperature[0]=therm_read_byte();
temperature[1]=therm_read_byte();
therm_reset();
//Store temperature integer digits and decimal digits
digit=temperature[0]>>4;
digit|=(temperature[1]&0x07)<<4;
//Store decimal digits
decimal=temperature[0]&0xf;
decimal*=5;
if (temperature[1]>0xFB)
{
digit = 127-digit;
buffer[0] = '-';
} else buffer[0] = '+';



buffer[1] = to_ascii(digit/100);
buffer[2] = to_ascii((digit%100)/10);
buffer[3] = to_ascii(digit%10);
buffer[4] = '.';
buffer[5] = to_ascii((decimal%100)/10);

}


юсб опять не отвечает на комманды sad.gif но компом распознаеться.
Андрей, а вы пробовали вашу либу совместно с драйвером obdev?
Причина редактирования: Общирные не оформленные исходные тексты
Go to the top of the page
 
+Quote Post
Br.Misha
сообщение Nov 5 2009, 19:06
Сообщение #5


Местный
***

Группа: Validating
Сообщений: 253
Регистрация: 21-12-08
Пользователь №: 42 646



Мужики, ну помогите, мож тут ещё че не так? Я уже и кварц на 16МГц ставил а оно всеравно не работаетsad.gif
Go to the top of the page
 
+Quote Post
Андрей Лютько
сообщение Nov 5 2009, 20:57
Сообщение #6





Группа: Участник
Сообщений: 6
Регистрация: 26-09-07
Пользователь №: 30 853



C OBDEV не использовал.
В файле usbdrvasm есть строка - "max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable". Судя по всему, максимально допустимое время с запрешёнными прерываниями - 25 тактов.
На мой взгляд, совместить OBDEV и 1-Wire очень тяжело. Разноси эти задачи по двум микроконтроллерам smile.gif
Go to the top of the page
 
+Quote Post
xemul
сообщение Nov 5 2009, 21:00
Сообщение #7



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Br.Misha @ Nov 5 2009, 22:06) *
мож тут ещё че не так?

Попробуйте нарисовать ванварный мастер как конечный автомат на прерываниях - внешнему по спаду и от (8-битного) таймера. Естесно, без delayxxx().
(хинт: у мастера 3 операции - сброс, чтение и запись, операции состоят соответственно из 3, 3 и 2 фаз. Всё это легко помещается в 1 байт и отрабатывается computational goto)
С 12 МГц клоком можно позволить себе не зависать в прерывании по спаду даже на 6 или 9 мкс (при чтении с шины), а отрабатывать их (6 и 9 мкс) таймером.
Когда всё с ванварью получится, добавьте obdev usb.
Заведите программный таймер на интервал, меньший интервала опроса по usb, как признак разрешения обмена по ванвари, и перезапускайте его по окончании обмена по usb.
Заведите программный таймер на интервал, равный или больший времени преобразования DS1820, и перезапускайте его по запуску преобразования.
Цитата
Я уже и кварц на 16МГц ставил а оно всеравно не работаетsad.gif

И не должно. Читайте доки от obdev.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 5 2009, 21:10
Сообщение #8


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Br.Misha @ Nov 5 2009, 19:56) *
вобщем сделал на "молекулярном уровне":

Ничего Вы не сделали, либо совсем ничего не поняли. Зачем Вы наглухо запрещаете прерывания, в функциях therm_read_byte() и therm_write_byte() ??? Так Вы совсем надолго отключаете УСБ.
Go to the top of the page
 
+Quote Post
Br.Misha
сообщение Nov 6 2009, 01:02
Сообщение #9


Местный
***

Группа: Validating
Сообщений: 253
Регистрация: 21-12-08
Пользователь №: 42 646



фух блин...... переделал код но опять не работает...... вот что я написал:

CODE
#include <avr/io.h>
#include "therm_ds18b20.h"
#include "ascii_conv.h"

volatile char THERM_DQ = 0;
/*
void therm_delay(uint16_t delay)
{
while(delay--) asm volatile("nop");
}
*/

uint8_t therm_reset()
{
uint8_t i;
//Pull line low and wait for 480uS
ds_cbi(THERM_PORT,THERM_DQ);
ds_sbi(THERM_DDR,THERM_DQ);
//_delay_us(480);
TCNT1 = 0;
while(TCNT1<(480*12));
//Release line and wait for 60uS
ds_cbi(THERM_DDR,THERM_DQ);
//_delay_us(60);
TCNT1 = 0;
while(TCNT1<(60*12));
//Store line value and wait until the completion of 480uS period
i=(THERM_PIN & (1<<THERM_DQ));
//_delay_us(420);
TCNT1 = 0;
while(TCNT1<(420*12));
//Return the value read from the presence pulse (0=OK, 1=WRONG)
return i;
}

void therm_write_bit(uint8_t bit)
{
//Pull line low for 1uS
ds_cbi(THERM_PORT,THERM_DQ);
ds_sbi(THERM_DDR,THERM_DQ);
//_delay_us(1);
TCNT1 = 0;
while(TCNT1<12);
//If we want to write 1, release the line (if not will keep low)
if(bit) ds_cbi(THERM_DDR,THERM_DQ);
//Wait for 60uS and release the line
//_delay_us(60);
TCNT1 = 0;
while(TCNT1<(60*12));
ds_cbi(THERM_DDR,THERM_DQ);
}

uint8_t therm_read_bit(void)
{
uint8_t bit=0;
//Pull line low for 1uS
ds_cbi(THERM_PORT,THERM_DQ);
ds_sbi(THERM_DDR,THERM_DQ);
//_delay_us(1);
TCNT1 = 0;
while(TCNT1<12);
//Release line and wait for 14uS
ds_cbi(THERM_DDR,THERM_DQ);
//_delay_us(14);
TCNT1 = 0;
while(TCNT1<(14*12));
//Read line value
if(THERM_PIN&(1<<THERM_DQ)) bit=1;
//Wait for 45uS to end and return read value
//_delay_us(45);
TCNT1 = 0;
while(TCNT1<(45*12));
return bit;
}

uint8_t therm_read_byte(void)
{
uint8_t i=8, n=0;
while(i--)
{
//Shift one position right and store read value
n>>=1;
n|=(therm_read_bit()<<7);
}
return n;
}

void therm_write_byte(uint8_t byte)
{
uint8_t i=8;
while(i--)
{
//Write actual bit and shift one position right to make the next bit ready
therm_write_bit(byte&1);
byte>>=1;
}
}

void therm_read_temperature(char *buffer, volatile char PIN_DS)
{
THERM_DQ = PIN_DS;
// Buffer length must be at least 12bytes long! ["+XXX.XXXX C"]
uint8_t temperature[2];
// uint16_t temper_16bit;
int8_t digit;
uint16_t decimal;
//Reset, skip ROM and start temperature conversion
therm_reset();
therm_write_byte(THERM_CMD_SKIPROM);
therm_write_byte(THERM_CMD_CONVERTTEMP);
//Wait until conversion is complete
//while(!therm_read_bit());
//_delay_ms(750);
for (volatile char gggg=0;gggg<151;gggg++)
{
TCNT1 = 0;
while(TCNT1<(5000*12));
}
//Reset, skip ROM and send command to read Scratchpad
therm_reset();
therm_write_byte(THERM_CMD_SKIPROM);
therm_write_byte(THERM_CMD_RSCRATCHPAD);
//Read Scratchpad (only 2 first bytes)
temperature[0]=therm_read_byte();
temperature[1]=therm_read_byte();
therm_reset();
//Store temperature integer digits and decimal digits
digit=temperature[0]>>4;
digit|=(temperature[1]&0x07)<<4;
//Store decimal digits
decimal=temperature[0]&0xf;
decimal*=5;
if (temperature[1]>0xFB) digit = 127-digit;

buffer[0] = to_ascii(digit/100);
buffer[1] = to_ascii((digit%100)/10);
buffer[2] = to_ascii(digit%10);
buffer[3] = '.';
buffer[4] = to_ascii((decimal%100)/10);

}


Обьясняю что наделал:
Частота 12000000 Гц получаеться что timer1 с пределителем на 1 будет делать 12 тиков каждую микросекунду.
Теперь чтобы сделать задержку в 1 микросекунду нада написать: TCNT1 = 0;while(TCNT1<(1*12)); тоесть теперь спустя 12 тиков(1мкс) програма будет выполняться дальше а так как таймер1 будет тикать постоянно, даже когда выполняеться прерывание INT0 то задержка будет более точной чем писать просто через _delay_us. А чтобы сделать иную задержку нада заменить 1 на нужное кол-во микросекунд(тока не больше 5400).
Тут как и раньше с выключеным ЮСБ работает а с включеным нет.
Причина редактирования: Нарушение п.3.4 Правил форума.
Go to the top of the page
 
+Quote Post
xemul
сообщение Nov 6 2009, 07:43
Сообщение #10



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Br.Misha @ Nov 6 2009, 04:02) *
Обьясняю что наделал:

Некоторый объём бесполезной работы?
Цитата
даже когда выполняеться прерывание INT0 то задержка будет более точной чем писать просто через _delay_us.

Вы не поняли причину проблемы и потому не с тем боретесь. С точки зрения контроллера между
//_delay_us(480);
и
TCNT1 = 0;
while(TCNT1<(480*12));
абсолютно никакой разницы нет - его на 480 мкс завесили в тупом цикле, и он не в состоянии отвлечься на другие задачи (н-р, на обработку обмена по usb, приоритет которой разумно сделать выше приоритета обмена по ванвари).
Я предлагал построить автомат не на задержках, а на интервалах, когда, обрабатывая (в прерывании) текущее состояние автомата и зная/предполагая его следующее состояние и время возникновения этого состояния, Вы можете задать это время таймером, выйти из обработки текущего прерывания, сделать что-нить полезное и по прерыванию от таймера вернуться к обработке следующего состояния автомата.
Цитата
Тут как и раньше с выключеным ЮСБ работает а с включеным нет.

Угу.
Go to the top of the page
 
+Quote Post
Br.Misha
сообщение Nov 6 2009, 09:03
Сообщение #11


Местный
***

Группа: Validating
Сообщений: 253
Регистрация: 21-12-08
Пользователь №: 42 646



но почему когда выполняеться _delay_us он не может переключиться на обмен данными по usb? а еси например появляеться прерывание INT0 которое вызывает комп по USB?
Go to the top of the page
 
+Quote Post
xemul
сообщение Nov 6 2009, 09:45
Сообщение #12



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(Br.Misha @ Nov 6 2009, 12:03) *
но почему когда выполняеться _delay_us он не может переключиться на обмен данными по usb? а еси например появляеться прерывание INT0 которое вызывает комп по USB?

Может, но тогда может нарушаться обмен по ванвари - собственно, этим Вы и начали топик. 480 мкс - самый длинный, но и самый некритичный по допуску интервал в этом обмене.
Я уже сказал, что, имхо, обмен по usb должен иметь приоритет перед обменом по ванвари. Т.к. запросами с компа контроллер управлять не может (почти), то остаётся только подстроить обмен по ванвари под паузы между обменом по usb, н-р, с помощью программного таймера, но это второй шаг в решении.
Не как решение задачи, а костыль - можно, коль Вы читаете из 1820 полностью скрэчпэд, просто проверять CRC прочитанного.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 6 2009, 10:38
Сообщение #13


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Раз Вы таки не поняли, показываю. Измените эти две функции.
CODE

void therm_write_bit(uint8_t bit)
{
cli();
if(bit)
{
ds_cbi(THERM_PORT,THERM_DQ);
_delay_us(4);
ds_sbi(THERM_PORT,THERM_DQ);
sei();
_delay_us(60);
}
else
{
ds_cbi(THERM_PORT,THERM_DQ);
sei();
_delay_us(60);
ds_sbi(THERM_PORT,THERM_DQ);
}
}

uint8_t therm_read_bit(void)
{
uint8_t bit=0;

cli();
ds_cbi(THERM_PORT,THERM_DQ);
_delay_us(4);
ds_sbi(THERM_DDR,THERM_DQ);
_delay_us(8);
if(THERM_PIN&(1<<THERM_DQ)) bit=1;
sei();
_delay_us(45);
return bit;
}
Go to the top of the page
 
+Quote Post
Rst7
сообщение Nov 6 2009, 11:33
Сообщение #14


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Господа, о чем вы? Понятное дело, что единственный способ работать с 1W софтово - это вклеить 1W в драйвер USB. Между битиками в USB ловить битики в 1W. Иначе - никак. Другое дело - если есть свободный UART, вопрос с 1W решается легко и небрежно:

CODE

static UREG OWByte(UREG b )
{
UREG i=8;
UBRR0=10; //115200
do
{
UREG d=0x00;
if (b&1) d=0xFF;
__disable_interrupt();
UDR0=d;
UCSR0A=(1<<TXC0);
__enable_interrupt();
while(!UCSR0A_TXC0);
b>>=1;
if (UDR0>0xFE) b|=128;
}
while(--i);
return b&255;
}

static UREG OWReset(void)
{
UREG c;
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
UBRR0=129; //9600
while(UCSR0A_RXC0) UDR0; //Зачистка буферов
__disable_interrupt();
UDR0=0xF0;
UCSR0A=(1<<TXC0);
__enable_interrupt();
while(!UCSR0A_TXC0);
c=UDR0;
if (c!=0xF0) return 1;
return 0;
}

void StartMeasureTemp(void)
{
if (!OWReset()) return;
OWByte(0xCC); //Skip ROM
OWByte(0x44); //Convert Temperature
}

REG16 ExtractMeasureTemp_one(void)
{
if (!OWReset()) return -273*16;
OWByte(0xCC); //Skip ROM
OWByte(0xBE); //Read scratchpad
REG16 v=OWByte(0xFF);
v|=OWByte(0xFF)<<8;
return v;
}


Только нужно заточить значения для UBRR под 12МГц (в приведенном исходнике - под 20). И подключить термометр - между ножками TXD и RXD процессора резистор 2.2к, вывод DQ термометра подключается к RXD. Питание не паразитное.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Br.Misha
сообщение Nov 6 2009, 13:36
Сообщение #15


Местный
***

Группа: Validating
Сообщений: 253
Регистрация: 21-12-08
Пользователь №: 42 646



_Pasha, я понял и делал так уже, юсб не отвечал потому что прерывания отключаються на больше чем 25 тактов.

Rst7, извиняюсь но я не совсем понял что вы написали. в моем девайсе чтоит датчик не с паразитным питанием и подтянут 2к2, но причем тут юарт и зачем соеденять Rx и Tx?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 10:35
Рейтинг@Mail.ru


Страница сгенерированна за 0.01562 секунд с 7
ELECTRONIX ©2004-2016