Mensagem

"Sonhar mais um sonho impossível, lutar quando é fácil ceder, vencer o inimigo invencível, negar quando a regra é vender."
Miguel de Cervantes.

"Os microprocessadores RISC funcionam a partir do princípio genial de se encarregar das coisas mais fáceis e deixar todas as partes difíceis para outras pessoas resolverem."
Douglas Adams.

Protocolo 1 Wire usando UART com o STM32

   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;