Bir çoğumuz mikrodenetleyiciler ile uğraşırken haberleşme paketlerini düzgün şekilde alabilmek adına çeşitli yöntemler dener. Durum makinesi ile bir protokolü çözümlemek, ingilizce adiyla “parse” etmek bu işi anlaşılır şekilde yapmak adına bir yoludur. Site yazarlarından Fatih ÖZCAN “Sonlu Durum Makineleri” hakkındaki yazısını okuduysanız konuyu uygulama üzerinde inceleyelim.
Uygulama olarak UART çevrebirimi üzerinden gelen verilere göre LED kontrol işlemi yapan işlevleri aşağıdaki gibi tanımlayabiliriz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
#include "main.h" uint8_t g_receivedData = 0; uint8_t g_receivedFlag = 0; void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET) { g_receivedData = (uint8_t)USART_ReceiveData(USART1); g_receivedFlag = 1; USART_ClearITPendingBit(USART1, USART_IT_RXNE); } } int main(void) { SYSTEM_Configuration(); while (1) { if (g_receivedFlag == 1) { LED_StateMachine(g_receivedData); g_receivedFlag = 0; } } } /* ['X']['Y'][LedNo][LedValue]['Z'] */ static void LED_StateMachine(uint8_t rxData) { static uint8_t state = 0; static uint8_t ledNo = 0; static uint8_t ledValue = 0; switch (state) { case 0: if (rxData == 'X') { state = 1; ledNo = 0; ledValue = 0; } break; case 1: if (rxData == 'Y') { state = 2; } break; case 2: if (rxData >= 1 && rxData <= 4 ) { ledNo = rxData; state = 3; } else { // Tanim araligi disindaki led girisi state = 0; } break; case 3: if (rxData == 0 || rxData == 1) { ledValue = rxData; state = 4; } else { // Tanim araligi disindaki led deger girisi state = 0; } break; case 4: if (rxData == 'Z') { state = 0; LED_Control(ledNo, ledValue); } else { // Iletisim hatasi state = 0; } break; } } static void LED_Control(uint8_t ledNo, uint8_t value) { uint8_t buffer[32]; switch (ledNo) { case 1: GPIO_WriteBit(LED_GREEN_GPIO, LED_GREEN_PIN, (BitAction)value); break; case 2: GPIO_WriteBit(LED_ORANGE_GPIO, LED_ORANGE_PIN, (BitAction)value); break; case 3: GPIO_WriteBit(LED_RED_GPIO, LED_RED_PIN, (BitAction)value); break; case 4: GPIO_WriteBit(LED_BLUE_GPIO, LED_BLUE_PIN, (BitAction)value); break; } sprintf((char *)buffer, (const char *)"%d.LED = %d Durumuna Gecti\n", ledNo, value); USART_SendString(USART1, (char *)buffer); } |
Burada denetleyicinin çözümlediği paket şu formattadır;
[‘X’][‘Y’][LedNo][LedValue][‘Z’]
Başlangıcı garantilemek amacıyla 2 adet karakter almak güvenlik açısından daha doğru olur. Verilen led numarası ve değerine bağlı olarak ilgili LED kontrol edilir ve bildirim cevabı yine UART protokolü üzerinden geri besleme olarak paket gönderen sisteme bildirilir. Örnek olarak aşağıdaki dizileri verebiliriz.
- [‘X’][‘Y’][1][1][‘Z’] Paket çözümlenmesi : 1. LED’i 1 yap.
- [‘X’][‘Y’][4][0][‘Z’] Paket çözümlenmesi : 4. LED’i 0 yap.
Haberleşme esnasında gönderilecek verilerin kritik olması duruma bağlı olarak protokole CRC kontrol ve bunun gibi bir takım doğrulama sistemleri eklenebilir. Çalışmayı geliştirmek adına bu örneğe CRC kontrolü eklemenizi öneririm. Konunun anlaşılması adına verdiğim bu basit uygulama ile alakalı sorularınızı ICTR Soru Cevap bölümde sorabilirsin.
Esen kalın.
Baran EKREM