printf() и два USART (AT91SAM7X256, Keil)

Статус: Offline
Реєстрація: 15.11.2007
Повідом.: 59
printf() и два USART (AT91SAM7X256, Keil)

В сабжевом контроллере есть два ЮАРТА и один дебаг юнит, по сути тоже юарт.

Функция printf() выводит поток в один девайс (по умолчанию это дебаг юнит).
С помощью ретаргетинга можно перенапрявить поток на другой ЮАРТ.

Вопрос, кто нибудь работал этой функцией с двумя ЮАРТАМИ?
И если да, то как делал ретаргет.
 
Работал с обоими UART, но не пользовал принтф(). Пользовал DMA - отлично суёт любой массив хоть в УАРТ, хоть в КАН...
Типа апну, мож кто подскажет.
 
Классная тема.. :) Не использовал такого никогда, посему тоже весь во внимании, интересно.. :)
 
В сабжевом контроллере есть два ЮАРТА и один дебаг юнит, по сути тоже юарт.

Функция printf() выводит поток в один девайс (по умолчанию это дебаг юнит).
С помощью ретаргетинга можно перенапрявить поток на другой ЮАРТ.

Вопрос, кто нибудь работал этой функцией с двумя ЮАРТАМИ?
И если да, то как делал ретаргет.
ХЕЗ,как там с ретаргетом,printf() выводит символы в стандарный поток вывода.Может, создать пару своих функций printf_1(),printf_2() и задействовать в каждой из них свой putchar_x(),направляющий символы в требуемый порт?
 
Если пихать просто в порт, то теряется вся прелесть форматированного вывода.
Тут надо что бы сама функция принтф делала преобразования и вызывала более низкоуровневую функцию int fputc(int ch, FILE *f), которая уже будет плевать в нужный порт.

Пока придумал только так:
Делаем перехват функции fputc в которой пишем что-то вроде

if (Device_Num == 0)
{
USART_PutChar(AT91C_BASE_US0,c);
return 0;
}
if (Device_Num == 1)
{
USART_PutChar(AT91C_BASE_US1,c);
return 0;
}
if (Device_Num == 2)
{
DBGU_PutChar(c);
return 0;
}
else return -1;

и пишем еще 3 функции printf0, printf1, printf2, по одной для каждого юарта

void printf0(const char *str,...)
{
Device_Num = 0;
printf(str,...); <<---как сюда вставить неизвестное количество параметров??
};

Так вот на данном этапе застрял на передаче неопределенного количества параметров самой функции printf();

Т.е. пока что можно написать printf1("It's my USART1\n\r"); и на юарте1 будет текст.
А вот printf("It's my USART%u\n\r",Device_Num); уже не обработает.

В общем можно жестко задаться количеством и типом передаваемых параметров.

Или вот еще. Оставить принтф в покое, но только перед ее вызовом переключать порт Device_Num, но тут потеряется наглядность, наверное.

Ну или... нужен гуру СИ.
 
Та не иф, а свич кэйс:рл:

Так вот на данном этапе застрял на передаче неопределенного количества параметров самой функции printf();

Нихуянипонял :eek:
Постановку задачи сведи, пожалуйста к первоначальному общему варианту. ЧТО именно надо делать? Передавать некоей функцией в некий порт строку неопределённой длины?

Можно создать динамический массив и тулить указатели, тогда не нужно совать туеву хучу параметров в функцию, достаточно двух - старта и длины, а она пусть по циклу выгребает этот бардак...
Только я не пойму - на кой ляд каждой фразе приделывать по функции, если можно сформировать массив и подсунуть его DMA под нос - и забыть вообще о выводе, оно само вытолкнет и прерывание выработает, что закончило.

А вот printf("It's my USART%u\n\r",); уже не обработает.
Device_Num вообще как с областью видимости? Он где и кем объявлен? Ты его юзаешь в основном теле, а отдаешь печатать его некоей функции - ничё, что она слыхом не слыхивала о такой переменной? Ты его хоть пабликом, что-ли обзави.

Ну и када код приводишь - объявления приводи и в укороченном виде - его место в коде, что-то типа

main {
...
int DeviceNum
...
while(1)
{
}
MyPrintf(///,///,///,)
{
...
}
}

А-то не понятно ж нихрена почему не работает, ибо вариантов более, чем одно :)

}
 
sprintf(строковая переменная,"текст со всеми радостями printf :))) ");
а потому эту переменную по символам пихаешь в putchar_x().
Вот те пример, правда для TMS, но смысл поймешь:
.............................
char text[];
..............................
sprintf(text," U(ADC) = %f",U_adc);
scia_msg(text);
...............................
где у ТМСа scia - первый УАРТ. второй УАРТ называется scib.
 
void printf0(const char *str,...)
{
Device_Num = 0;
printf(str,...); <<---как сюда вставить неизвестное количество параметров??
};

Вообще-то именно для таких целей есть класс функций v(s)printf.
А также набор макросов из <stdarg.h>/<varargs.h>
 
Вообще-то именно для таких целей есть класс функций v(s)printf.
А также набор макросов из <stdarg.h>/<varargs.h>
ИМХО это все хорошо для взрослых машин,для имбеддед приложений жлобишся каждым словом...
 
а написать printf заново не? :)
не очень помню про перегрузку функций в plain C,
но можно printf назвать по другому и все.
она правда немаленькая
Тільки зареєстровані користувачі бачать весь контент у цьому розділі



или неплохо подсказали открыть поток fopen на другой юарт и делать fprintf туда.
можно через #define подключить
 
Останнє редагування:
Та не иф, а свич кэйс:рл:

Та ладно тебе, я помню в авр-ах тот свичкейс городил таблицу во флеше, так что единственным его приимуществом была наглядность.

По теме нужно писать свой putchar/getchar, т.к. принтф будет использовать их. На практике никогда эти принтф не пользовал, небыло необходимости, хотя проверял - даже работали.
 
Всё вообще-то гораздо проще. printf() на самом деле годится только для демонстраций, поскольку требуется #include если не ошибаюсь, <stdio.h> и соответственно раздуть откомпиллированный код до безобразия. Чтобы направить в нужный UART записывайте в соответствующий регистр (точно не помню, что-то типа AT91_UART2_TX) вашу строку по одному символу (байту, т.е. побуквенно) и всё. Ктати, если не поленитесь и посмотрите реализацию printf() в системной библиотеке, то увидите, что именно это она и делает.
 
Всё вообще-то гораздо проще. printf() на самом деле годится только для демонстраций, поскольку требуется #include если не ошибаюсь, <stdio.h> и соответственно раздуть откомпиллированный код до безобразия. Чтобы направить в нужный UART записывайте в соответствующий регистр (точно не помню, что-то типа AT91_UART2_TX) вашу строку по одному символу (байту, т.е. побуквенно) и всё. Ктати, если не поленитесь и посмотрите реализацию printf() в системной библиотеке, то увидите, что именно это она и делает.

Та свои путстринг и гетстринг написать и совать строку в DMA с указанием номера порта. Всё. Там в том арме ДМА специально для этого и придуман - он отлично САМ (без ансамбля, сам бля, во бля...) разбирается со всей периферией, включая SPI, выталкивая туда массив на ура. Давайте уже использовать микроскопы и молотки по назначению..

Та ладно тебе, я помню в авр-ах тот свичкейс городил таблицу во флеше, так что единственным его приимуществом была наглядность..

В кейле, или в чём? Я просто кейл не юзаю. я IAR пользовал.. D IAR всё нормально работает. И наглядности добавляет, и не засирает при этом память.
 
Назад
Зверху Знизу