ILI9341 Biblioteca para arduino

0

Estoy escribiendo una biblioteca de arduino para la pantalla tft ILI9341. Intenté escribir en la pantalla pero no aparece nada. ¿Por qué? ¿Cómo puedo resolver el problema?

Mi código fuente:

    /* DISPLAY PINS */
#define LCD_RST A4    //reset
#define LCD_CS A3
#define LCD_RS A2
#define LCD_WR A1
#define LCD_RD A0



#define LCD_D0 8
#define LCD_D1 9
#define LCD_D2 2
#define LCD_D3 3
#define LCD_D4 4
#define LCD_D5 5
#define LCD_D6 6
#define LCD_D7 7





void setup()
{

    delay(1000);
    //init serial
    Serial.begin(9600);

    //init digital pins
    initLcdPins();
    delay(100);

    setPower1();
    memoryAccessControl();
    setPixelFormat(18);


    displayOn();

    delay(100);
    setCol();
    setPage();
    writeMemory();
}

// Add the main program code into the continuous loop() function
void loop()
{


}




void initLcdPins() {
    pinMode(LCD_RST, OUTPUT);
    pinMode(LCD_CS, OUTPUT);
    pinMode(LCD_RS, OUTPUT);
    pinMode(LCD_WR, OUTPUT);
    pinMode(LCD_RD, OUTPUT);
    pinMode(LCD_D0, OUTPUT);
    pinMode(LCD_D1, OUTPUT);
    pinMode(LCD_D2, OUTPUT);
    pinMode(LCD_D3, OUTPUT);
    pinMode(LCD_D4, OUTPUT);
    pinMode(LCD_D5, OUTPUT);
    pinMode(LCD_D6, OUTPUT);
    pinMode(LCD_D7, OUTPUT);


    digitalWrite(LCD_RST, HIGH);
    digitalWrite(LCD_CS, HIGH);
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_WR, HIGH);
    digitalWrite(LCD_RD, HIGH);



    digitalWrite(LCD_D0, 0);
    digitalWrite(LCD_D1, 0);
    digitalWrite(LCD_D2, 0);
    digitalWrite(LCD_D3, 0);
    digitalWrite(LCD_D4, 0);
    digitalWrite(LCD_D5, 0);
    digitalWrite(LCD_D6, 0);
    digitalWrite(LCD_D7, 0);


}



void  setAddress(byte d7, byte d6, byte d5, byte d4, byte d3, byte d2, byte d1, byte d0) {



    //SEND COMMAND TO THE ILI9341
    digitalWrite(LCD_RST, HIGH);
    digitalWrite(LCD_CS, HIGH);
    digitalWrite(LCD_RS, LOW);
    digitalWrite(LCD_WR, LOW);
    digitalWrite(LCD_RD, HIGH);

        delay(10);


    //SET BYTE
    digitalWrite(LCD_D0, d0);
    digitalWrite(LCD_D1, d1);
    digitalWrite(LCD_D2, d2);
    digitalWrite(LCD_D3, d3);
    digitalWrite(LCD_D4, d4);
    digitalWrite(LCD_D5, d5);
    digitalWrite(LCD_D6, d6);
    digitalWrite(LCD_D7, d7);



    delay(10);

    digitalWrite(LCD_WR, HIGH);

    delay(10);
    digitalWrite(LCD_RS, HIGH);

    digitalWrite(LCD_D0, 0);
    digitalWrite(LCD_D1, 0);
    digitalWrite(LCD_D2, 0);
    digitalWrite(LCD_D3, 0);
    digitalWrite(LCD_D4, 0);
    digitalWrite(LCD_D5, 0);
    digitalWrite(LCD_D6, 0);
    digitalWrite(LCD_D7, 0);



    delay(20);

}

