реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> STM32F103C8T - перезапуск таймера от внешнего сигнала
varvar
сообщение Mar 27 2016, 09:04
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Пытаюсь перенести на STM32 свой старый проект на MSP430. И второй день туплю с применением таймера.
Делаю OSD. Алгоритм простой - на ногу 10 (PA0) подключен HSYNC. От него должен запустится таймер (TIM2) и запустить через какое-то время DMA и вызвать прерывание. Хотелось бы все сделать с минимумом кода, момент запуска DMA должен быть точно привязан к HSYNC, иначе изображение будет дергаться.
Задом чуствую, как-то надо использовать one pulse mode, но не выходит каменный цветок sad.gif
Прошу помощи более опытных товарищей - с STM32 я только начал играться. Ткните носом в пример кода инициализации таймера sm.gif

Go to the top of the page
 
+Quote Post
kolobok0
сообщение Mar 27 2016, 10:56
Сообщение #2


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(varvar @ Mar 27 2016, 12:04) *
...Ткните носом в пример кода инициализации таймера sm.gif


Не буду оригинален, на сайте производителя смотрели всевозможные библиотеки с примерами или просто примеры?
В кубе были по мойму примеры генерации подобных вещей.

(круглый)
Go to the top of the page
 
+Quote Post
scifi
сообщение Mar 27 2016, 10:58
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Можно и по старинке - почитать мануал, понять, как всё это работает... Или это нынче не модно?
Go to the top of the page
 
+Quote Post
varvar
сообщение Mar 27 2016, 11:51
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Спасибо на добром слове, вот такая заготовка заработала:
CODE
void hsync_timer_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* Time base configuration */
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 100;
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

/* TIM2 PWM2 Mode configuration: Channel1 */
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 20;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);

/* TIM2 configuration in Input Capture Mode */

TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);

/* One Pulse Mode selection */
TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single);
/* Input Trigger selection */
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
/* Slave Mode selection: Trigger Mode */
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Trigger);
//TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE)
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);

TIM_Cmd(TIM2, ENABLE);
NVIC_EnableIRQ(TIM2_IRQn);
}

void TIM2_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
SPI1->DR |= 0xCCCC;
SPI2->DR |= 0x3333;
}


Понять бы почему, мне кажется, что

TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);

не в тему, должно быть TIM_TS_TI1FP1

А куб, конечно, хорошая вещь, когда памяти немеряно и спешить некуда. Ну и не удалось мне совместить HAL с scmRTOS.

Сообщение отредактировал IgorKossak - Mar 28 2016, 07:46
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
Go to the top of the page
 
+Quote Post
AleksBak
сообщение Mar 28 2016, 06:07
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364



Цитата(varvar @ Mar 27 2016, 15:51) *
...Ну и не удалось мне совместить HAL с scmRTOS.

А scmRTOS Вы раньше использовали и теперь хотите использовать я так понял? Я вот на днях, благодаря участнику esaulenka, обнаружил, что оказывается есть много библиотек и софта (esaulenka писал конкретно о stm32tpl) Участника данного форума - АНТОХА кажется его никнейм точно сейчас не помню и у него есть портированная эта ОС тоже. Человек сделал большую работу и выложил ее для всеобщего доступа.
Go to the top of the page
 
+Quote Post
varvar
сообщение Mar 28 2016, 08:19
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



scmRTOS чудесно работает с CMSIS, а куб генерирует HAL. У меня не получилось заставить вместе работать кубовый USB стек и scmRTOS.
Хотя может быть и к лучшему - HAL память жрет, как свинья помои.
Go to the top of the page
 
+Quote Post
AleksBak
сообщение Mar 28 2016, 09:30
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364



Цитата(varvar @ Mar 28 2016, 12:19) *
scmRTOS чудесно работает с CMSIS, а куб генерирует HAL...

Хм.. Значит Вы же попробовали/проверили эту ОС на этом контроллере. А я думал, что нет..
Цитата(varvar @ Mar 28 2016, 12:19) *
...
Хотя может быть и к лучшему - HAL память жрет, как свинья помои.

