Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
He hecho el siguiente programa y lo he cargado en la raspberry, empleando para cronometrar la libreria chrono de C++11
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //read, write, close, usleep
#include <fcntl.h> //constantes: O_RDWR, O_NOCTTY
#include <termios.h> //rs232
#include <time.h>
#include <chrono>
#include "mmapGpio.h"//gpio OJO!!! modificar base address 0x20 a 0x3F para raspberry2
#include "mmapGpio.cpp"//gpio
mmapGpio rpiGpio1; // instantiate an instance of the mmapGpio class
//20*10/9600=20.83ms
void delay_ms(long int ms) { timespec t1,t2;t1.tv_sec=0;t1.tv_nsec=ms*1000*1000; nanosleep(&t1,&t2); }
void delay_us(long int us) { timespec t1,t2;t1.tv_sec=0;t1.tv_nsec=us*1000; nanosleep(&t1,&t2); }
void delay_mbps(long int mbps) {timespec t1,t2;t1.tv_sec=0;t1.tv_nsec=mbps*(500000000L/BAUDRATE); nanosleep(&t1,&t2); }//cambio #V023
//configura gpio outputs e inputs:
void init_gpio();
//Lee estado del puerto de entrada
int lee_puerto(int puerto) { if (rpiGpio1.readPin(puerto) == mmapGpio::HIGH) return 1;else return 0;}
void pone_puerto(int puerto,int estado) { if (estado) rpiGpio1.writePinHigh(puerto );else rpiGpio1.writePinLow( puerto );}
using namespace std;
using namespace std::chrono;
class halla_tiempo_c
{
public:
high_resolution_clock::time_point t1,t2;
void inicia() { t1= high_resolution_clock::now(); }
double halla_tiempo() //retorna el tiempo en segundos
{
t2= high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
return time_span.count();
}
};
int main()
{
halla_tiempo_c tiempo1;
printf("===inicio prueba de reloj cronometrando 50 segundos, dar a entern");getchar();
tiempo1.inicia();
while (tiempo1.halla_tiempo()<50);
printf("===fin prueba de reloj cronometrando 50 segundos===============n");
pone_puerto(3,0);delay_ms(1);
printf("nInicializo y compruebo GPIOs:n");
init_gpio();
int uart_str;
printf("nInicializo y compruebo RS232:n");
rs232_setup(uart_str);
if (uart_str == -1) return -1;
long i,maxi=10000000L,j=0;
tiempo1.inicia();
for (i=0;i<maxi;i++)
{
pone_puerto(3,1);
while( lee_puerto(2)!=1) j++;
pone_puerto(3,0);
while( lee_puerto(2)!=0) j++;
}
double t2=tiempo1.halla_tiempo();
double frecuencia;
frecuencia=1.0*maxi/t2/1.0e6;
printf("nTiempo=%lg Frecuencia=%lg Mhzn",t2,frecuencia);
return 1;
}
void init_gpio()
{
//inputs:
rpiGpio1.setPinDir( 2,mmapGpio::INPUT);
//outputs:
rpiGpio1.setPinDir( 3,mmapGpio::OUTPUT);
}
Entonces he puenteado la GPIO02 con la GPIO03 y segun mi programa pongo un 1 y un 0 a una frecuencia de 2.57Mhz
He usado para ello la libreria mmapGpio
¿Teneis alguna manera de hacerlo más rapido?
Por lo que he visto la culpa es de lo lenta que es leyendo del puerto, escribe a razon de 18.56 megamuestras por segundo pero lee a 6.63megamuestras.
No he usado overclocking
Acceder al hardware a través de librerías de alto nivel suele tener ese resultado, demasiadas capas de abstracción hacen que se ralentice todo mucho.
Prueba a usar la librería "bcm2835" que es de bajo-bajo nivel a ver si mejora...
bcm2835_init
bcm2835_gpio_write
Hecho y el resultado es:
Usando mmapGpio:
Read : 6.61Mhz
Write: 18.81Mhz
Usando bcm2835:
Read: 6.0Mhz
Write: 11.2-11.5Mhz
Además las mmapGpio al ser compiladas en vez de instaladas son mas fáciles de usar 🙂
El codigo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <chrono>
#include <bcm2835.h>
//Compile and link flags at geany:
//g++ -pthread -std=c++11 -o3 -Wall -c "%f"
//g++ -pthread -std=c++11 -Wall -o "%e" "%f" -lbcm2835
//configura gpio outputs e inputs:
void init_gpio();
//Lee estado del puerto de entrada
int lee_puerto(uint8_t puerto) { return bcm2835_gpio_lev(puerto);}
void pone_puerto(uint8_t puerto,uint8_t estado) { bcm2835_gpio_write(puerto, estado);}
using namespace std;
using namespace std::chrono;
class halla_tiempo_c
{
public:
high_resolution_clock::time_point t1,t2;
void inicia() { t1= high_resolution_clock::now(); }
double halla_tiempo() //retorna el tiempo en segundos
{
t2= high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
return time_span.count();
}
};
int main()
{
halla_tiempo_c tiempo1;
printf("nInicializo y compruebo GPIOs:n");
init_gpio();
printf("Signal 3 a 0:n");
pone_puerto(RPI_BPLUS_GPIO_J8_05,0);delay_ms(1);
int uart_str;
printf("nInicializo y compruebo RS232:n");
rs232_setup(uart_str);
if (uart_str == -1) return -1;
long i,maxi=10000000L,j=0;
tiempo1.inicia();
for (i=0;i<maxi;i++)
{
// j=lee_puerto(2);
// j+=lee_puerto(2);
pone_puerto(3,1);
pone_puerto(3,0);
}
double t2=tiempo1.halla_tiempo();
double frecuencia;
frecuencia=2.0*maxi/t2/1.0e6;
printf("nTiempo=%lg Frecuencia=%lg Mhzn",t2,frecuencia);
j=0;
pone_puerto(3,1);
j=lee_puerto(2);
// while( lee_puerto(2)!=1) j++;
printf("j=%lin",j);
return 1;
}
void init_gpio()
{
printf("bcm2835_init():n");
bcm2835_init();
printf("gpio02 input:n");
//GPIO2 inputs:
bcm2835_gpio_fsel( 2, BCM2835_GPIO_FSEL_INPT); //RPI_BPLUS_GPIO_J8_03 = GPIO2
//GPIO03 outputs:
printf("gpio03 output:n");
bcm2835_gpio_fsel( 3, BCM2835_GPIO_FSEL_OUTP); //RPI_BPLUS_GPIO_J8_05= GPIO3
}
Has consultado esto?: http://codeandlife.com/2012/07/03/benchmarking-raspberry-pi-gpio-speed/