void setParameter(byte d7, byte d6, byte d5, byte d4, byte d3, byte d2, byte d1, byte d0) {





    digitalWrite(LCD_RST, HIGH);
    digitalWrite(LCD_CS, HIGH);
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_WR, LOW);
    digitalWrite(LCD_RD, HIGH);



    delay(10);


    digitalWrite(LCD_D0, d0);
    digitalWrite(LCD_D1, d1);
    digitalWrite(LCD_D2, d2);
    digitalWrite(LCD_D3, d3);
    digitalWrite(LCD_D4, d4);
    digitalWrite(LCD_D5, d5);
    digitalWrite(LCD_D6, d6);
    digitalWrite(LCD_D7, d7);


    delay(10);

    digitalWrite(LCD_WR, HIGH);

    delay(10);




    digitalWrite(LCD_D0, 0);
    digitalWrite(LCD_D1, 0);
    digitalWrite(LCD_D2, 0);
    digitalWrite(LCD_D3, 0);
    digitalWrite(LCD_D4, 0);
    digitalWrite(LCD_D5, 0);
    digitalWrite(LCD_D6, 0);
    digitalWrite(LCD_D7, 0);

    delay(20);
}


void setPower1() {
    setAddress(1 ,1, 0, 0, 0, 0, 0, 0);

    setParameter(0, 0, 1, 0, 1, 0, 1, 1);
}

void setCol() {
    setAddress(0, 0, 1, 0, 1, 0, 1, 0);


    setParameter(0, 0, 0, 0, 0, 0, 0, 0 );  //SC
    setParameter(0, 0, 0, 0, 0, 0, 0, 1);  //EC



}

void setPage() {

    setAddress(0, 0, 1, 0, 1, 0, 1, 1);


    setParameter(0, 0, 0, 0, 0, 0, 0, 0);  //SC
    setParameter(0, 0, 0, 0, 0, 0, 0, 1);  //EC

}



void writeMemory() {
    setAddress(0, 0, 1, 0, 1, 1, 0, 0);


    setParameter(0, 0, 0, 0, 0, 0, 0, 0); 
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);


    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);


    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);

    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);
    setParameter(0, 0, 0, 0, 0, 0, 0, 0);




}


void setPixelFormat(int format) {


    setAddress(0, 0, 1, 1, 1, 0, 1, 0);


    if (format == 16) {
        setParameter(0, 1, 0, 1, 0, 1, 0, 1);
    }
    else if (format == 18) {
        setParameter(0, 1, 1, 0, 0, 1, 1, 0);
    }


}







void displayOn() {
    setAddress(0, 0, 1, 0, 1, 0, 0, 1);


}


void memoryAccessControl() {
    setAddress(0, 0, 1,1, 0, 1, 1, 1);

    setParameter(0, 1, 0, 0, 1, 0, 0, 0);
}

La hoja de datos del ILI9341: Link

Editar:

He actualizado el código fuente pero la pantalla todavía no muestra nada. ¿Tienes alguna sugerencia?

El código fuente actualizado:

/* DISPLAY PINS */
#define LCD_RST A4    //reset
#define LCD_CS A3
#define LCD_RS A2
#define LCD_WR A1
#define LCD_RD A0



#define LCD_D0 8
#define LCD_D1 9
#define LCD_D2 2
#define LCD_D3 3
#define LCD_D4 4
#define LCD_D5 5
#define LCD_D6 6
#define LCD_D7 7





/* DISPLAY REGISTERS*/

#define SLEEP_OUT 0x11
#define COLUMN_ADDRESS_SET 0x2A
#define PAGE_ADDRESS_SET 0x2B
#define MEMORY_WRITE 0x2C
#define MEMORY_ACCESS_CONTROL 0x36
#define PIXEL_FORMAT_SET 0x3A
#define POWER_CONTROL_1 0xC0
#define DISPLAY_ON 0x29










void setup()
{

//  delay(1000);
    //init serial
    Serial.begin(9600);

    //init digital pins
    initLcdPins();
    delay(100);

    setPower1();
    delay(100);
    memoryAccessControl();
    delay(100);
    setPixelFormat(18);
    delay(100);


    displayOn();
    delay(100);




    delay(100);
    setCol();
    delay(100);
    setPage();
    delay(100);
    writeMemory();


    sleepOut();
}

// Add the main program code into the continuous loop() function
void loop()
{


}




