O protocolo 1 wire é muito interessante para uso de somente um pino de I/O de um microcontrolado. Protocolo simples e baseado em janelas de tempo entre os sinais. Todavia, o uso de atrasos para escrita e leitura do pino pode resultar em perda de desempenho e complicar a vida do programador. Isso ocorrerá se a temporização for feita através da execução de laços vazios.
Visando superar essas complicações e otimizar a programação e desempenho do microcontrolador, a Maxim (compradora da
Dallas Semiconductor Corp. , que criou o protocolo), apresenta uma
nota de aplicação para realizar a comunicação 1 wire empregando o protocolo serial simples (UART).
O detalhe está em trocar a taxa de transmissão entre 9600 e 115200 bps. No Reset usa-se 9600 e envia-se o dado 0xF0. Para escrita e leitura, 115200 bps. Na escrita de 1 lógico envia-se 0xFF, de 0, 0x00. Na leitura se envia 0xFF para cada bit a ser lido, retorno 0xFF significa bit 1. O uso da UART é, portanto, simples e prático.
A comunicação deve ser configurada para 8 bits de dados, um bit de parada, sem bit de paridade.
A seguir código exemplo para o DS80B20 (sensor de temperatura), empregado para um Corte-M0+ da STM, baseado na camada de abstração de hardware (HAL). Os detalhes foram suprimidos, pois a ideia é apresentar o algoritmo básico.
//--------------------------------------------------------------------------
// 1 WIRE functions - UART 2
//--------------------------------------------------------------------------
// 1 WIRE functions - UART 2
void reset_1w()
{
unsigned char buff[2];
buff[0]=0xF0;
huart2.Init.BaudRate = 9600; // para o reset a taxa deve ser 9600
HAL_UART_Init(&huart2);
HAL_UART_Transmit(&huart2, buff, 1, HAL_MAX_DELAY);
huart2.Init.BaudRate = 115200; // 115200 para rescrita e leitura
HAL_UART_Init(&huart2);
}
//--------------------------------------------------------------------------
void write_byte_1w(unsigned char data)
{
uint32_t i;
for(i=0; i<8; i++)
{
if(tst_bit(data,i))
USART2->TDR = 0xFF; // logico 1 envia FF
else
USART2->TDR = 0x00; // logico 0 envia 00
HAL_UART_Receive(&huart2, (uint8_t *)aRxBuffer, 1,0xFFFF);
}
}
//---------------------------------------------------------------------------
unsigned char read_byte_1w()
{
unsigned int i;
unsigned char dado = 0; // todos os bits são zero por default
for (i=0;i<8;i++)
{
USART2->TDR = 0xFF; // para ler um bit envia FF
HAL_UART_Receive(&huart2, (uint8_t *)aRxBuffer, 1,0xFFFF);
if(aRxBuffer[0] == 0xFF) //se for igual a FF o bit é um, zero se contrário
set_bit(dado,i);
}
return (dado);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//DS18B20 - uma conversão
reset_1w(); //reset do sensor (a resposta de presença é retornada mas não avaliada).
write_byte_1w(0xCC); //comando para pular ROM (só 1 dispositivo no barramento).
write_byte_1w(0x44); //manda iniciar a conversão
HAL_Delay(750);
reset_1w();
write_byte_1w(0xCC);
write_byte_1w(0xBE); //avisa que quer ler a memória
temp_LSB = read_byte_1w();//só interesse em ler os dois bytes da temperatura
temp_MSB = read_byte_1w();
temp_16bits = (temp_MSB<<8) | (temp_LSB);
if (temp_MSB > 7)
{
temp_16bits = 0xFFFF - temp_16bits + 1;
sinal = '-';
}
else
sinal = '+';
temperatura = (5*temp_16bits)/8;