Страница 1 из 1
Потоки в библиотеке stdio.h
Добавлено: Сб окт 30, 2021 12:07:36
LEVV2006
Всем привет!
Для ввода и вывода данных по UART я использую библиотеку stdio.h и ей потоки.
Но тут мне потребовалось в дополнений реализовать программный UART интерфейс.
И возник такой вопрос. Как воспользоваться библиотекой stdio.h если её 2 стандартных потока (stdin и stdout) уже заняты аппаратным UART?
А если например на МК есть 2 аппаратным UART. Как быть в таком случае?
Re: Потоки в библиотеке stdio.h
Добавлено: Сб окт 30, 2021 15:00:53
Карбофос
Изучите stdiodemo из исходников avr-libc.
А вообще, конечно-же, много разных вариантов.
Re: Потоки в библиотеке stdio.h
Добавлено: Сб окт 30, 2021 20:04:05
LEVV2006
Ну..... кое что у меня заработало.
Суть проблемы.
По умолчанию библиотека stdio.h заточена под 3 потока. (stdin, stdout, stderr). И следовательно для двухстороннего общения по 2 UART этого мало.
Что сделал чтобы заработало.
Файл stdio.h запрещен к изменению так как является частью среды разработки. Я сохранил копию файла stdio.h и добавил в свой проект под новым именем stdio_dual.h. Во всем проекте заменил stdio.h на stdio_dual.h. И внес в файл следующие изменения:
Добавил 2 строчки
Код: Выделить всё
//Было
#define stdin (__iob[0])
#define stdout (__iob[1])
#define stderr (__iob[2])
//Добавил
#define stdinsoft (__iob[3])
#define stdoutsoft (__iob[4])
Теперь спокойно можно организовать прием и передачу по 2 интерфейсам
Код: Выделить всё
static FILE uart = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
static FILE Soft_uart = FDEV_SETUP_STREAM(Soft_uart_putchar, Soft_uart_getchar, _FDEV_SETUP_RW);
stdin=stdout=&uart;
stdinsoft=stdoutsoft=&Soft_uart;
Как читать и писать в порт
Код: Выделить всё
fscanf(stdin,"%s",&StringUART);
fprintf(stdout,"USART = %s\n",StringUART);
fscanf(stdinsoft,"%s",&StringUART);
fprintf(stdoutsoft,"Soft_USART = %s\n",StringUART);
Подводные камни:
Компилятор не мог найти эти переменные: stdinsoft и stdoutsoft. Мне пришлось их продублировать в main.h. Спустя некоторое время я решил их закомментировать и компилятор ругаться по новой не стал. При этом все продолжило работать.
PS/ К сожалению пока тест проводился только на одном аппаратном UART. И частично на программном UART (Пока не могу добиться стабильной работы).
Re: Потоки в библиотеке stdio.h
Добавлено: Сб окт 30, 2021 20:14:57
Карбофос
Вот только в iob.c определение:
Код: Выделить всё
#include <stdint.h>
#include <stdio.h>
#include "stdio_private.h"
FILE *__iob[3]; /* stdin, stdout, stderr */
Конечно-же, stdio.h править или подменять не следует.
Re: Потоки в библиотеке stdio.h
Добавлено: Сб окт 30, 2021 22:12:27
LEVV2006
Было найдено более оригинальное решение. Думаю стоит его выложить целиком. Может кому то и пригодится.
Ничего что я делал выше, делать не надо. Все на оригинальных файлах.
main.c
Код: Выделить всё
#include "main.h"
uint8_t StringUART[50]={'\0'};
int main(void)
{
init_USART();
fprintf(&mystd,"Test\n");
while (1)
{
if (UARTRead)
{
fscanf(&mystd,"%s",&StringUART);
fprintf(&mystd,"USART = %s\n",StringUART);
}
}
}
main.h
Код: Выделить всё
#ifndef MAIN_H_
#define MAIN_H_
#define F_CPU 16000000UL //частота МК
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "UART.h"
extern FILE* mystd;
#endif
UART.c
Код: Выделить всё
#include "UART.h"
FILE mystd = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
void init_USART() //инициализация USART
{
UBRR0L = UBRRL_value;
UBRR0H = (UBRRL_value>>8);
UCSR0B |=(1<<TXEN0)|(1<<RXEN0);
UCSR0C |=(1<<UCSZ01)|(1<<UCSZ00)|(1<<USBS0);
}
static int uart_putchar(char c, FILE *stream) //отправка данных по USART
{
if (c == '\n')
uart_putchar('\r', stream);
while(!(UCSR0A&(1<<UDRE0)));
UDR0=c;
return 0;
}
static int uart_getchar(FILE *stream) //чтение данных по USART
{
while(!(UCSR0A&(1<<RXC0)));
return UDR0;
}
UART.h
Код: Выделить всё
#ifndef UART_H_
#define UART_H_
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 16000000UL //частота МК
#define BAUD 9600L
#define UBRRL_value (F_CPU/(BAUD*16))-1
#define UARTRead UCSR0A&(1<<RXC0)
//прототипы функций
void init_USART();
static int uart_putchar(char c, FILE *stream); //отправка данных по USART
static int uart_getchar(FILE *stream); //чтение данных по USART
#endif /* UART_H_ */
Re: Потоки в библиотеке stdio.h
Добавлено: Сб окт 30, 2021 22:27:37
Карбофос
Вот и чудесно.
Интереса ради, можете AVR303 appnote глянуть, там в примере кольцевые буферы приема/передачи организованы через прерывания.