void initLcdPins() {
    pinMode(LCD_RST, OUTPUT);
    pinMode(LCD_CS, OUTPUT);
    pinMode(LCD_RS, OUTPUT);
    pinMode(LCD_WR, OUTPUT);
    pinMode(LCD_RD, OUTPUT);
    pinMode(LCD_D0, OUTPUT);
    pinMode(LCD_D1, OUTPUT);
    pinMode(LCD_D2, OUTPUT);
    pinMode(LCD_D3, OUTPUT);
    pinMode(LCD_D4, OUTPUT);
    pinMode(LCD_D5, OUTPUT);
    pinMode(LCD_D6, OUTPUT);
    pinMode(LCD_D7, OUTPUT);


    digitalWrite(LCD_RST, HIGH);
    digitalWrite(LCD_CS, HIGH);
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_WR, HIGH);
    digitalWrite(LCD_RD, HIGH);



    digitalWrite(LCD_D0, 0);
    digitalWrite(LCD_D1, 0);
    digitalWrite(LCD_D2, 0);
    digitalWrite(LCD_D3, 0);
    digitalWrite(LCD_D4, 0);
    digitalWrite(LCD_D5, 0);
    digitalWrite(LCD_D6, 0);
    digitalWrite(LCD_D7, 0);


}



void setAddress(byte data) {
    //SEND COMMAND TO THE ILI9341
    digitalWrite(LCD_RST, HIGH);
    digitalWrite(LCD_CS, HIGH);
    digitalWrite(LCD_RS, LOW);
    digitalWrite(LCD_WR, LOW);
    digitalWrite(LCD_RD, HIGH);

    delay(10);


    //SET BYTE
    digitalWrite(LCD_D0, (data >> 0) & 0x01);
    digitalWrite(LCD_D1, (data >> 1) & 0x01);
    digitalWrite(LCD_D2, (data >> 2) & 0x01);
    digitalWrite(LCD_D3, (data >> 3) & 0x01);
    digitalWrite(LCD_D4, (data >> 4) & 0x01);
    digitalWrite(LCD_D5, (data >> 5) & 0x01);
    digitalWrite(LCD_D6, (data >> 6) & 0x01);
    digitalWrite(LCD_D7, (data >> 7) & 0x01);


    delay(10);

    digitalWrite(LCD_WR, HIGH);

    delay(10);
    digitalWrite(LCD_RS, HIGH);

    digitalWrite(LCD_D0, 0);
    digitalWrite(LCD_D1, 0);
    digitalWrite(LCD_D2, 0);
    digitalWrite(LCD_D3, 0);
    digitalWrite(LCD_D4, 0);
    digitalWrite(LCD_D5, 0);
    digitalWrite(LCD_D6, 0);
    digitalWrite(LCD_D7, 0);

    delay(20);

}



void setParameter(byte data) {





    digitalWrite(LCD_RST, HIGH);
    digitalWrite(LCD_CS, HIGH);
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_WR, LOW);
    digitalWrite(LCD_RD, HIGH);



    delay(10);

    //SET BYTE
    digitalWrite(LCD_D0, (data >> 0) & 0x01);
    digitalWrite(LCD_D1, (data >> 1) & 0x01);
    digitalWrite(LCD_D2, (data >> 2) & 0x01);
    digitalWrite(LCD_D3, (data >> 3) & 0x01);
    digitalWrite(LCD_D4, (data >> 4) & 0x01);
    digitalWrite(LCD_D5, (data >> 5) & 0x01);
    digitalWrite(LCD_D6, (data >> 6) & 0x01);
    digitalWrite(LCD_D7, (data >> 7) & 0x01);


    delay(10);

    digitalWrite(LCD_WR, HIGH);

    delay(10);




    digitalWrite(LCD_D0, 0);
    digitalWrite(LCD_D1, 0);
    digitalWrite(LCD_D2, 0);
    digitalWrite(LCD_D3, 0);
    digitalWrite(LCD_D4, 0);
    digitalWrite(LCD_D5, 0);
    digitalWrite(LCD_D6, 0);
    digitalWrite(LCD_D7, 0);

    delay(20);
}






void setPower1() {
    setAddress(POWER_CONTROL_1);

    setParameter(0x2B);
}






