Skocz do zawartości

Problem z wyświetlaczem OLED i animacją na nim


tospros99

Pomocna odpowiedź

Hej wszystkim!
Mam problem z animacją na wyświetlaczu SSD1331 OLED przy użyciu mikrokontrolera STM32F411VET6 Discovery. Głównym problemem jest migotanie animowanego obrazu, które próbowałem rozwiązać, wprowadzając podwójne buforowanie. Niestety, po implementacji tej metody pojawiły się inne problemy: obraz zmienia kolory, a na ekranie pojawiają się dziwne artefakty graficzne. Nie wiem gdzie leży problem jestem początkujący w temacie stm32 jak i w C, dlatego proszę o pomoc.
Mój kod:

 

uint8_t ssd1331_check_exposed_pixel(uint8_t x_min, uint8_t x_max, uint8_t y_min, uint8_t y_max, uint8_t pixel_value, uint8_t xppos, uint8_t yppos){
    if(xppos > x_max || xppos < x_min || yppos > y_max || yppos < y_min || pixel_value == 0x00){
        return 1;
    }
    return 0;

}
void ssd1331_draw_animation(uint8_t new_chXpos, uint8_t new_chYpos, uint8_t old_chXpos, uint8_t old_chYpos, const uint8_t *pchBmp, const uint8_t * pBackBmp, uint8_t chWidth, uint8_t chHeight){

    ssd1331_draw_bitmap(new_chXpos, new_chYpos, pchBmp, chWidth, chHeight, 0);
    uint16_t i, j;
    int16_t deltaX = (int16_t)(new_chXpos - old_chXpos);
    int16_t deltaY = (int16_t)(new_chYpos - old_chYpos);


    for(j = 0; j < chHeight + ((deltaY < 0) ? -deltaY : deltaY); j++){
        for(i = 0; i < chWidth + ((deltaX < 0) ? -deltaX : deltaX); i++){

            uint16_t x = (deltaX < 0) ? (uint16_t)(new_chXpos + i) : (uint16_t)(old_chXpos + i);
            uint16_t y = (deltaY < 0) ? (uint16_t)(new_chYpos + j) : (uint16_t)(old_chYpos + j);

            int16_t local_x = (int16_t)(x - new_chXpos);
            int16_t local_y = (int16_t)(y - new_chYpos);

            if (local_x >= 0 && local_x < chWidth && local_y >= 0 && local_y < chHeight) {
                uint16_t pixel_value = (uint16_t)((pchBmp[(local_y * chWidth + local_x) * 2] << 8)
                        | pchBmp[(local_y * chWidth + local_x) * 2 + 1]);


            if(ssd1331_check_exposed_pixel( ((deltaX > 0) ? (uint16_t)old_chXpos : (uint16_t)new_chXpos),
                                            ((deltaX > 0) ? (uint16_t)new_chXpos : (uint16_t)old_chXpos),
                                            ((deltaY > 0) ? (uint16_t)old_chYpos : (uint16_t)new_chYpos),
                                            ((deltaY > 0) ? (uint16_t)new_chYpos : (uint16_t)old_chYpos),
                                            pixel_value,
                                            x, y) ){
                uint16_t back_pixel = (uint16_t)((pBackBmp[(y * OLED_WIDTH + x) * 2] << 8) | pBackBmp[(y * OLED_WIDTH + x) * 2 + 1]);
                ssd1331_draw_point(x, y, back_pixel);
            }

        }
    }


}
}

void ssd1331_draw_bitmap(uint8_t chXpos, uint8_t chYpos, const uint8_t *pchBmp, uint8_t chWidth, uint8_t chHeight, uint16_t hwColor)
{
    uint16_t i, j;


    for(j = 0; j < chHeight; j++) {
        for(i = 0; i < chWidth; i++) {

            uint16_t pixelIndex = (j * chWidth + i) * 2;
            uint16_t color = (pchBmp[pixelIndex] << 8) | pchBmp[pixelIndex + 1];

            if(color != 0x0000)
                ssd1331_draw_point(chXpos + i, chYpos + j, color);
        }
    }
}

void ssd1331_draw_point(uint8_t chXpos, uint8_t chYpos, uint16_t hwColor) 
{
    if (chXpos >= OLED_WIDTH || chYpos >= OLED_HEIGHT) {
        return;
    }

    //set column point
    ssd1331_write_byte(SET_COLUMN_ADDRESS, SSD1331_CMD);
    ssd1331_write_byte(chXpos, SSD1331_CMD);
    ssd1331_write_byte(OLED_WIDTH - 1, SSD1331_CMD);
    //set row point
    ssd1331_write_byte(SET_ROW_ADDRESS, SSD1331_CMD);
    ssd1331_write_byte(chYpos, SSD1331_CMD);
    ssd1331_write_byte(OLED_HEIGHT - 1, SSD1331_CMD);
    
    //fill 16bit colour
    ssd1331_write_byte(hwColor >> 8, SSD1331_DATA);
    ssd1331_write_byte(hwColor, SSD1331_DATA);   
}

static void ssd1331_write_byte(uint8_t chData, uint8_t chCmd) 
{
    if (chCmd) {
        __SSD1331_DC_SET();
    } else {
        __SSD1331_DC_CLR();
    }
    
    __SSD1331_CS_CLR();
    __SSD1331_WRITE_BYTE(chData);
    
    __SSD1331_CS_SET();
    __SSD1331_DC_SET();
}

#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "SSD1331.h"
#include "grass_texture.h"
#include "golf_logo.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim10;

/* USER CODE BEGIN PV */

/*
 * ADC_Buffer[0] --> The x coordinate from joystick input
 * ADC_Buffer[1] --> The y coordinate from joystick input
 * ADC_Buffer[2] --> The Signal A from encoder input
 * ADC_Buffer[3] --> The Signal B from encoder input
 */

