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); }