|
STM32F103C8T - перезапуск таймера от внешнего сигнала |
|
|
|
Mar 27 2016, 09:04
|

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

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

Частый гость
 
Группа: Участник
Сообщений: 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] - для короткого!
|
|
|
|
|
Mar 28 2016, 06:07
|
Частый гость
 
Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364

|
Цитата(varvar @ Mar 27 2016, 15:51)  ...Ну и не удалось мне совместить HAL с scmRTOS. А scmRTOS Вы раньше использовали и теперь хотите использовать я так понял? Я вот на днях, благодаря участнику esaulenka, обнаружил, что оказывается есть много библиотек и софта ( esaulenka писал конкретно о stm32tpl) Участника данного форума - АНТОХА кажется его никнейм точно сейчас не помню и у него есть портированная эта ОС тоже. Человек сделал большую работу и выложил ее для всеобщего доступа.
|
|
|
|
|
Mar 28 2016, 09:30
|
Частый гость
 
Группа: Участник
Сообщений: 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-у. Может его попробуете? Попробуете его потом наверно все-таки т.к. сейчас основная проблема - это разобраться вначале с работой периферии (Таймера и пр.) - тут, у стм-овских контроллеров, она гораздо сложнее.
|
|
|
|
|
Mar 28 2016, 09:51
|

Частый гость
 
Группа: Участник
Сообщений: 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 байт оперативки для видео буферов  Цитата(AleksBak @ Mar 28 2016, 12:30)  хотя уже лет 20 (двадцать) контроллерами занимаюсь. Ну Вы еще совсем молодой, у Вас все впереди
|
|
|
|
|
Mar 28 2016, 11:07
|
Частый гость
 
Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364

|
Цитата(varvar @ Mar 28 2016, 13:51)  На собственном грустном опыте - у MSP430 стек отъел меньше 8к памяти - у STM в районе 20... Да - большая разница (хотя все-равно не понятно откуда там так много - 20К, но все равно это не так важно). Еще по именно Вашей теме напишу такую вещь - HAL как бы вводит понятия уже более "сложного" программирования и у него есть такие полезные вещи как callback-и и тут они пригодились бы. Но Вы пишите про использование FreeRTOS (и еще Вам важно быстродействие системы), то тогда это про как информация пусть будет.
|
|
|
|
|
Mar 28 2016, 14:05
|
Профессионал
    
Группа: Свой
Сообщений: 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, но не выходит каменный цветок  Прошу помощи более опытных товарищей - с STM32 я только начал играться. Ткните носом в пример кода инициализации таймера  Я бы сделал следующим образом: Подключить строчный синхроимпульс ко входу input capture свободно бегущего таймера. В обработчике прерывания input capture прибавил к захваченному значению требуемое время задержки в тиках таймера (h front porch) и записал полученную сумму в compare register для output compare того же таймера. В обработчике прерывания output compare запускать DMA. Если не все понятно -- могу углубиться в детали.
|
|
|
|
|
Mar 28 2016, 15:27
|

Частый гость
 
Группа: Участник
Сообщений: 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, если мой вариант не сработает - попробую Ваш.
|
|
|
|
|
Mar 28 2016, 16:35
|
Гуру
     
Группа: Свой
Сообщений: 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, вот он столько и съел. Выделяйте меньше.
|
|
|
|
|
Mar 28 2016, 16:48
|

Частый гость
 
Группа: Участник
Сообщений: 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 размеры несколько скромнее.
|
|
|
|
|
Mar 28 2016, 18:38
|
Профессионал
    
Группа: Свой
Сообщений: 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 -- тогда и предложенный мной способ будет безупречен  . В моем предложении задержка с прерыванием, запускающим DMA может привести к дерганью картинки. Но всегда можно найти способ улучшить. Навскидку: поставить прерывание на время перед окончанием front porch и запретить все остальные прерывания, разрешив их после старта DMA. Второй вариант -- остальные процессы делать без прерываний, либо синхронизировать с hsync, избегая опасного участка -- момента окончания front porch. Третий вариант -- делать ожидание окончания front porch чуть короче и выжигать время в цикле внутри прерывания. Задержка с input capture interrupt пофиг. Там железо захватывает значение в регистр. Цитата(jcxz @ Mar 28 2016, 20:58)  Нет конечно, такое гумно не использую. USB-стек из примеров IAR, остальное (кроме uCOS) - своё. Я с кубовым подхожу к окончанию проекта. Нареканий нет.
|
|
|
|
|
Mar 29 2016, 02:40
|
Профессионал
    
Группа: Свой
Сообщений: 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)  Нарекание уже хотя-бы то, что он монструозен, раздувает код до неприличных размеров. Мне пофиг пока хватает места.
|
|
|
|
|
Apr 2 2016, 13:54
|

Частый гость
 
Группа: Участник
Сообщений: 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
}
|
|
|
|
|
Apr 4 2016, 08:34
|

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

|
Цитата(Огурцов @ Apr 3 2016, 21:09)  почему бы не использовать spi в режиме slave, дёргать nss строчным синхроимпульсом и заполнять через dma ? минус таймер, плюс всё чисто аппаратно Так, собственно и так практически все аппаратно - прерывания только меняют режимы и переключают буфера. Таймер запускается от синхроимпульса, аппаратно при срабатывании запускает DMA, тот пишет в SPI. SPI использованы оба - один для белого, второй для черного. Ваша идея очень хороша, конечно, но программа уже как-то работает, трогать не хочется.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|