void setCol() {


    setAddress(COLUMN_ADDRESS_SET);


    setParameter(0x0 );  //SC
    setParameter(0x5);  //EC



}





void setPage() {

    setAddress(PAGE_ADDRESS_SET);


    setParameter(0x0);  //SC
    setParameter(0x5);  //EC

}



void writeMemory() {
    setAddress(MEMORY_WRITE);




    for (int i = 0; i < (18*25); i++) {
        setParameter(i);
    }
}


void setPixelFormat(int format) {


    setAddress(PIXEL_FORMAT_SET);




    if (format == 16) {
        setParameter(0x55);
    }
    else if (format == 18) {
        setParameter(0x66);
    }


}







void displayOn() {
    setAddress(DISPLAY_ON);


}


void memoryAccessControl() {
    setAddress(MEMORY_ACCESS_CONTROL);

    setParameter(0x48);
}





void sleepOut() {
    setAddress(SLEEP_OUT);
}

EDITAR:

/* DISPLAY REGISTERS*/

#define SLEEP_OUT 0x11
#define COLUMN_ADDRESS_SET 0x2A
#define PAGE_ADDRESS_SET 0x2B
#define MEMORY_WRITE 0x2C
#define MEMORY_ACCESS_CONTROL 0x36
#define PIXEL_FORMAT_SET 0x3A
#define POWER_CONTROL_1 0xC0
#define DISPLAY_ON 0x29
#define GAMMA_SET 0x26
#define DISPLAY_BRIGHTNESS 0x51







// adapted from LCD_ID_Reader from http://misc.ws/lcd_information
// controllers either read as 16-bit or as a sequence of 8-bit values

//-- Arduino UNO or Mega 2560 Plugged as shield
#define LCD_RST A4
#define LCD_CS A3
#define LCD_RS A2
#define LCD_WR A1
#define LCD_RD A0

#define LCD_D0 8
#define LCD_D1 9
#define LCD_D2 2
#define LCD_D3 3
#define LCD_D4 4
#define LCD_D5 5
#define LCD_D6 6
#define LCD_D7 7

void setup()
{
    Serial.begin(9600);

    lcdInit();
    lcdReset();      //ensures that controller is in default state
                     //    for (uint16_t i = 0; i < 256; i++) readReg(i, 7, "f.k"); 




    delay(500);

    setPixelFormat(18);



    setCol(0, 0xA);
    setPage(0, 0xA);

    writeMemory(0xA, 0xA);





}

void loop()
{
    // put your main code here, to run repeatedly:

}

void printhex(uint8_t val)
{
    if (val < 0x10) Serial.print("0");
    Serial.print(val, HEX);
}

void readReg(uint16_t reg, uint8_t n, const char *msg)
{
    uint8_t val8;
    lcdReset();
    lcdSetWriteDir();
    lcdWriteCommand(0xB0);     //Command Access Protect
    lcdWriteData(0x00);        //looks wrong
                               /*
                               lcdWriteCommand(0xF6);
                               lcdWriteData(0x01);
                               lcdWriteData(0x01);
                               lcdWriteData(0x03);
                               */
    lcdWriteCommand(reg);
    Serial.print("reg(0x");
    printhex(reg >> 8);
    printhex(reg);
    Serial.print(")");
    lcdSetReadDir();
    while (n--) {
        val8 = lcdReadData8();
        Serial.print(" ");
        printhex(val8);
    }
    lcdSetWriteDir();
    Serial.print("\t");
    Serial.println(msg);
}

void lcdInit()
{
    pinMode(LCD_CS, OUTPUT);
    digitalWrite(LCD_CS, HIGH);
    pinMode(LCD_RS, OUTPUT);
    digitalWrite(LCD_RS, HIGH);
    pinMode(LCD_WR, OUTPUT);
    digitalWrite(LCD_WR, HIGH);
    pinMode(LCD_RD, OUTPUT);
    digitalWrite(LCD_RD, HIGH);
    pinMode(LCD_RST, OUTPUT);
    digitalWrite(LCD_RST, HIGH);
}

