jcxz 184 28 марта, 2016 Опубликовано 28 марта, 2016 · Жалоба Я с кубовым подхожу к окончанию проекта. Нареканий нет. Нарекание уже хотя-бы то, что он монструозен, раздувает код до неприличных размеров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 29 марта, 2016 Опубликовано 29 марта, 2016 · Жалоба Та мода, что вы описали есть в STM32F429. В описании (RM0090 Reference manual) глава 15.3.14 Timers and external trigger synchronization Я не смотрел для вашего процессора. Может быть тоже есть. Нарекание уже хотя-бы то, что он монструозен, раздувает код до неприличных размеров. Мне пофиг пока хватает места. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 1 апреля, 2016 Опубликовано 1 апреля, 2016 · Жалоба Ну что у вас? Получилось? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
varvar 0 2 апреля, 2016 Опубликовано 2 апреля, 2016 · Жалоба Ну что у вас? Получилось? да, получилось. Картинка, как влитая. Ноги, правда, пришлось другие использовать. Программа не особо чищена, но все работает. Нужна инициализация, дальше все прерывания делают. Буфера на страницу нет - слишком мало оперативки у процессора, только 20к. Изображение формируется "на лету", белое и черное. #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 } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 3 апреля, 2016 Опубликовано 3 апреля, 2016 · Жалоба Ну и хорошо :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VCucumber 0 3 апреля, 2016 Опубликовано 3 апреля, 2016 · Жалоба почему бы не использовать spi в режиме slave, дёргать nss строчным синхроимпульсом и заполнять через dma ? минус таймер, плюс всё чисто аппаратно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
varvar 0 4 апреля, 2016 Опубликовано 4 апреля, 2016 · Жалоба почему бы не использовать spi в режиме slave, дёргать nss строчным синхроимпульсом и заполнять через dma ? минус таймер, плюс всё чисто аппаратно Так, собственно и так практически все аппаратно - прерывания только меняют режимы и переключают буфера. Таймер запускается от синхроимпульса, аппаратно при срабатывании запускает DMA, тот пишет в SPI. SPI использованы оба - один для белого, второй для черного. Ваша идея очень хороша, конечно, но программа уже как-то работает, трогать не хочется. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться