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