void lcdReset()
{
    digitalWrite(LCD_RST, LOW);
    delay(2);
    digitalWrite(LCD_RST, HIGH);
    delay(10);             //allow controller to re-start
}

void lcdWrite8(uint16_t data)
{
    digitalWrite(LCD_D0, data & 1);
    digitalWrite(LCD_D1, (data & 2) >> 1);
    digitalWrite(LCD_D2, (data & 4) >> 2);
    digitalWrite(LCD_D3, (data & 8) >> 3);
    digitalWrite(LCD_D4, (data & 16) >> 4);
    digitalWrite(LCD_D5, (data & 32) >> 5);
    digitalWrite(LCD_D6, (data & 64) >> 6);
    digitalWrite(LCD_D7, (data & 128) >> 7);
}

uint16_t lcdRead8()
{
    uint16_t result = digitalRead(LCD_D7);
    result <<= 1;
    result |= digitalRead(LCD_D6);
    result <<= 1;
    result |= digitalRead(LCD_D5);
    result <<= 1;
    result |= digitalRead(LCD_D4);
    result <<= 1;
    result |= digitalRead(LCD_D3);
    result <<= 1;
    result |= digitalRead(LCD_D2);
    result <<= 1;
    result |= digitalRead(LCD_D1);
    result <<= 1;
    result |= digitalRead(LCD_D0);

    return result;
}

void lcdSetWriteDir()
{
    pinMode(LCD_D0, OUTPUT);
    pinMode(LCD_D1, OUTPUT);
    pinMode(LCD_D2, OUTPUT);
    pinMode(LCD_D3, OUTPUT);
    pinMode(LCD_D4, OUTPUT);
    pinMode(LCD_D5, OUTPUT);
    pinMode(LCD_D6, OUTPUT);
    pinMode(LCD_D7, OUTPUT);
}


void lcdSetReadDir()
{
    pinMode(LCD_D0, INPUT);
    pinMode(LCD_D1, INPUT);
    pinMode(LCD_D2, INPUT);
    pinMode(LCD_D3, INPUT);
    pinMode(LCD_D4, INPUT);
    pinMode(LCD_D5, INPUT);
    pinMode(LCD_D6, INPUT);
    pinMode(LCD_D7, INPUT);
}

void lcdWriteData(uint16_t data)
{
    lcdSetWriteDir();
    digitalWrite(LCD_CS, LOW);
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_RD, HIGH);
    digitalWrite(LCD_WR, HIGH);

    lcdWrite8(data >> 8);

    digitalWrite(LCD_WR, LOW);
    delayMicroseconds(10);
    digitalWrite(LCD_WR, HIGH);

    lcdWrite8(data);

    digitalWrite(LCD_WR, LOW);
    delayMicroseconds(10);
    digitalWrite(LCD_WR, HIGH);

    digitalWrite(LCD_CS, HIGH);
}

void lcdWriteCommand(uint16_t command)
{
    lcdSetWriteDir();
    digitalWrite(LCD_CS, LOW);
    digitalWrite(LCD_RS, LOW);
    digitalWrite(LCD_RD, HIGH);
    digitalWrite(LCD_WR, HIGH);
    lcdWrite8(command >> 8);
    digitalWrite(LCD_WR, LOW);
    delayMicroseconds(10);
    digitalWrite(LCD_WR, HIGH);
    lcdWrite8(command);
    digitalWrite(LCD_WR, LOW);
    delayMicroseconds(10);
    digitalWrite(LCD_WR, HIGH);
    digitalWrite(LCD_CS, HIGH);
}

uint8_t lcdReadData8()
{
    uint8_t result;
    lcdSetReadDir();
    digitalWrite(LCD_CS, LOW);
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_RD, HIGH);
    digitalWrite(LCD_WR, HIGH);

    digitalWrite(LCD_RD, LOW);
    delayMicroseconds(10);
    result = lcdRead8();
    digitalWrite(LCD_RD, HIGH);

    delayMicroseconds(10);

    return result;
}


uint16_t lcdReadData16()
{
    uint16_t result;
    result = lcdReadData8() << 8;
    result |= lcdReadData8();
    return result;
}