uint16_t ADC_Buffer[4];
uint8_t frame_update;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_SPI1_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM10_Init(void);
/* USER CODE BEGIN PFP */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
    uint8_t level = 0;
    uint8_t game_is_running = 1;
    uint8_t i, j = 4;

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_SPI1_Init();
  MX_TIM2_Init();
  MX_TIM10_Init();
  /* USER CODE BEGIN 2 */
    //ADC1/TIM2/OLED INICIALIZATION
    HAL_TIM_Base_Start(&htim2);
    HAL_TIM_Base_Start_IT(&htim10);


    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADC_Buffer, 4) != HAL_OK)
        Error_Handler();

    ssd1331_init();
    ssd1331_draw_bitmap(0, 0, image_data_grass_texture, 96, 64, 0);
    //ssd1331_draw_bitmap(16, 4, image_data_golf_logo, 64, 15, 0);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (game_is_running) {
        switch (level) {

        case 0:
            uint8_t lg_flag = 0;

            while (level == 0) {
                if (frame_update) {
                    if ((i < 9) && (lg_flag == 0)) {
                        i++;
                        //ssd1331_draw_animation(16, i, 16, j, image_data_golf_logo, image_data_grass_texture, 64, 15);
                        ssd1331_draw_animation(16, i, 16, j,
                                image_data_golf_logo, image_data_grass_texture,
                                64, 15);
                        j = i;
                        frame_update = 0;
                    } else {
                        lg_flag = 1;
                        j--;
                        ssd1331_draw_animation(16, j, 16, i,
                                image_data_golf_logo, image_data_grass_texture,
                                64, 15);
                        frame_update = 0;
                        i = j;
                        if ((i >= 4) && (i < 5))
                            lg_flag = 0;
                    }
                }

            }
            break;
        };

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    }

  /* USER CODE END 3 */
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM10) {
        frame_update = 1;
    }
}

 

Link do komentarza
Share on other sites

Naprawiłem już migotanie ale teraz pozostają paski po złym rozpoznawaniu odkrytych pikseli.... Nie wiem czy to co robię jest w ogóle dobrym podejście, czy ktoś wie jak mógłbym napisać taką funkcję wykorzystującą DMA? Zacząłem trochę z tym kombinować, ale póki co nawet nie wyświetla mi obrazu.
 

void set_window(uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end) {

    uint8_t column_command[] = {0x15, x_start, x_end};
    HAL_SPI_Transmit(&hspi1, column_command, sizeof(column_command), HAL_MAX_DELAY);


    uint8_t row_command[] = {0x75, y_start, y_end};
    HAL_SPI_Transmit(&hspi1, row_command, sizeof(row_command), HAL_MAX_DELAY);
}

void write_to_buffer(uint8_t chXpos, uint8_t chYpos, const uint8_t * pchBmp, uint8_t chWidth, uint8_t chHeight, uint8_t * frame_buffer){
	for(uint8_t j = 0; j < chHeight; j++){
			for(uint8_t i = 0; i < chWidth; i++){
				frame_buffer[chYpos + j*chWidth + i + chXpos] = pchBmp[j*chWidth + i];
			}
		}
}


int main(void)
{

  /* USER CODE BEGIN 1 */
	uint8_t level = 0;
	uint8_t game_is_running = 1;
	uint8_t i, j = 4;
	uint8_t * frame_buffer;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_SPI1_Init();
  MX_TIM2_Init();
  MX_TIM10_Init();
  /* USER CODE BEGIN 2 */
	//ADC1/TIM2/OLED INICIALIZATION
	HAL_TIM_Base_Start(&htim2);
	HAL_TIM_Base_Start_IT(&htim10);

	HAL_DMA_Init(&hdma_spi1_tx);

	if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADC_Buffer, 4) != HAL_OK)
		Error_Handler();

	ssd1331_init();
	ssd1331_draw_bitmap(0, 0, image_data_grass_texture, 96, 64, 0);
	//ssd1331_draw_bitmap(16, 4, image_data_golf_logo, 64, 15, 0);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (game_is_running) {
		switch (level) {

		case 0:
			uint8_t lg_flag = 0;
			frame_buffer = realloc(frame_buffer, sizeof(uint8_t)*64*19);
			write_to_buffer(0, 0, image_data_grass_texture, 64, 19, frame_buffer);
			while (level == 0) {
				if (frame_update) {

					if ((i < 9) && (lg_flag == 0)) {
						i++;
						set_window(16, 80, j, i + 15);
						write_to_buffer(0, 0, image_data_golf_logo, 64, 15, frame_buffer);
						HAL_SPI_Transmit_DMA(&hspi1, frame_buffer, sizeof(uint8_t)*64*19);
						//ssd1331_draw_animation(16, i, 16, j, image_data_golf_logo, image_data_grass_texture, 64, 15);
						//ssd1331_draw_animation(16, i, 16, j,
							//	image_data_golf_logo, image_data_grass_texture,
							//	64, 15);
						j = i;
						frame_update = 0;
					} else {
						lg_flag = 1;
						j--;
						set_window(16, 80, j, i + 15);
						write_to_buffer(0, 0, image_data_golf_logo, 64, 15, frame_buffer);
						HAL_SPI_Transmit_DMA(&hspi1, frame_buffer, sizeof(uint8_t)*64*19);

						//ssd1331_draw_animation(16, j, 16, i,
						//		image_data_golf_logo, image_data_grass_texture,
						//		64, 15);


						frame_update = 0;

						i = j;
						if ((i >= 4) && (i < 5))
							lg_flag = 0;
					}
				}

			}
			break;
		};

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	}
	free(frame_buffer);
  /* USER CODE END 3 */
}

 

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.