Hardware
A ligação do DS18B20 é trivial: terra, alimentação (3.3V) e o sinal de dados (DQ, conectado a P1.1 na Launchpad).
Software
Aqui as coisas ficam mais "interessantes" (leia-se complicadas). O protocolo usado pelo sensor (OneWire) possui alguns tempos críticos da ordem de microsegundos. Para complicar, o MSP430 está rodando a 1MHz, portanto cada ciclo consome 1 microsegundo.
O compilador da IAR possui uma pseudo função __delay_cycles que gera código que consome "com precisão" um certo número de ciclos. Entretanto, operações comuns (como a chamada de rotina) consome vários ciclos (e portanto microsegundos). As primeiras tentativas não deram certo. Uma observação com osciloscópio mostrou grandes divergências. Infelizmente, o meu osciloscópio é um pouco limitado para este tipo de análise. O resultado final foi obtido pelo ajuste empírico dos tempos. Talvez eu tente revisar isto depois usando um Bus Pirate.
Abaixo as rotinas de comunicação com o sensor. O projeto completo pode ser baixado dos arquivos do blog (arquivo MSP_NRF24_2.zip).
#define delayMicroseconds(n) __delay_cycles(n) // 1MHz = 1uS por ciclo
// Macros para comunicação com o DS18B20
// Usadas para maior velocidade
#define setDQ_LOW() { P1DIR |= DS18B20; P1REN &= ~DS18B20; P1OUT &= ~DS18B20; }
#define setDQ_HIGH() { P1DIR &= ~DS18B20; P1REN |= DS18B20; P1OUT |= DS18B20; }
// Leitura da temperatura
// Retorna temperatura em décimos de grau
// Considera que temos apenas um sensor conectado
// e ele está com a configuração padrão
// Ref: AN162 da Maxim
static unsigned leTemperatura(void)
{
unsigned valor;
if (!OW_Reset())
return 0;
OW_WriteByte (0xCC); // Skip ROM
OW_WriteByte (0x44); // Start conversion
delay(8); // aguarda fim da conversao
OW_Reset();
OW_WriteByte (0xCC); // Skip ROM
OW_WriteByte (0xBE); // Read ScratchPAD
valor = OW_ReadByte(); // LSB
valor = (OW_ReadByte() << 8) + valor; // MSB
OW_Reset(); // Nao queremos o resto
valor = (valor * 100) / 16;
return (valor+5)/10;
}
// OneWire reset
// Retorna true se tem um sensor conectado
static byte OW_Reset(void)
{
byte resposta;
setDQ_LOW();
delayMicroseconds(500); // comanda reset
setDQ_HIGH();
delayMicroseconds(70); // aguarda sensor responder
resposta = P1IN & DS18B20; // le a resposta
delayMicroseconds(500); // aguarda fim da resposta
return resposta == 0;
}
// OneWire Read Byte
static byte OW_ReadByte(void)
{
byte i, resp;
for (i = 0; i < 8; i++)
{
// Pulso de 1uS abre janela para resposta
setDQ_LOW();
setDQ_HIGH();
// Dá um tempo para sensor colocar a resposta e a lê
delayMicroseconds(8);
resp = resp >> 1;
if ((P1IN & DS18B20) != 0)
{
resp = resp | 0x80;
}
// Aguarda o final da janela
delayMicroseconds(50);
}
return resp;
}
// OneWire Write Byte
static void OW_WriteByte(byte valor)
{
byte i;
for (i = 0; i < 8; i++)
{
// Low inicia a janela
setDQ_LOW();
if (valor & 0x01)
{
// Volta o nivel alto se for "1"
setDQ_HIGH();
// Manter o bit até o final da janela
delayMicroseconds(90);
}
else
{
// Manter o bit até o final da janela
delayMicroseconds(90);
// Voltar ao repouso
setDQ_HIGH();
}
// Passar para o próximo bit
valor = valor >> 1;
}
}

Nenhum comentário:
Postar um comentário