Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Кольцевой буфер на Си, буфер на Си для UART микроконтроллеров 
:(
    Опции темы
Arcanum
Дата 18.12.2011, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 1.11.2011

Репутация: нет
Всего: нет



я электронщик и писал до этого на Асме и не знал проблем пока не понял что надо расти.
свою первую в жизни функцию решил написать для буфера UART
есть два буфера - для приёмника и для передатчика.
вот функции записи и чтения приёмника:
Код


#define  MAXBUFF 10

volatile unsigned char BUFF_IN[MAXBUFF];        // Буфер приема массив
volatile unsigned char IN_PTR_S = 0;            // Указатель начала
volatile unsigned char IN_PTR_E = 0;            // Указатель конца
volatile unsigned char IN_FULL = 0;                // Флаг переполнения

void InBufferRx(unsigned char Rx_buf_In)
{
    BUFF_IN[IN_PTR_E] = Rx_buf_In;        // забрали байт 
    IN_PTR_E++;                            // увеличили смещение
    if (IN_PTR_E ==  MAXBUFF)            // Если достигли конца 
        IN_PTR_E = 0;                    // переставляем на начало
    if(IN_PTR_E == IN_PTR_S)            // Дошли до непрочитанных данных?        
            IN_FULL = 1;                // буфер переполнен
}

//чтение из буфера приёмника
unsigned char OutBufferRx(void)
{
    unsigned char i;
    if (IN_FULL == 0)
        if (IN_PTR_S == IN_PTR_E)
            return 0;
    i = BUFF_IN[IN_PTR_S];
    IN_PTR_S++;        
    IN_FULL = 0;
    if (IN_PTR_S == MAXBUFF)        
        IN_PTR_S = 0;        
    return i;
}



а вот для передатчика:

Код

volatile unsigned char BUFF_OUT[MAXBUFF];        // Буфер передачи массив
volatile unsigned char OUT_PTR_S = 0;            // Указатель начала
volatile unsigned char OUT_PTR_E = 0;            // Указатель конца
volatile unsigned char OUT_FULL = 0;            // Флаг переполнения.

void InBufferTx(unsigned char Tx_buf_In)
{
    BUFF_OUT[OUT_PTR_E]= Tx_buf_In;        // забрали байт из уарта
    OUT_PTR_E++;                        // увеличили смещение
    if (OUT_PTR_E ==  MAXBUFF)            // Если достигли конца 
        OUT_PTR_E = 0;                    // переставляем на начало
    if(OUT_PTR_E == OUT_PTR_S)            // Дошли до непрочитанных данных?        
        OUT_FULL = 1;                    // буфер переполнен
}

// обработчик опустошения буфера передатчика UART
ISR (USART_UDRE_vect)
{
    if (OUT_FULL == 0)
        if (OUT_PTR_S == OUT_PTR_E)
            UCSRB = (1<<RXEN|1<<TXEN|1<<RXCIE|1<<TXCIE|0<<UDRIE); //прекращаем передачу    
                
    UDR = BUFF_OUT[OUT_PTR_S];
    OUT_PTR_S++;    
    OUT_FULL = 0;    
    if (OUT_PTR_S == MAXBUFF)            
        OUT_PTR_S = 0;                
}


проверял следующей функцией:

Код

void Terminal (void)
{
unsigned char i;
    i = '0';
    InBufferRx(i+1);
    InBufferRx(i+2);
    InBufferRx(i+3);
    InBufferRx(i+4);
    InBufferRx(i+5);
    InBufferRx(i+6);
    InBufferRx(i+7);
    InBufferRx(i+8);
    InBufferRx(i+9);
    InBufferRx(i+10);
    
    
    
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    InBufferTx(OutBufferRx());
    
    

    StartTx();
}


вроде всё работает но почемуто он мне постоянно шлёт на 1 байт больше причём этот байт всегда начальный. пример(hex):
31 32 33 34 35 36 37 38 39 3A 31 
то что это проблема функции ISR (USART_UDRE_vect) я понимаю но что конкретно не так - не знаю

Это сообщение отредактировал(а) Arcanum - 18.12.2011, 21:37
PM MAIL   Вверх
bsa
Дата 18.12.2011, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Для себя я принял правило при написании кольцевых буферов (на асм и С): есть указатель на текущую свободную запись (в твоем случае индекс) и количество записей. При добавлении в список ты записываешь по адресу указателя, увеличиваешь его на 1, выравниваешь по размеру буфера (if (++i >= size) i = 0;) и если буфер еще не заполнен увеличиваешь количество записей на 1. Чтение если буфер не пуст: вычитаешь из указателя количество записей, выравниваешь по границе буфера (if ((i -= count) < 0) i += size;), берешь значение, количество записей уменьшаешь на 1.
Практика использования двух указателей (индексов) ведет к тому, что тебе сложно создать условие "буфер пуст" или "буфер полон" без введения дополнительных переменных. А это лишние условия и ошибки.
PM   Вверх
Arcanum
Дата 19.12.2011, 05:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 1.11.2011

Репутация: нет
Всего: нет



проблема решилась! не хватало return в одном месте:

Код

ISR (USART_UDRE_vect)
{    
    
    if (OUT_FULL == 0)
    {
        if (OUT_PTR_S == OUT_PTR_E)
        {
            UCSRB = (1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE|0<<UDRIE); //прекращаем передачу    
            return;
        }
    }    
    UDR = BUFF_OUT[OUT_PTR_S];
    OUT_PTR_S++;
    OUT_FULL = 0;    
    if (OUT_PTR_S == MAXBUFF)
    {            
        OUT_PTR_S = 0;                
    }
}


Добавлено через 1 минуту и 39 секунд
Цитата(bsa @ 19.12.2011,  02:54)
Для себя я принял правило при написании кольцевых буферов (на асм и С): есть указатель на текущую свободную запись (в твоем случае индекс) и количество записей. При добавлении в список ты записываешь по адресу указателя, увеличиваешь его на 1, выравниваешь по размеру буфера (if (++i >= size) i = 0;) и если буфер еще не заполнен увеличиваешь количество записей на 1. Чтение если буфер не пуст: вычитаешь из указателя количество записей, выравниваешь по границе буфера (if ((i -= count) < 0) i += size;), берешь значение, количество записей уменьшаешь на 1.
Практика использования двух указателей (индексов) ведет к тому, что тебе сложно создать условие "буфер пуст" или "буфер полон" без введения дополнительных переменных. А это лишние условия и ошибки.

можно ссылку на книжку где это подробнее описано?
PM MAIL   Вверх
bsa
Дата 19.12.2011, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



не знаю я такой книжки. сам придумал при попытке реализации.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0690 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.