README.md

K1948BK018_ST7735s_160x80_SPI0_DMA_512

Первый опыт использования DMA на микроконтроллере к1948вк018

Развитие предыдущего проекта «K1948BK018_ST7735s_160x80_SPI0_4»

ПРОБЛЕМА В ТОМ, ЧТО МЕТОД С ПОСЫЛКОЙ И ОЖИДАНИЕМ ОДНОГО БАЙТА ВПОЛНЕ АДЕКВАТНО РАБОТАЕТ :

void ST7735s_class::data(uint8_t d)
{
  HAL_SPI_Enable  ( &h_spi ) ;
         HAL_DMA_Start ( &h_dma_ch0, (void*)&d, (void*)&h_spi.Instance->TXDATA, 0/* всего один байт */ ) ;
    if ( HAL_DMA_Wait  ( &h_dma_ch0, DMA_TIMEOUT_DEFAULT ) != HAL_OK ) xprintf ( "DMA timeout\r\n" ) ;
  HAL_SPI_Disable ( &h_spi ) ;
}

А В МЕТОДЕ, КОТОРЫЙ ПОСЫЛАЕТ ПАЧКИ БАЙТОВ ОБЪЁМОМ В ПОЛ-КИЛОБАЙТА, НЕОБХОДИМА ИСКУССТВЕННАЯ ПАУЗА (*) :

void ST7735s_class::draw(uint16_t const* picture)
{
    command4(/* CASET */0x2A, 0, yoff, 0, yoff + ysize - 1);
    command4(/* RASET */0x2B, 0, xoff, 0, xoff + xsize - 1);
    command (/* RAMWR */0x2C);
    uint16_t const* p = &picture[2];
    static constexpr uint16_t N = 256/* пикселей = пол-кило-байтов */;
    uint32_t size = xsize * ysize / N ; /// количество порций величиной в N * sizeof(uint16_t)
    while ( size-- )
    {
        /* ЭТОГО НЕ НУЖНО, ЕСЛИ <<picture>> ПРАВИЛЬНО КОНВЕРТИРОВАНА */
           uint16_t t [ N ] ; for ( uint16_t i = 0; i < N; i++ ) t[i] = ~ ( p[i] << 8 | p[i] >> 8 ) ;
        HAL_SPI_Enable  ( &h_spi ) ;
            HAL_DMA_Start ( &h_dma_ch0, (void*)t, (void*)&h_spi.Instance->TXDATA, N * sizeof(uint16_t) /* байтов */ - 1 ) ;
            volatile uint32_t i = 0; while ( i < 1500 ) i++; /// (*) НЕОБХОДИМАЯ ПАУЗА, ПОТОМУ ЧТО <<HAL_DMA_Wait>> ЗДЕСЬ НЕ РАБОТАЕТ (???)
            /// HAL_DMA_Wait ( &h_dma_ch0, DMA_TIMEOUT_DEFAULT ) <--- здесь не работает почему-то !
        HAL_SPI_Disable ( &h_spi ) ;
        p += N;
    }
}

Рассуждения на эту тему

void ST7735s_class::init()
{
  h_spi.Instance = SPI_0;
  /* Режим SPI */
     h_spi.Init.SPI_Mode = HAL_SPI_MODE_MASTER;
  /* Настройки */
     h_spi.Init.CLKPhase    = SPI_PHASE_ON;
     h_spi.Init.CLKPolarity = SPI_POLARITY_LOW;
     h_spi.Init.ThresholdTX = 4;
  /* Настройки для ведущего */
     h_spi.Init.BaudRateDiv = SPI_BAUDRATE_DIV4; /// !!!
     h_spi.Init.Decoder     = SPI_DECODER_NONE;
     h_spi.Init.ManualCS    = SPI_MANUALCS_OFF;
     h_spi.Init.ChipSelect  = SPI_CS_NONE;
     if ( HAL_SPI_Init(&h_spi) != HAL_OK ) xprintf ( "SPI_Init_Error\r\n" ) ;
  DMA_Init();
  <...>
}

SPI_BAUDRATE_DIV4 - это минимально возможный делитель, насколько я понимаю.
Т.е. 32 МГц / 4 = 8 МГц - частота передачи битов, значит
Частота передачи байтов (8 битов), вероятнее всего, составляет 1 МГц (период 1 мкс)
Время передачи всего кадра (изображения на индикатор) составляет
{ (xsize * ysize * 2) = (160 * 80 * 2) = 25'600 байтов }
25,6 миллисекунд
terminal_2M_baud__ST7735s_SPI_DMA_512.png => ~ 50 миллисекунд, значит есть надежда ещё сократить время передачи кадра
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Это можно сделать, если в искусственную паузу внести конвертацию порций картинки и др.действия, ведь DMA-канал должен передавать данные не зависимо от ядра.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Среда разработки: ECLIPSE & GCC-RISC-V-v12.2.1

Описание

Первый опыт использования DMA на микроконтроллере к1948вк018 для передачи изображения на дисплей (SPI)

Конвейеры
0 успешных
0 с ошибкой