Приветствую, коллеги. Пытаюсь реализовать на STM32F103 поддержку RGB интерфейса (DATA[24], DataCLK, VSYNC, HSYNC, DataEN) для передачи изображения на матрицу матрицу hsd050idw1-a20. Изображение нужно только черно-белое (не градиент, а именно только черное и только белое), поэтому пытаюсь сделать аналогично данной
статье. Также использую SPI для формирования сигналов DATA[24] и DataCLK. Остальные сигналы реализуются просто на GPIO. Длительность этапов отправки данных формируются размером ДМА. То есть сформировал сигналы задал размер дма и запустил его, в прерывании завершения отправки дма переключаю сигналы в новое положение, задаю новый размер дма и запускаю отправку. и т.д. Естественно при каждом таком переходе образуется небольшая пауза в тактировании DataCLK. Собственно код прерывания дма следующий :
CODE
void LcdSpiHandler (void)
{
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_TXE) == RESET);
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_BSY) == SET);
switch(lcd->vState)
{
case(eLcdState_PULSE):
{
switch(lcd->hState)
{
case(eLcdState_PULSE):
{
GPIOSet(lcd->gpioHSync);
lcd->hState = eLcdState_BACK_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_BACK_PORCH):
{
lcd->hState = eLcdState_DATA;
DMASetCurrDataCounter(100, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_DATA):
{
lcd->hState = eLcdState_FRONT_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_FRONT_PORCH):
{
if(lcd->hNumber == 2)
{
GPIOSet(lcd->gpioVSync);
GPIOReset(lcd->gpioHSync);
lcd->vState = eLcdState_BACK_PORCH;
lcd->hState = eLcdState_PULSE;
lcd->hNumber = 0;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
}
else
{
GPIOReset(lcd->gpioHSync);
lcd->hNumber++;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
lcd->hState = eLcdState_PULSE;
DMACmd(ENABLE, lcd->spi->dmaTx);
}
break;
}
}
break;
}
case(eLcdState_BACK_PORCH):
{
switch(lcd->hState)
{
case(eLcdState_PULSE):
{
GPIOSet(lcd->gpioHSync);
lcd->hState = eLcdState_BACK_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_BACK_PORCH):
{
lcd->hState = eLcdState_DATA;
DMASetCurrDataCounter(100, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_DATA):
{
lcd->hState = eLcdState_FRONT_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_FRONT_PORCH):
{
if(lcd->hNumber == 28)
{
GPIOReset(lcd->gpioHSync);
lcd->vState = eLcdState_DATA;
lcd->hState = eLcdState_PULSE;
lcd->hNumber = 0;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
}
else
{
GPIOReset(lcd->gpioHSync);
lcd->hNumber++;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
lcd->hState = eLcdState_PULSE;
DMACmd(ENABLE, lcd->spi->dmaTx);
}
break;
}
}
break;
}
case(eLcdState_DATA):
{
switch(lcd->hState)
{
case(eLcdState_PULSE):
{
GPIOSet(lcd->gpioHSync);
lcd->hState = eLcdState_BACK_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_BACK_PORCH):
{
GPIOSet(lcd->gpioDe);
lcd->hState = eLcdState_DATA;
DMASetCurrDataCounter(100, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_DATA):
{
GPIOReset(lcd->gpioDe);
lcd->hState = eLcdState_FRONT_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_FRONT_PORCH):
{
if(lcd->hNumber == 479)
{
GPIOReset(lcd->gpioHSync);
lcd->vState = eLcdState_FRONT_PORCH;
lcd->hState = eLcdState_PULSE;
lcd->hNumber = 0;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
}
else
{
GPIOReset(lcd->gpioHSync);
lcd->hNumber++;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
lcd->hState = eLcdState_PULSE;
DMACmd(ENABLE, lcd->spi->dmaTx);
}
break;
}
}
break;
}
case(eLcdState_FRONT_PORCH):
{
switch(lcd->hState)
{
case(eLcdState_PULSE):
{
GPIOSet(lcd->gpioHSync);
lcd->hState = eLcdState_BACK_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_BACK_PORCH):
{
lcd->hState = eLcdState_DATA;
DMASetCurrDataCounter(100, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_DATA):
{
lcd->hState = eLcdState_FRONT_PORCH;
DMASetCurrDataCounter(5, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
break;
}
case(eLcdState_FRONT_PORCH):
{
if(lcd->hNumber == 12)
{
GPIOReset(lcd->gpioVSync);
GPIOReset(lcd->gpioHSync);
lcd->vState = eLcdState_PULSE;
lcd->hState = eLcdState_PULSE;
lcd->hNumber = 0;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
DMACmd(ENABLE, lcd->spi->dmaTx);
}
else
{
GPIOReset(lcd->gpioHSync);
lcd->hNumber++;
DMASetCurrDataCounter(6, lcd->spi->dmaTx);
lcd->hState = eLcdState_PULSE;
DMACmd(ENABLE, lcd->spi->dmaTx);
}
break;
}
}
break;
}
}
}
Но к сожалению так оно не взлетает. может есть способ как-то поумнее управлять сигналами управления, а не просто переключать в прерывании. К сожалению в вышеприведенной статье об этом не упоминается. Подскажите кто что думает.
Сообщение отредактировал IgorKossak - May 14 2017, 11:09
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!