А где именно Вы нашли, что много памяти он жрет? Я спрашиваю это потому, что сам такой же новичок в АРМ-ах хотя уже лет 20 (двадцать) контроллерами занимаюсь. То что HAL много "лишних" движений делает - это понятно. Т.к. задумка для него была сделать универсальность еще. То что бывают неучтенные баги и недочеты для конкретного контроллера - это тоже понятно (опять-таки из-за универсальности). То что есть некоторые сильно "кривые" моменты - тоже понятно. Но про жрание памяти пока не знал. Память программ Вы может имели ввиду? А не ОЗУ как я понял? Это да, но ведь это не просто использование памяти, а использование памяти кодом (хоть и кривым/растянутым, но готовым уже и вместо вашего он уже есть). Еще можно отключить некоторые вещи в Cube для экономии памяти (Full Assert и т.п.). А еще, у человека про которого я написал и одного из разработчиков/писателей этой scmRTOS (АНТОХА) есть также свой фреймворк как альтернатива HAL-у. Может его попробуете? Попробуете его потом наверно все-таки т.к. сейчас основная проблема - это разобраться вначале с работой периферии (Таймера и пр.) - тут, у стм-овских контроллеров, она гораздо сложнее.
Go to the top of the page
 
+Quote Post
varvar
сообщение Mar 28 2016, 09:51
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Цитата(AleksBak @ Mar 28 2016, 12:30) *
А где именно Вы нашли, что много памяти он жрет?

На собственном грустном опыте - у MSP430 стек отъел меньше 8к памяти - у STM в районе 20. scmRTOS не пошла - пришлось ставить FreeRTOS - еще 10 кбайт долой, плюс оперативку хорошо подъела. Короче, FreeRTOS, USB, IMU и дисплей - 60к долой. Аналогичная задача на MSP заняла меньше 20к. Ну и сложность периферии - это смотря с чем сравнивать. По-моему у MSP430 периферия посложнее будет, но есть хорошие примеры, которые снимают все вопросы.
Кстати, то же OSD на MSP430 мне удавалось сделать использую около 200 байт оперативки для видео буферов sm.gif
Цитата(AleksBak @ Mar 28 2016, 12:30) *
хотя уже лет 20 (двадцать) контроллерами занимаюсь.

Ну Вы еще совсем молодой, у Вас все впереди sm.gif
Go to the top of the page
 
+Quote Post
AleksBak
сообщение Mar 28 2016, 11:07
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364



Цитата(varvar @ Mar 28 2016, 13:51) *
На собственном грустном опыте - у MSP430 стек отъел меньше 8к памяти - у STM в районе 20...

Да - большая разница (хотя все-равно не понятно откуда там так много - 20К, но все равно это не так важно). Еще по именно Вашей теме напишу такую вещь - HAL как бы вводит понятия уже более "сложного" программирования и у него есть такие полезные вещи как callback-и и тут они пригодились бы. Но Вы пишите про использование FreeRTOS (и еще Вам важно быстродействие системы), то тогда это про как информация пусть будет.
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Mar 28 2016, 14:05
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(varvar @ Mar 27 2016, 13:04) *
Пытаюсь перенести на STM32 свой старый проект на MSP430. И второй день туплю с применением таймера.
Делаю OSD. Алгоритм простой - на ногу 10 (PA0) подключен HSYNC. От него должен запустится таймер (TIM2) и запустить через какое-то время DMA и вызвать прерывание. Хотелось бы все сделать с минимумом кода, момент запуска DMA должен быть точно привязан к HSYNC, иначе изображение будет дергаться.
Задом чуствую, как-то надо использовать one pulse mode, но не выходит каменный цветок sad.gif
Прошу помощи более опытных товарищей - с STM32 я только начал играться. Ткните носом в пример кода инициализации таймера sm.gif


Я бы сделал следующим образом:
Подключить строчный синхроимпульс ко входу input capture свободно бегущего таймера.
В обработчике прерывания input capture прибавил к захваченному значению требуемое время задержки в тиках таймера (h front porch) и записал полученную сумму в compare register для output compare того же таймера. В обработчике прерывания output compare запускать DMA.
Если не все понятно -- могу углубиться в детали.
Go to the top of the page
 
+Quote Post
varvar
сообщение Mar 28 2016, 15:27
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Цитата(Tarbal @ Mar 28 2016, 17:05) *
Я бы сделал следующим образом:
Подключить строчный синхроимпульс ко входу input capture свободно бегущего таймера.
В обработчике прерывания input capture прибавил к захваченному значению требуемое время задержки в тиках таймера (h front porch) и записал полученную сумму в compare register для output compare того же таймера. В обработчике прерывания output compare запускать DMA.
Если не все понятно -- могу углубиться в детали.

