Перейти к содержанию
    

STM32F103 и ч/б RGB интерфейс

Приветствую, коллеги. Пытаюсь реализовать на STM32F103 поддержку RGB интерфейса (DATA[24], DataCLK, VSYNC, HSYNC, DataEN) для передачи изображения на матрицу матрицу hsd050idw1-a20. Изображение нужно только черно-белое (не градиент, а именно только черное и только белое), поэтому пытаюсь сделать аналогично данной статье. Также использую SPI для формирования сигналов DATA[24] и DataCLK. Остальные сигналы реализуются просто на GPIO. Длительность этапов отправки данных формируются размером ДМА. То есть сформировал сигналы задал размер дма и запустил его, в прерывании завершения отправки дма переключаю сигналы в новое положение, задаю новый размер дма и запускаю отправку. и т.д. Естественно при каждом таком переходе образуется небольшая пауза в тактировании DataCLK. Собственно код прерывания дма следующий :

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
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если FSMC использовать? Или на крайняк ногодрыг через DMA?

И да, для начала попробуйте просто повыкидывать все библиотечные функции из тела обработчика прерывания. Переключайте напрямую регистрами. Я с этой проблемой столкнулся, когда 1-wire делал. Если вызывать функции (я тогда opencm3 пользовался), то получались заметные выбросы, а если делать по-человечески, все было четко.

Изменено пользователем Эдди

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И да, для начала попробуйте просто повыкидывать все библиотечные функции из тела обработчика прерывания. Переключайте напрямую регистрами.

Переход на работу с регистрами к сожалению не исправил положение. FSMC тоже вряд ли поможет, там ведь также придется отдельно работать с сигналами управления. Остается попробовать ногодрыг через дма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А может кто-нибудь поделиться примером ногодрыга из дма по таймеру? Адекватных работающих примеров я не нагуглил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Соорудил все на ногодрыге из дма по таймеру. Но все равно матрица ничего не выдает. Такое ощущение что она вообще не воспринимает сигналы с стм. То есть без разницы включаю я питание и подаю сигналы или просто включаю питание логики без сигналов - реакция матрицы идентична: появляются некоторые вертикальные цветные линии. К сожалению нет под рукой логического анализатора, но то что можно увидеть по осцилографу - все как по даташиту матрицы.

Изменено пользователем Ruslan-maniak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В коде из первого сообщения неверная полярность DE - он должен быть в '1' при активных данных. HS и VS вообще не нужны, работайте в DE-mode.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В коде из первого сообщения неверная полярность DE - он должен быть в '1' при активных данных. HS и VS вообще не нужны, работайте в DE-mode.

В коде с полярностью все верно. По DE подается именно '1' когда передаются данные. Спасибо что натолкнули на DE mode. Не знал про него. Только в даташите на матрицу не указаны параметры для реализации этого режима.

Изменено пользователем Ruslan-maniak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только в даташите на матрицу не указаны параметры для реализации этого режима.

Переведите HS и VS в третье стостояние, а DE управляйте как обычно - это и будет DE-mode.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Переведите HS и VS в третье стостояние, а DE управляйте как обычно - это и будет DE-mode.

Третье состояние - это оставить в воздухе? Все так и сделал. Глянул осцилом - все как надо. Но все равно результат не изменился. Надо искать логический анализатор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оказалось что сигнал клока не заходил в шлейф. Исправил. Теперь в DE mode все работает как надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...