@taburyak я таки розібрався!
Справа в тому що екран повертає дані в форматі 888. Тобто для зчитування одного пікселю треба зробити два рази Read по 16 біт в результаті отримаємо два шматка: [R1G1][B1R2]. З яких забираємо три байти кольору, і потім ще треба привести до формату 565 (у мене для цього є окрема функція)
Ввідні дані: весь екран залитий кольором 0x1234, один піксель залив 0x4321.
Ось тут зробив послідовно десять разів LCD_RD_Data() в масив temp. (нульова ячейка - dummy read)

як бачиш паттерн повторюється 10 44 a4 (це у 888 що відповідає 0x1234 у форматі 565) - фоновий колір. А наш пацієнт це 40 64 08 (це у 888 форматі відповідає 0x4321 у форматі 565) - колір замальованого пікселя.
Функція що робить перетворення 888 -> 565:
/**
* \brief Calculate 16Bit-RGB
*
* \param r Red
* \param g Green
* \param b Blue
*
* \return uint16_t 16Bit-RGB
*/
uint16_t LCD_Color565(uint8_t r, uint8_t g, uint8_t b) {
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}
Плюс не потрібно виставляти ціле вікно для отримання пікселю, достатньо виставити лише лівий верхній кут. Ось так виглядає функція ReadPixel:
/**
* \brief Reads a point from the specified coordinates
*
* \param x x-Coordinate
* \param y y-Coordinate
*
* \return uint16_t Color
*/
uint16_t LCD_ReadPixel(int16_t x, int16_t y) {
uint16_t temp[3];
// Clip
if ((x < 0) || (y < 0) || (x >= TFTWIDTH) || (y >= TFTHEIGHT))
return;
LCD_WR_REG(ILI9341_COLADDRSET);
LCD_WR_Data(x >> 8);
LCD_WR_Data(x & 0xFF);
LCD_WR_REG(ILI9341_PAGEADDRSET);
LCD_WR_Data(y >> 8);
LCD_WR_Data(y & 0xFF);
LCD_WR_REG(ILI9341_MEMORYREAD);
temp[0] = LCD_RD_Data(); // dummy read
temp[1] = LCD_RD_Data();
temp[2] = LCD_RD_Data();
return LCD_Color565((temp[1] >> 8) & 0xFF, temp[1] & 0xFF, (temp[2] >> 8) & 0xFF);
}
Ось так у мене виглядає DrawPixel - ставлю тільки x,y (без другої точки кінця вікна):
/**
* \brief Draws a point at the specified coordinates
*
* \param x x-Coordinate
* \param y y-Coordinate
* \param color Color
*
* \return void
*/
void LCD_DrawPixel(int16_t x, int16_t y, uint16_t color) {
// Clip
if ((x < 0) || (y < 0) || (x >= TFTWIDTH) || (y >= TFTHEIGHT))
return;
LCD_WR_REG(ILI9341_COLADDRSET);
LCD_WR_Data(x >> 8);
LCD_WR_Data(x & 0xFF);
LCD_WR_REG(ILI9341_PAGEADDRSET);
LCD_WR_Data(y >> 8);
LCD_WR_Data(y & 0xFF);
LCD_WR_REG(ILI9341_MEMORYWRITE);
LCD_WR_Data(color);
}
І пам'ятаєш казав у тебе правильно працює але невірно зроблена функція SetWindow - переплутані місцями x1, x2, y1, y2 і в аргументах і всередині. Потрібно передавати
LCD_SetAddrWindow (x1, y1, x2, y2)
І тоді в CASET писати х1/х2, а в PASET - y1/y2. А у тебе навпаки 
Сама функція:
/**
* \brief Sets window address
*
* \param x1 Left top window x-coordinate
* \param y1 Left top window y-coordinate
* \param x2 Rigth bottom window x-coordinate
* \param y2 Rigth bottom window y-coordinate
*
* \return void
*/
void LCD_SetAddrWindow(int x1, int y1, int x2, int y2) {
LCD_WR_REG(ILI9341_COLADDRSET);
LCD_WR_Data(x1 >> 8);
LCD_WR_Data(x1 & 0xFF);
LCD_WR_Data(x2 >> 8);
LCD_WR_Data(x2 & 0xFF);
LCD_WR_REG(ILI9341_PAGEADDRSET);
LCD_WR_Data(y1 >> 8);
LCD_WR_Data(y1 & 0xFF);
LCD_WR_Data(y2 >> 8);
LCD_WR_Data(y2 & 0xFF);
LCD_WR_REG(ILI9341_MEMORYWRITE);
}