Примерно так кода-то делал - на другом процессоре - наложенное изображение дергается, немного, но неприятно. А когда таймер, запускаемый от hsync автоматически запускает DMA безо всяких прерываний - получается абсолютно стабильная картинка. Теоретически и STM32 должно быть то же самое - но пока у меня DMA от таймера запускается - но со временем какая-то беда, что-то не так настраиваю. В примере от ST пишут, что используется CCR1, а что-то непонятное они делают с CCR2 (/Project/STM32xx_StdPeriph_Examples/TIM/OnePulse folder.)
В принципе, эта идея вролне совместима с Вашей - вполне можно вместо вызова прерываний запустить DMA, если мой вариант не сработает - попробую Ваш.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 28 2016, 16:35
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(varvar @ Mar 28 2016, 15:51) *
На собственном грустном опыте - у MSP430 стек отъел меньше 8к памяти - у STM в районе 20. scmRTOS не пошла - пришлось ставить FreeRTOS - еще 10 кбайт долой, плюс оперативку хорошо подъела. Короче, FreeRTOS, USB, IMU и дисплей - 60к долой.

Что-то это как-то слишком - 60К под такую простую задачу.
Вот у меня сейчас открыт в чём-то похожий проект на Cortex-M: uCOS + USB + SPI-LCD (своя графика: прямые, прямоугольники, треугольники, текст, ...) + АЦП + прочие мелочи.
Всё в сумме: 29704 (ro code) + 20216 (ro data), причём "ro data" - это в основном шрифты и пиктограммы. Так что, если не считать шрифтов, флеши наберётся на <30К. Да и то из них там много лишнего - MassStorage в USB который там болтается, но пока не используется. Если его да всякую отладку повыкидывать - будет наверное чуть больше 20кил. Ваш проект ещё меньше флеши должен занять.
А стек Вы сами выделяете, раз сами выделили 20, вот он столько и съел. Выделяйте меньше.
Go to the top of the page
 
+Quote Post
varvar
сообщение Mar 28 2016, 16:48
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Цитата(jcxz @ Mar 28 2016, 19:35) *
Всё в сумме: 29704 (ro code) + 20216 (ro data), причём "ro data" - это в основном шрифты и пиктограммы. Так что, если не считать шрифтов, флеши наберётся на <30К. Да и то из них там много лишнего - MassStorage в USB который там болтается, но пока не используется. Если его да всякую отладку повыкидывать - будет наверное чуть больше 20кил.

И все это с кубовым USB и HAL? Что компилятор может настолько разный размер генерить - не очень похоже (в моем случае GCC).
Без HAL размеры несколько скромнее.

Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 28 2016, 16:58
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(varvar @ Mar 28 2016, 22:48) *
И все это с кубовым USB и HAL?

Нет конечно, такое гумно не использую. USB-стек из примеров IAR, остальное (кроме uCOS) - своё.
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Mar 28 2016, 18:38
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Цитата(varvar @ Mar 28 2016, 19:27) *
Примерно так кода-то делал - на другом процессоре - наложенное изображение дергается, немного, но неприятно. А когда таймер, запускаемый от hsync автоматически запускает DMA безо всяких прерываний - получается абсолютно стабильная картинка. Теоретически и STM32 должно быть то же самое - но пока у меня DMA от таймера запускается - но со временем какая-то беда, что-то не так настраиваю. В примере от ST пишут, что используется CCR1, а что-то непонятное они делают с CCR2 (/Project/STM32xx_StdPeriph_Examples/TIM/OnePulse folder.)
В принципе, эта идея вролне совместима с Вашей - вполне можно вместо вызова прерываний запустить DMA, если мой вариант не сработает - попробую Ваш.


Вам надо найти если возможно заускать DMA по таймеру или output compare -- тогда и предложенный мной способ будет безупречен sm.gif.

В моем предложении задержка с прерыванием, запускающим DMA может привести к дерганью картинки. Но всегда можно найти способ улучшить. Навскидку:
поставить прерывание на время перед окончанием front porch и запретить все остальные прерывания, разрешив их после старта DMA.
Второй вариант -- остальные процессы делать без прерываний, либо синхронизировать с hsync, избегая опасного участка -- момента окончания front porch.
Третий вариант -- делать ожидание окончания front porch чуть короче и выжигать время в цикле внутри прерывания.
Задержка с input capture interrupt пофиг. Там железо захватывает значение в регистр.

Цитата(jcxz @ Mar 28 2016, 20:58) *
Нет конечно, такое гумно не использую. USB-стек из примеров IAR, остальное (кроме uCOS) - своё.


Я с кубовым подхожу к окончанию проекта. Нареканий нет.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 28 2016, 23:53
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Tarbal @ Mar 29 2016, 00:38) *
Я с кубовым подхожу к окончанию проекта. Нареканий нет.

Нарекание уже хотя-бы то, что он монструозен, раздувает код до неприличных размеров.
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Mar 29 2016, 02:40
Сообщение #17


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Та мода, что вы описали есть в STM32F429. В описании (RM0090 Reference manual) глава 15.3.14 Timers and external trigger synchronization
Я не смотрел для вашего процессора. Может быть тоже есть.

