Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как использовать printf для вывода сразу на несколько устройств?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
scout
Понимаю, что нужно создать несколько функций:


print_LCD // вывод на LCD
{

}

print_RS232
{

}

и в каждой перенаправить printf на соответствующий putchar. Подскажите как это сделать?
zltigo
printf() оставьте в покое. Ознакомьтесь с первоисточником - vsprintf() и пишите в свои функции в
стиле:

Код
void bprintf( char *arg_list, ...)
{
va_list arg_buffer;
char *tbptr = tobuf;
    va_start( arg_buffer, arg_list );
    vsprintf( tobuf, arg_list, arg_buffer );
      while( *tbptr )
        boutchar( *tbptr++ );
}
scout
Спасибо за ответ. В общем понятно. Но неясно что такое tobuf?
zltigo
Цитата(scout @ Jun 16 2006, 23:06) *
Спасибо за ответ. В общем понятно. Но неясно что такое tobuf?

Буфер, естественно:
Код
// Temporary console print buffer
char tobuf[MAXSTRLEN];
scout
Спасибо вам zltigo. Все получилось.
VAI
Я вывожу или на термопринтер или на LCD. В putchar() обрабатываю соответствующую ESC-команду, которая должна переключать поток на принтер, выставляю флажок и вывожу на принтер. putchar( 0 ) возвращает флажок назад - для вывода на LCD.
scout
Спасибо VAI тоже вариант, только меня немного смущает, что стандартная ESC последовательность
используется не по назначению...
VAI
не настолько она стандартная. Я не имею ввиду символы '\a', '\n', '\r' и т.д. Я имею ввиду символ ESC, с кодом 0x1b или '\033'. Например, у принтеров все эти ESC-последовательности зависят от производителя принтера, у каждой фирмы свои.
Я применяю подобное в терминалах (ЖКИ+контроллер+термопринтер соединенные с основным устройством через СОМ-порт) для управления индикатором (вкл\откл курсор, gotoxy и т.д.) и переключения вывода на принтер.
Aaron
подниму старую тему, быстрым поиском по форуму решил, что эта тема наиболее подходящая для вопроса.
Раньше обходился простым вызовом printf, а сейчас появилось желание использовать разделение потока: fpintf(stdout, ...) и fprintf(stderr, ...)
Функции вполне себе стандартные, в конечном счёте всё сводится к вызову fputs(pStr, pStream). Если поток stdout, я использую класс и асинхронные очереди сообщений (неблокирующая передача). Если поток stderr, то передаю сообщение напрямую в UART полностью без прерываний:
Код
signed int fputs(const char *pStr, FILE *pStream) {
    signed int num = 0;
    if (pStream == stdout) {
        console_uart.puts(pStr);
    } else if (pStream == stderr) {
        NVIC_DisableIRQ(USART1_IRQn);
        while (*pStr != 0) {
            USART1_SendData(*pStr);
            num++;
            pStr++;
        }
        NVIC_EnableIRQ(USART1_IRQn);
    } else {
        num = -1;
    };
    return num;
}

signed int fprintf(FILE *pStream, const char *pFormat, ...) {
    va_list ap;
    signed int result;

    // Forward call to vfprintf
    va_start(ap, pFormat);
    result = vfprintf(pStream, pFormat, ap);
    va_end(ap);

    return result;
}

signed int printf(const char *pFormat, ...) {
    va_list ap;
    signed int result;

    // Forward call to vprintf
    va_start(ap, pFormat);
    result = vprintf(pFormat, ap);
    va_end(ap);

    return result;
}

Суть в том, что все вызовы функции printf(...) всегда работают нормально (используется stdout).
Но функция fprintf(pStream, ...) может либо нормально отработать, либо привести к зависанию МК, независимо от используемого pStream.
Например, такой вызов приведёт к зависанию на fprintf:
printf("line 1\r\n");
fprintf(stdout, "line 2\r\n");
А такой вызов всё отработает нормально:
printf("line 1\r\n");
for (i=0;i<5;i++) fprintf(stdout, "line %г\r\n", i);

Начал копать, - зависание происходит на fputs. Я вообще не понимаю, как такое возможно, ведь printf и fprintf в итоге используют одну и ту же функцию fputs, почему тогда она в одном случае зависает???
jcxz
Странный и, по-моему, очень кривой метод.
Во-первых: у вас при выводе длинной строки будут запреты прерываний на длительное время. Это может помешать работе других ISR.
Во-вторых: выводимые строки через stderr могут влезать внутрь строк выводимых в stdout.
В-третьих:
Вы знаете как построен обработчик прерывания UART, который выводит в порт из буфера console_uart? Почему Вы думаете, что после
того как Вы вмешаетесь в его работу прямым выводом в порт, это не нарушит его работу?
Элементарная ситуация, которая сразу приходит на ум:
После вывода последнего символа из буфера console_uart, на следующее TX-прерывание обработчик console_uart видя, что буфер пуст
просто ничего не делает (не маскируя прерывание TX), а просто выходит из прерывания. После такого выхода он не будет ожидать
след. TX-прерывания, а вы после этого своей функцией делаете вывод символа и он получает неожиданное TX-прерывание, которого
не должно быть. Ему может от этого поплохеть.
Aaron
весь код пишу сам, прекрасно представляю, что он делает.
По первому пункту - запрет идёт только на прерывания UART, с которым и надо работать. Остальная периферия работает замечательно.
По второму пункту - да, именно так и подразумевается, что stderr должен вклиниваться в вывод, прерывая нормальный поток процесса. Скажу даже, что до этого у меня была только реализация stderr, и она делала именно то, что мне надо было - в стандартный поток, идущий по UART с использованием прерываний (работа периферии, протоколы...), вклинивались сообщения printf. С периферийным модулем UART при этом ничего не происходит, всё прекрасно работает. Прерывание TX при пустом буфере, естественно, отключается, так что описанная вами ситуация с неожиданным TX прерыванием не возникает.
aaarrr
Цитата(Aaron @ Apr 20 2012, 10:52) *
Начал копать, - зависание происходит на fputs.

В примере fputs должен без вариантов вызвать console_uart.puts. Так в каком именно месте происходит "зависание"?
AHTOXA
Я подозреваю, что вывод в stderr прерывает работу прерывания (каламбурчик!) в какой-то неудачный момент времени, и после возобновления передачи по прерываниям система раскорячивается. Попробуйте запрещать прерывания поаккуратнее, скажем, после запрета - дождитесь флага TXEMPTY, и очистите его. Ну и при последующем разрешении - если есть данные в буфере передатчика, то надо взвести TXEMPTY снова, или что-то в этом роде.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.