1 месяц назад
История
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 с ошибкой