Цитата(jcxz @ Mar 29 2016, 03:53) *
Нарекание уже хотя-бы то, что он монструозен, раздувает код до неприличных размеров.


Мне пофиг пока хватает места.
Go to the top of the page
 
+Quote Post
Tarbal
сообщение Apr 1 2016, 15:15
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Ну что у вас? Получилось?
Go to the top of the page
 
+Quote Post
varvar
сообщение Apr 2 2016, 13:54
Сообщение #19


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Цитата(Tarbal @ Apr 1 2016, 18:15) *
Ну что у вас? Получилось?

да, получилось. Картинка, как влитая. Ноги, правда, пришлось другие использовать.
Программа не особо чищена, но все работает. Нужна инициализация, дальше все прерывания делают. Буфера на страницу нет - слишком мало оперативки у процессора, только 20к. Изображение формируется "на лету", белое и черное.
CODE
#define FirstLine 30
#define LastLine 255
#define VIDEO_DELAY 820
#define VIDEO_EXRA_DELAY 400
//#define VIDEO_EXRA_DELAY 1000


uint16_t TestFlag=0x3333;
uint16_t LineCnt=0;
uint16_t LinePointer=0;
uint16_t Vsync_delay;

union buff_t
{
uint16_t wData[26];
uint8_t bData[52];
};


buff_t WhiteBuffer1;
buff_t WhiteBuffer2;
buff_t BlackBuffer1;
buff_t BlackBuffer2;

void OSD_init(void)
{


GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
SPI_InitTypeDef SPI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;


for (int i=0; i<26; i++)
{
WhiteBuffer1.wData[i]= ~0x4040;
BlackBuffer1.wData[i]= ~0x0004;

// WhiteBuffer1[i]= ((i+1)<<8) +i +1;
// BlackBuffer1[i]= ((i+1)<<8) +i +1;

WhiteBuffer2.wData[i]= ~0x0040;
BlackBuffer2.wData[i]= ~0x0404;
}


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable GPIO Peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // for Interrupt
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // timer
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Enable DMA1 clock




// Configure test pin in output push/pull mode
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// ****************************************************
// Vsync pin
// ****************************************************
// pin as input
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// interrupt from Vsync
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line3);// Clear EXTI Line Pending Bit
// Connect EXTI
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);
// Configure EXTI1 to generate an interrupt on falling edge
EXTI_InitStructure.EXTI_Line = EXTI_Line3;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

// ****************************************************
// Hsync timer
// ****************************************************
// pin as input
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//
TIM_TimeBaseStructure.TIM_Period = VIDEO_DELAY + VIDEO_EXRA_DELAY;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// TIM2 PWM2 Mode configuration: Channel1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_Pulse = VIDEO_DELAY;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
//
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
//
TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single);
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Trigger);
//
NVIC_EnableIRQ(TIM2_IRQn);

// ****************************************************
// SPI as black and white video
// ****************************************************
// SPI1 slave (black) PA6-MISO PA5-SCK
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx ;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_CRCPolynomial = 10; // !!! mandatory!!!
SPI_Init(SPI1, &SPI_InitStructure);
// SPI2 master (white) PB15-MISO PB13-SCK
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx ;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_CRCPolynomial = 10; // !!! mandatory!!!
SPI_Init(SPI2, &SPI_InitStructure);
//
// ****************************************************
// DMA
// ****************************************************
// Configure DMA1 - Channel5== (memory -> SPI)

DMA_DeInit(DMA1_Channel3); //Set DMA registers to default values
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR; //Address of peripheral the DMA must map to
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BlackBuffer1.wData; //Variable from which data will be transmitted
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 26; //Buffer size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure); //Initialize the DMA
//
// master SPI black
DMA_DeInit(DMA1_Channel5); //Set DMA registers to default values
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR; //Address of peripheral the DMA must map to
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)WhiteBuffer1.wData; //Variable from which data will be transmitted
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 26; //Buffer size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure); //Initialize the DMA

DMA_Cmd(DMA1_Channel3, ENABLE); // slave TX
//
//DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);


NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);



// ****************************************************
// enables
// ****************************************************
SPI1->CR2 |= 0x02; // TX DMA Enable
SPI2->CR2 |= 0x02;

}


