Часто, работая с микроконтроллерами на С++, приходится изменять вывод std::cout. Например направить его в USART, на дисплей или просто в буфер. В данной статье будет описано 3 способа изменения вывода — два универсальных и один для IAR.
Первый способ — создать свой класс, наследуемый от streambuf и реализовать в нем виртуальный метод overflow, при этом указав буфер для хранения данных на передачу нулевого размера. И указать на экземпляр этого класса, для стандартного вывода cout.
out_buf the_out_buf;
cout.rdbuf(&the_out_buf);
Тогда, когда вы будете вызывать, cout << any будет вызываться метод overflow (т.к. буфер нулевого размера). Данный метод будет вызываться для каждого символа передаваемого на вывод и вам нужно просто написать свою процедуру обработки этих данных.
test.h
#include <streambuf>
class out_buf: public streambuf {
public:
out_buf();
char out_ch;
private:
virtual int overflow(int ch);
char *tmp;
};
out_buf::out_buf()
{
// устанавливаем нулевой размер буфера
setp(tmp, tmp); // начало = концу буфера
}
int out_buf::overflow(int ch)
{
out_ch = (char)ch;
}
main.c
#include <iostream>
#include "test.h"
int main(void)
{
out_buf the_out_buf;
cout.rdbuf(&the_out_buf);
cout << "test";
cout << endl;
{
Второй способ — полностью заменить cout своим классом (через макрос — см. код). При данном подходе, необходимо написать методы для всех типов данных передаваемых в cout.
debug_out.h
#define cout DebugOut::GetCurrentDebugOut()
#define endl DebugOut::endl
class DebugOut
{
public:
DebugOut();
~DebugOut();
void putChar( char ch );
friend DebugOut& operator <<( DebugOut& rOs, unsigned char bChar );
friend DebugOut& operator <<( DebugOut& rOs, unsigned short integer );
friend DebugOut& operator <<( DebugOut& rOs, unsigned int integer );
friend DebugOut& operator <<( DebugOut& rOs, char bChar );
friend DebugOut& operator <<( DebugOut& rOs, short integer );
friend DebugOut& operator <<( DebugOut& rOs, int integer );
friend DebugOut& operator <<( DebugOut& rOs, void* ptr );
friend DebugOut& operator <<( DebugOut& rOs, const char* pString );
DebugOut& operator<<( DebugOut& (*_f)( DebugOut& ) );
static DebugOut& endl(DebugOut& rOs);
static DebugOut& GetCurrentDebugOut();
};
debug_out.cpp
#include "debug_out.h"
#include <stdio.h>
static DebugOut iar_cout;
DebugOut::DebugOut(void){}
DebugOut::~DebugOut(void){}
void DebugOut::putChar( char ch )
{
printf("%c", ch);
}
DebugOut& operator <<( DebugOut& rOs, unsigned char bChar )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, unsigned short integer )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, unsigned int integer )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, char bChar )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, short integer )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, int integer )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, void* ptr )
{
return rOs;
}
DebugOut& operator <<( DebugOut& rOs, const char* pString )
{
while(*pString != 0)
{
rOs.putChar( *pString);
pString++;
}
return rOs;
}
DebugOut & DebugOut::operator<< (DebugOut & (*_f)(DebugOut &))
{
return(*_f)(*this);
}
DebugOut& DebugOut::endl(DebugOut & rOs)
{
rOs.putChar(0x0A);
return rOs;
}
DebugOut& DebugOut::GetCurrentDebugOut()
{
return iar_cout;
}
main.c
#include "debug_out.h"
int main(void)
{
cout << "test" << endl;
cout << endl;
cout << "test";
}
Третий способ — специализирован для IAR.
В папке где установлен IAR, найти \arm\src\lib\write.c. Данный файл подключить к проекту и переписать код в функции
size_t __write(int handle, const unsigned char * buffer, size_t size)
{
}
на необходимый.
При вызове cout будет вызваться данная функция.