void lcdWriteRegister(uint16_t addr, uint16_t data)
{
    lcdWriteCommand(addr);
    lcdWriteData(data);
}







void setCol(uint16_t from, uint16_t at) {


    lcdWriteCommand(COLUMN_ADDRESS_SET);


    lcdWriteData(from);  //SC
    lcdWriteData(at);  //EC



}
void setPage(uint16_t from, uint16_t at){

    lcdWriteCommand(PAGE_ADDRESS_SET);

    lcdWriteData(from);  //SP
    lcdWriteData(at);  //EP

}
void writeMemory(uint16_t data, uint16_t b) {





    lcdWriteCommand(MEMORY_WRITE);

    //setParameter(data);





    for (int i = 0; i < data; i++) {
        for (int j = 0; j < b; j++)
        {
            //16 BIT COLORS
            lcdWriteData(0xFFFF);

        }
    }

}

void setPixelFormat(int format) {


    lcdWriteCommand(PIXEL_FORMAT_SET);




    if (format == 16) {
        lcdWriteData(0x55);
    }
    else if (format == 18) {
        lcdWriteData(0x66);
    }


}
    
pregunta jhon tonini

1 respuesta

1

Me di cuenta de que la dirección que das en memoryAccessControl() es 0x37 (Dirección de inicio de desplazamiento vertical) no 0x36.

También debe usar el comando de inactividad 0x11 en su función setup ().

Editar: cambios de selección de chip

void setPower1() {
    digitalWrite(LCD_CS, LOW);
    setAddress(POWER_CONTROL_1);
    setParameter(0x2B);
    digitalWrite(LCD_CS, HIGH);
}

void setCol() {
    digitalWrite(LCD_CS, LOW);
    setAddress(COLUMN_ADDRESS_SET);
    setParameter( 0x0 );  //SC
    setParameter( 0x5 );  //EC
    digitalWrite(LCD_CS, HIGH);
}

void setPage() {
    digitalWrite(LCD_CS, LOW);
    setAddress(PAGE_ADDRESS_SET);
    setParameter(0x0);  //SC
    setParameter(0x5);  //EC
    digitalWrite(LCD_CS, HIGH);
}


void writeMemory() {
    digitalWrite(LCD_CS, LOW);
    setAddress(MEMORY_WRITE);
    for (int i = 0; i < (18*25); i++) {
        setParameter(i);
    }
    digitalWrite(LCD_CS, HIGH);
}


void setPixelFormat(int format) {
    digitalWrite(LCD_CS, LOW);
    setAddress(PIXEL_FORMAT_SET);
    if (format == 16) {
        setParameter(0x55);
    }
    else if (format == 18) {
        setParameter(0x66);
    }

    digitalWrite(LCD_CS, HIGH);
}

void displayOn() {
    digitalWrite(LCD_CS, LOW);
    setAddress(DISPLAY_ON);
    digitalWrite(LCD_CS, HIGH);
}


void memoryAccessControl() {
    digitalWrite(LCD_CS, LOW);
    setAddress(MEMORY_ACCESS_CONTROL);
    setParameter(0x48);
    digitalWrite(LCD_CS, HIGH);
}

void sleepOut() {
    digitalWrite(LCD_CS, LOW);
    setAddress(SLEEP_OUT);
    digitalWrite(LCD_CS, HIGH);
}
void setAddress(byte data) {
    //SEND COMMAND TO THE ILI9341
    digitalWrite(LCD_RST, HIGH);
    //digitalWrite(LCD_CS, HIGH);  <--------
    digitalWrite(LCD_RS, LOW);
    digitalWrite(LCD_WR, LOW);
    digitalWrite(LCD_RD, HIGH);
    /*rest of the function*/
}
void setParameter(byte data) {
    digitalWrite(LCD_RST, HIGH);
    //digitalWrite(LCD_CS, HIGH);  <--------
    digitalWrite(LCD_RS, HIGH);
    digitalWrite(LCD_WR, LOW);
    digitalWrite(LCD_RD, HIGH);
    /*rest of the function*/
}
    
respondido por el Adam VZ

Lea otras preguntas en las etiquetas