// Vsync interrupt
extern "C" void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line3);
if (Vsync_delay > 0)
{
if (--Vsync_delay==0)
{
SPI2->CR1 |= 0x0040; // master SPI enable
SPI1->CR1 |= 0x0040; // slave SPI enable
TIM2->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC1DE; // Capture/Compare 1 DMA request and interrupt enable
TIM2->CR1 |= 0x0001; // enabled
}
}
LineCnt=0;
LinePointer=0;
}
}


// Hsync interrupt
// master 5ch DMA SPI2
extern "C" void TIM2_IRQHandler(void)
{
TIM2->SR &= ~TIM_IT_CC1; // Clear CC1IF
if ((LineCnt > FirstLine) && (LineCnt < LastLine))
{
TIM2->CR1 &= ~0x0001; // timer disabled

//GPIOA->ODR |= 0x04;

TIM2->DIER &= ~TIM_DIER_CC1DE; // DMA TIM disabled
SPI2->CR2 |= 0x02; // DMA master enabled

DMA1_Channel5->CCR |= DMA_CCR5_EN | DMA_CCR5_TCIE; // enable DMA & int
LinePointer++;
}
if (LineCnt == FirstLine)
{
DMA1_Channel5->CCR |= DMA_CCR5_EN | DMA_CCR5_TCIE; // enable DMA & int
DMA1_Channel3->CCR |= DMA_CCR3_EN;
}
LineCnt++;
}

// master DMA IRQ
extern "C" void DMA1_Channel5_IRQHandler(void)
//void DMA1_Channel5_IRQHandler(void)
{
DMA1->IFCR = DMA_IFCR_CGIF5; // clear int flag

DMA1_Channel5->CCR &= ~(DMA_CCR5_EN | DMA_CCR5_TCIE); // disable DMA & interrupt
DMA1_Channel3->CCR &= ~DMA_CCR3_EN;

SPI2->CR2 &= ~0x02; // DMA master disabled
SPI1->SR &= ~SPI_I2S_FLAG_TXE; // Clear slane SPI TX INT
SPI1->CR2 |= 0x80; // slave SPI interrupt enable
}

// slave SPI IRQ
extern "C" void SPI1_IRQHandler(void)
{
SPI1->SR &= ~SPI_I2S_FLAG_TXE; // Clear SPI2 TX INT
SPI1->CR2 &= ~0x80; // SPI1 interrupt disable

//GPIOA->ODR &= ~0x04;


TIM2->SR &= ~ TIM_SR_CC1OF; // compare flag
TIM2->EGR &= ~ TIM_EGR_CC1G; // capture/compare 1 generation
TIM2->DIER |= TIM_DIER_CC1DE; // DMA TIM enabled
SPI2->CR2 &= ~0x02; // DMA SPI1 disabled

if (LineCnt != LastLine)
{
if(LineCnt & 0x01)
{
DMA1_Channel5->CMAR = (uint32_t)WhiteBuffer1.wData;
DMA1_Channel3->CMAR = (uint32_t)BlackBuffer1.wData;
}
else
{
DMA1_Channel5->CMAR = (uint32_t)WhiteBuffer2.wData;
DMA1_Channel3->CMAR = (uint32_t)BlackBuffer2.wData;
}
DMA1_Channel5->CCR |= DMA_CCR5_EN; // enable DMA
DMA1_Channel3->CCR |= DMA_CCR3_EN;
flag |= 0x01;
}
else flag |= 0x02;
TIM2->CR1 |= 0x0001; // timer enabled

}


Go to the top of the page
 
+Quote Post
Tarbal
сообщение Apr 3 2016, 17:21
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439



Ну и хорошо sm.gif
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Apr 3 2016, 18:09
Сообщение #21


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



почему бы не использовать spi в режиме slave, дёргать nss строчным синхроимпульсом и заполнять через dma ?
минус таймер, плюс всё чисто аппаратно
Go to the top of the page
 
+Quote Post
varvar
сообщение Apr 4 2016, 08:34
Сообщение #22


Частый гость
**

Группа: Участник
Сообщений: 93
Регистрация: 5-01-05
Из: Оулу
Пользователь №: 1 811



Цитата(Огурцов @ Apr 3 2016, 21:09) *
почему бы не использовать spi в режиме slave, дёргать nss строчным синхроимпульсом и заполнять через dma ?
минус таймер, плюс всё чисто аппаратно

Так, собственно и так практически все аппаратно - прерывания только меняют режимы и переключают буфера.
Таймер запускается от синхроимпульса, аппаратно при срабатывании запускает DMA, тот пишет в SPI. SPI использованы оба - один для белого, второй для черного. Ваша идея очень хороша, конечно, но программа уже как-то работает, трогать не хочется.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 4th September 2025 - 22:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.02527 секунд с 7
ELECTRONIX ©2004-2016