#include "dvp.h" #include "ch32v30x_dvp.h" #include "eth_driver.h" #include "string.h" __attribute__((aligned(4))) uint8_t DMA_LineBuf0[BYTES_PER_LINE]; __attribute__((aligned(4))) uint8_t DMA_LineBuf1[BYTES_PER_LINE]; volatile uint8_t Line_Ready_Flag = 0; volatile uint8_t *Ready_Line_Ptr = NULL; volatile uint32_t current_line_idx = 0; static uint32_t frame_count = 0; extern u8 socket[]; void DVP_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DVP, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_9 | GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9; GPIO_Init(GPIOB, &GPIO_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = DVP_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DVP_Cfg(DVP_DMA_Disable, DVP_FLAG_FIFO_RESET_Enable, DVP_RX_RESET_Enable); DVP_Mode(RB_DVP_D8_MOD, Video_Mode); DVP->CR0 &= ~(RB_DVP_P_POLAR | RB_DVP_V_POLAR | RB_DVP_H_POLAR); DVP->DMA_BUF0 = (uint32_t)DMA_LineBuf0; DVP->DMA_BUF1 = (uint32_t)DMA_LineBuf1; DVP->ROW_NUM = 1; DVP->COL_NUM = BYTES_PER_LINE; DVP_INTCfg(ENABLE, RB_DVP_IE_STR_FRM | RB_DVP_IE_ROW_DONE); DVP_Cfg(DVP_DMA_Enable, DVP_FLAG_FIFO_RESET_Disable, DVP_RX_RESET_Disable); DVP->CR0 |= RB_DVP_ENABLE; } void DVP_Task(void) { if (!Line_Ready_Flag) return; uint8_t *line = (uint8_t *)Ready_Line_Ptr; uint32_t idx = current_line_idx; Line_Ready_Flag = 0; /* 仅发送图像行,跳过参数行,且 socket 已连接 */ if (idx < SENSOR_HEIGHT && socket[0] != 0xFF) { /* 4字节行头:帧号(2B) + 行号(2B) */ uint8_t hdr[4] = { (frame_count >> 8) & 0xFF, frame_count & 0xFF, (idx >> 8) & 0xFF, idx & 0xFF }; u32 len = 4; WCHNET_SocketSend(socket[0], hdr, &len); len = BYTES_PER_LINE; WCHNET_SocketSend(socket[0], line, &len); /* 每帧第0行打印一次,确认帧号和socket状态 */ if (idx == 0) printf("[DVP] frame=%lu socket=%d\r\n", frame_count, socket[0]); } else if (idx == 0 && socket[0] == 0xFF) { /* socket 未连接时提示 */ printf("[DVP] frame=%lu waiting for TCP...\r\n", frame_count); } memset(line, 0, BYTES_PER_LINE); } void DVP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void DVP_IRQHandler(void) { if (DVP->IFR & RB_DVP_IF_STR_FRM) { DVP->IFR = RB_DVP_IF_STR_FRM; current_line_idx = 0; frame_count++; } if (DVP->IFR & RB_DVP_IF_ROW_DONE) { DVP->IFR = RB_DVP_IF_ROW_DONE; Ready_Line_Ptr = (DVP->CR1 & RB_DVP_BUF_TOG) ? DMA_LineBuf0 : DMA_LineBuf1; current_line_idx++; Line_Ready_Flag = 1; } }