1.26.2014

UART - Realizacja komunikacji 1-Wire z termometrem DS18B20 - EK-TM4C123GXL


Mikro-kontroler TM4C123GH6PM posiada 8 modułów UART - Universal Asynchronous Receiver/Transmitter. Do obsługi transmisji 1-Wire należny przygotować wyjście TX i wejście RX tak aby sygnały były współdzielone z jednym przewodem na którym musi być oparta cała transmisja. Do fizycznego połączenia pinów RX i TX potrzebne są dwa tranzystory NPN BC547 i dwa rezystory, przy testach i pisaniu kodu korzystałem z dokumentacji Atmel  i Maxim integrated.


Testowa płytka stykowa połączona z lanunchpadem.



Do inicjacji UART służy poniższa funkcja, nie wykorzystałem przerwań i buforów FIFO. Należy  w opcjach projektu  dodać "predefined symbols" "PART_LM4F230H5QR", gdyż bez tego biblioteka nie zwróci odpowiednich map dla naszego procesora. W zależności od płytki może być potrzebny inny zapis, więcej na forum TI link.

 
void OneWire_init(void)
{
  // Enable Peripheral Clocks
 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
 // Enable pin  for UART URX
 GPIOPinConfigure(GPIO_PB0_U1RX);
 GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0);
 // Enable pin  for UART UTX
 GPIOPinConfigure(GPIO_PB1_U1TX);
 GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_1);

 UARTClockSourceSet(UART1_BASE, UART_CLOCK_SYSTEM);
 UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
 UARTFIFODisable(UART1_BASE);
 UARTEnable(UART1_BASE);
}

Podstawowe funkcje jakie będą niezbędne do obsługi 1-Wire na wyższym poziomie to wczytywanie 1, wczytywanie 0, odczyt jednego bitu i reset.  W jednym bajcie przekazywany jest tylko jeden bit, cała ramka jest potrzebna do spełnienia czasowego wymogu transmisji. Baud rate ustawione w większości operacji na 115200.
Po nadaniu bajtu funkcja czeka aż bajt zostanie wysłany przez UART i następnie odebrany i odczytany (możliwe, że odczytanie jest zbędne, ma na celu oczyszczenie bufora).

Wczytanie 0 na magistrale, TX nadaje bajt składający się z samych zer.

void OneWire_write0()
{
 UARTCharPut(U_BASE, 0x00);
 while(UARTBusy(U_BASE))
 {
 }
 while(UARTCharsAvail(U_BASE))
 {
  UARTCharGetNonBlocking(U_BASE);
 }
}


Wczytanie 1 na magistrale, TX nadaje bajt składający się z samych 1.

void OneWire_write1()
{
 UARTCharPut(U_BASE, 0xFF);
 while(UARTBusy(U_BASE))
 {
 }
 while(UARTCharsAvail(U_BASE))
 {
  UARTCharGetNonBlocking(U_BASE);
 }
}

Odczytanie jednego bitu ze slave. Wczytanie 1 na magistrale i odczyt bajtu który przy zmodyfikowaniu przez slave będzie inny niż 1 co oznacza nadanie przez slave 0.

Read 0

Read 1

unsigned char OneWire_Read()
{
 // function reads 1-wire bus
 // return 1 or 0

 unsigned long tmp;
 UARTCharPut(U_BASE, 0xFF);
 while(UARTBusy(U_BASE))
 {
 }
 while(UARTCharsAvail(U_BASE))
 {
  tmp=UARTCharGetNonBlocking(U_BASE);
 }
 return (0xFF==tmp);
}

Dodatkową ważną funkcja jest reset, musi być wykonany przy niższym baud rate = 9600.
Polega na wczytanie 0xF0 na magistrale i odczycie bajtu który przy zmodyfikowaniu przez slave będzie inny niż 0xF0 co oznacza, że jest działający slave na magistrali.

Reset - brak slave na magistrali.


Reset - slave odpowiedział.



unsigned char OneWire_Reset(void){

 // function reset bus and returns 1 if is presence pulse

 unsigned long tmp=0;
 UARTDisable(U_BASE);
    UARTConfigSetExpClk(U_BASE, SysCtlClockGet(), 9600, (UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    UARTEnable(U_BASE);

 UARTCharPut(U_BASE, 0xF0);
 while(UARTBusy(U_BASE))
 {
 }
 while(UARTCharsAvail(U_BASE))
 {
  tmp=UARTCharGetNonBlocking(U_BASE);
 }

 UARTDisable(U_BASE);
    UARTConfigSetExpClk(U_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
    UARTEnable(U_BASE);
 return (0xF0!=tmp);
}