Ynt: uart sorusu

Başlatan Karamel, 23 Nisan 2015, 18:01:23

Karamel

merhaba. z hocam surada https://www.picproje.org/index.php/topic,58899.msg454972/topicseen.html#msg454972 uart sorusu sorunca benimde uart ile ilgili aklima takilan sorularim hortladi. gectigimiz yazin bunun ile ilgili beyin firtinasi yapmistim ama pek bir sonuca varamamistim.


soyle bir case imiz olsun.

-uart hattimiza durmadan surekli bilgi basilsin. microcontrollerimiz "PicProje1=" den "PicProje2=" den "PicProje3=" ten sonra 80 byte bilgi ceksin. 81. byte tada "." (nokta) ile bilgiyi tam aldigini dogrulasin. (nokta yada herhangi karakterde olur ama biz bi standart olsun diye nokta secelim)


-programimiz time out u algilasin. yani ilk 60 byte lik veri gelirde iletisim belli bir surenin uzerinde durursa. microcontroller son 80 byte lik veri alimini yoksaysin.


yazin bunlar hakkinda cok kafa yormustum ama uart tan birden fazla veriyi alip. analiz etmeyi becerememistim. yalnizca bir byte veri alabilmistim. bu sorularimi algoritma bazinda yani ozel yazilmis ve icersini goremedigimiz kutuphaneler kullanmadan nasil yapildigini merak ediyorum.



mesaj birleştirme:: 23 Nisan 2015, 18:06:00

bu arada uarttan verileri interrupt ile alacagiz.

microcontrollerimiz normal islerini yaparken interrupt ile bir diger yandanda eger PicPrpje1= bilgisini almissa. ardindaki 80 byte i alacak ve sonundada "." ile iletisimi dogrulayacak.



gecen yaz ki denemelerimde interrupt fonksiyonu icersinde uart in receive registerini okuyordum ama 1 byte oluyordu. simdi birsuru bilgi icersinden anahtar kelimeyi secmemiz gerekli.....  :-\

aliveli


Karamel

hocam ring bufferdan kastiniz su ise http://en.wikipedia.org/wiki/Circular_buffer yarin bunu okuyup. anlayip. anladiklarimi turkce olarak buraya yazacagim.

butun gun ders kitabimdan 300 sayfa kadar yazi okudum. beynim sulandi.  :-\

Karamel

https://www.youtube.com/watch?v=fdCAsZkjpSg


burada konu guzel anlatiliyor. burada da http://en.wikipedia.org/wiki/Circular_buffer guzel anlatilmis. aklimda birseyler canlandi.

simdi anladigim kadari ile cylindirical gibi dusunecegiz. bir noktasini offset olarak alacagiz. yonumuz arbitrary. kafamiza gore secebiliriz. ilk gelen bilgi offest e yerlesiyor. 2. geline. sectigimiz yone dogru shift oluyor. 3-4-5-6-7-8-9....... neyse. buffer dolunca yeniler eskilerin uzerine yazilmaya basliyor. en eski bilgi yok oluyor.


mesela 10 byte lik bufferimiz oldugunu var sayalim.

1 = A
2 = B
3 = C
4 = D
5 = E
6 = F
7 = G
8 = H
9 = I
10 = J

seklinde dolsun. simdi P karakteri gelirse durum suna donusuyor?

1 = P
2 = A
3 = B
4 = C
5 = D
6 = E
7 = F
8 = G
9 = H
10 = I


dogru mu anlamisim?

Tagli

Veriler bellekte kaymıyor ama. Sadece pointer'lar kayıyor.

XC16'daki bir uygulama için bir kod yazmıştım zamanında.

buffer.h


#ifndef BUFFER_H
#define	BUFFER_H

/* Data Structures */
struct circularBuffer {
    int size;
    int wrt, rd; /* Writer and reader indices */
    int ghost;
    int nData, nGhost; /* Number of valid & ghost entries in the buffer */
    volatile char *data;
};
typedef volatile struct circularBuffer buffer_t;

/* Global Functions */
void bufferInit(buffer_t* target, volatile char* startAddr, unsigned char size);
int bufferEnqueue(buffer_t* target, char* source, int size);
int bufferDequeue(buffer_t* source, char* target, int size);
int bufferMove(buffer_t* source, buffer_t* target, int size);
int bufferFreeSpace(buffer_t* buf);
int bufferGhostEnqueue(buffer_t* target, char data);
void bufferKillGhost(buffer_t* buf);
void bufferAcceptGhost(buffer_t* buf);

#endif	/* BUFFER_H */


buffer.c

#include "buffer.h"

/* Functions */

/**
 * Creates a buffer header for further use.
 * @param target Data structure that saves the buffer info
 * @param startAddr Address pre-allocated data space
 * @param size Size of the pre-allocated data space
 */
void bufferInit(buffer_t* target, volatile char* startAddr, unsigned char size) {
    int i;
    target->size = size;
    target->data = startAddr;
    target->wrt = 0;
    target->rd = 0;
    target->ghost = 0;
    target->nData = 0;
    target->nGhost = 0;
    for (i = 0; i < size; ++i) {
        target->data[i] = 0;
    }
}

/**
 * Enqueues new data into a buffer.
 * @param target Target buffer for enqueue operation
 * @param data Pointer to the new data to be enqueued into the buffer
 * @param size Number of bytes to enqueue
 * @return Returns -1 if buffer was full (enqueue failure)
 */
