Стандартные функции ввода/вывода
Стандартные функции ввода/вывода позволяют обмениваться информацией с выполняемой программой, что, к примеру, очень удобно в процессе отладки. Все они построены на основе функций посимвольного ввода/вывода, которые легко приспособить к аппаратным требованиям системы. Если при обычном применении языка С эти функции используются для ввода данных с клавиатуры и вывода на экран или принтер, то применительно к микроконтроллерам речь идет об обмене данными через приемопередатчик UART/USART (по умолчанию) или последовательный порт. Таким образом, прежде чем начать ввод/вывод в программе должны быть выполнены соответствующие настройки.
Ввод/вывод символов с помощью определений getchar () и putchar ()
Простейшими определениями ввода/вывода в языке С являются getchar () и putchar (), которые предназначены для посимвольного обмена данными . Макрос getchar () возвращает символ, принятый от UART/USART или по последовательному интерфейсу, а макрос putchar (), наоборот, выводит символ. Все остальные стандартные функции ввода/вывода базируются на них.
Макросы getchar () и putchar () в компиляторах для микроконтроллеров реализуют ожидание готовности именно приемопередатчика UART/USART для передачи/приема символа. В том случае, если требуется организовать обмен данными по другому интерфейсу (например, по SPI), необходимо разработать собственные функции аналогичного содержания.
Рассмотрим пример простой программы, выводящей в бесконечном цикле через приемопередатчик UART/USART символы "1", "2", "3", "4" и "5". Ниже представлен исходный код программы putchar.с для устройства AT90S8515.
#include <avr/io.h>
#include <stdio.h>
int main (void)
{
const char str[] = "12345";
int i;
UBRR = 25; //Скорость обмена через UART - 9600 бод
UCR = 0x18;
//Устанавливаем разряды TXEN и RXEN для
активизации UART в режиме ввода/вывода через выводы 0 и 1 порта D.
//Разряд CHR9 = 0 - передача 8 бит данных
i = 0; //Индекс строки символов
while (1) //Бесконечный цикл
{
if (i > 4) i = 0; //Проверка выхода за пределы массива
putchar(str[i]); //Выводим i-й символ через UART
}
}
Функции вывода строк puts () и printf()
Функции puts () и printf () используют определение putchar () для посимвольного вывода строки в порт RS232, назначенный последним. Предположим, у нас есть определение строки, предназначенной для вывода через последовательный интерфейс: char s[6] = "12345"; Вызов функции puts () для вывода этой строки выглядит просто как puts(s).
Функция printf () несколько сложнее, поскольку позволяет применить форматированный вывод. Она имеет следующий синтаксис вызова:
printf("Строка, в которую подставляются переменные", переменная1, переменная2, ....) ;
В выводимой строке обычно используются спецификации форматирования значений переменных, переданных в качестве параметров. Каждая такая спецификация начинается со знака "%", после которого следуют обозначения параметров форматирования:
с — вывод параметра в виде символа ASCII;
d — вывод параметра в виде целого числа;
е — вывод параметра в экспоненциальном формате;
f — вывод параметра в виде вещественного числа;
ld — вывод параметра в виде длинного целого со знаком;
lu — вывод параметра в виде беззнакового длинного целого;
Lx —вывод параметра в виде беззнакового длинного целого в шестнадцатеричном представлении, используя нижний регистр символов;
LX —вывод параметра в виде беззнакового длинного целого в шестнадцатеричном представлении, используя верхний регистр символов;
s — вывод параметра в виде строки;
u — вывод параметра в виде беззнакового целого;
х — вывод параметра в виде беззнакового целого в шестнадцатеричном представлении, используя нижний регистр символов;
X —вывод параметра в виде беззнакового целого в шестнадцатеричном представлении, используя верхний регистр символов;
% — вывод знака процента.
Количество спецификаций должно совпадать с количеством переменных. При этом первая встретившаяся спецификация соответствует первой переменной в списке, вторая — второй и т.д.
В случае вывода числовых значений сразу же после знака "%" может быть указано количество символов и формат для отображения чисел, например:
8 — восемь знаков;
08 — восемь знаков с дополнением ведущими нулями;
8.2 — восемь знаков, два знака после десятичной точки.
Примеры использования спецификаций форматирования:
int n = 123;
char с = '$' ;
float f = 23.5;
char str[] = "Hello";
printf("n = %d, str = %s", n, str);
//(«n %целое число, str %строка», n = 123, str = Hello)
printf("n = %d : 0x%04X", n, n); /* (n % целое число : 0x% восемь знаков с дополнением ведущими нулями. Вывод параметра в виде беззнакового целого в шестнадцатеричном представлении, используя верхний регистр символов» n = 123:0x007B)
printf("Salary = %c%8.2f", c, f); //(«Salary %строка %8.2 восемь знаков, два после точки f » c = $, f = 23.50)
Функции ввода строк gets () и scanf ()
Функции gets () и scanf () выполняют действия, обратные функциям puts () и printf (): считывают посимвольно строку через назначенный последним последовательный интерфейс.
Функция scanf () считывает из входного потока значения в формате, определенном в первом параметре, и сохраняет их в переменных, адреса которых переданы ей в качестве последующих параметров. Спецификации форматирования для этой функции такие же, как и для printf (). Обычно функция scanf () используется в паре с printf():
int x, у;
puts("Enter two integers: ");
scanf("%d,%x\n", &x, &y); /* Считывает два числа, введенные через запятую: одно - в десятичной, а другое – в шестнадцатеричной форме */
printf("х = %d, у = %04Х", х, у);
Рассмотрим пример использования функций gets () и puts () для микроконтроллеров PIC.
#include <18F458.h>
#fuses HS, NOWDT
#use delay(clock=10000000)
#use rs232(baud=9600,
xmit=PIN_C6, rcv=PIN_C7)
char s1[12]; //Буфер, в который будет помещена принятая строка
void main()
{
while (1)
{
gets(si); //Считываем строку из стандартного входного потока
puts(si); //Выводим строку в стандартный выходной поток
}
}