int bufferEnqueue(buffer_t* target, char* source, int size) {
    int i;
    if (target->nData + size > target->size) {
        /* TODO: Set an error flag somewhere. */
        return -1; /*Unable to enqueue*/
    }

    for (i = 0; i < size; ++i) {
        target->data[target->wrt++] = source[i];
        if (target->wrt == target->size) target->wrt = 0;
    }
    target->nData += size;

    /* Ghost entries are no longer valid */
    target->ghost = target->wrt;
    target->nGhost = 0;

    return 0;
}

/**
 * Dequeues data from a buffer.
 * @param source Source buffer for dequeue operation
 * @param data Pointer to the location where dequeued data will be placed
 * @param size Number of bytes to dequeue
 * @return Returns the actual number of bytes dequeued.
 */
int bufferDequeue(buffer_t* source, char* target, int size) {
    int i;
    int limit = (source->nData < size) ? (source->nData) : size;
    
    for (i = 0; i < limit; ++i) {
        target[i] = source->data[source->rd++];
        if (source->rd == source->size) source->rd = 0;
    }
    source->nData -= limit;

    return limit;
}

/**
 * Moves data by dequeuing from one buffer and enqueuing into another.
 * @param source Source of dequeue
 * @param target Target of enqueue
 * @param size Size of the data to be moved from one buffer to another
 * @return Returns -1 if an error occurs
 */
int bufferMove(buffer_t* source, buffer_t* target, int size){
    int i;
    if (source->nData < size || target->nData + size > target->size){
        /* TODO: Set an error flag somewhere. */
        return -1; /*Unable to enqueue*/
    }
    
    for (i = 0; i < size; ++i){
       target->data[target->wrt++] = source->data[source->rd++];
       if (target->wrt == target->size) target->wrt = 0;
       if (source->rd == source->size) source->rd = 0;
    }
    target->ghost = target->wrt;
    target->nGhost = 0;
    target->nData += size;
    source->nData -= size;

    return 0;
}

/**
 * Enqueues temporary ghost data into a buffer.
 * @param target Target buffer for enqueue operation
 * @param data New data to be enqueued into the buffer
 * @return Returns -1 if buffer was full (enqueue failure)
 */
int bufferGhostEnqueue(buffer_t* target, char data) {
    if ((target->nData + target->nGhost) >= target->size) {
        /* TODO: Set an error flag somewhere. */
        return -1; /*Unable to enqueue*/
    }

    target->data[target->ghost] = data;
    ++(target->ghost);
    if (target->ghost == target->size) target->ghost = 0;
    ++(target->nGhost);

    return 0;
}

/**
 * Calculates the free space available in a buffer.
 * @param buf Buffer to be tested.
 * @return Number of free bytes in the buffer
 */
int bufferFreeSpace(buffer_t* buf) {
    return (buf->size - buf->nData);
}

/**
 * Forgets the ghost data in the buffer.
 * @param buf Target buffer to work on
 */
void bufferKillGhost(buffer_t* buf) {
    buf->ghost = buf->wrt;
    buf->nGhost = 0;
}

/**
 * Turns ghost data in a buffer into actual data.
 * @param buf Target buffer to work on
 */
void bufferAcceptGhost(buffer_t* buf) {
    buf->wrt = buf->ghost;
    buf->nData += buf->nGhost;
    buf->nGhost = 0;
}


ghost fonksiyonları seri porttan gelen verinin checksum onayı almadan geçici olarak saklanması ile ilgili idi. Checksum tutmazsa veri geçersiz saylıyordu. Oraya takılma.
Gökçe Tağlıoğlu

z

Aşağıdaki kodlara da göz at.

void SendChar(char Tx) 
{
      while(!(USART3->SR&0x80));  // TX Buffer dolu ise bekle (Rehber Sayfa 646)
      USART3->DR=Tx;
}
 
void SendTxt(char *Adr)
{
      while(*Adr) 
        {
          SendChar(*Adr);
          Adr++;
        }  
}
 
char DataReady()
{
       return(WAdr-RAdr);
} 
 
char ReadChar()
{
char Dat;
    
      Dat=RxBuf[RAdr];
      RAdr=(RAdr+1)&0x7F;
      return(Dat);
}
 
// Rx ve TX pinlerini (GPIOB10 ve GPIOB11) birbirine baglarsaniz gonderdiginiz datalar geri gelecektir
 
int main()
{
int i;
      UsartInit(); 
      SendTxt("PicProje");
      SendChar(' ');  
      SendTxt("Bunalmis");
 
      for(i=0;i<0x1000000;i++);         // Laf olsun diye bekledik
 
      while(DataReady()) ReadChar(); 
 
      while(1); 
}


https://www.picproje.org/index.php/topic,35896.msg263612.html#msg263612
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Karamel

Hocam simdi anladim. buffer i array olarak tanimlayip global bir degiskrn ile interrupt icersinde her bilgi gelince bu degiskeni bir arttirarak 80 byte incekiyorsunuz.

Oyleyse soru1

Bu sistem kontrol olmaksizin 80 byte i alir? biz ilk basta PicProje1= i nasil okuyacagiz? once P yi sonra P ve i olmusmu? Vs seklindemi gidecegiz? eger boyle ise interrupt icersinde cok falza if kullanmak gerekmez mi?

Soru2

timeout a halen kafam basmadi. interrupt rutininde birde timer calistirsak. her int e girdiginde timer calissa vede degeri sifirlansa. 81 de nokta isaretini alinca dursa? buda cok coplex mi olur? yoksa normal mi?