先总结总结问题 
问题1:MX_DCMI_Init();放到  MX_DMA_Init();后 
 
问题2:DMA缓存缓存要放到SRAM中__align(32) uint32_t buffer[65535] __attribute((at(0X24040000))); 
 
问题3:IO复用问题,DCMI数据口可以复用到其他IO口,要注意配置 
 
问题4:摄像头时钟配置,不能过快,也不能过慢,过快采集不过来,过慢JPEG会传一半停止 
 
问题5:上位机字节序,JPG由FF D8开头,FF D9结尾 
 
解决上面5个问题,STM32H7 DCMI就可以轻松使用 
 
由于需要用到摄像头,用IO驱动的话会比较慢,这里使用的STM32H7B0中的DCMI接口,由于DMA用的比较少,在这里卡了3天,期间各种测试,从硬件到软件,接用IO读OV2640,可以读到数据,确定硬件没有问题,DCMI的DMA一直进错误中断Transfer Error Interrupt management 
 
 
 
 
网上说是内存地址问题,DMA不能访问直接访问DTCM,也改成SRAM了,也会进入错误中断 
 
 
 
 
DMA1等都不能访问DTCM 
 
 
 
 
最终发现把    MX_DCMI_Init();放到  MX_DMA_Init();即可正常传输数据 
 
 
 
 
 Several peripheral DMA handle pointers point to the same DMA handle. 
     Be aware that there is only one channel to perform all the requested DMAs.干扰项,删掉就行不用管,我开始还以为这里需要配置什么东西,就保留最上边一行  
 
 
 
 
删完就像这样就可以 
 
 
 
 
 
缓存放到SRAM放到中 
 
__align(32) uint32_t buffer[65535] __attribute((at(0X24040000))); 
 
开启缓存对于DCMI没有影响,开不开都可以正常运行 
 
static void CPU_CACHE_Enable(void) 
{ 
    SCB_EnableICache();//使能I-Cache 
  SCB_EnableDCache();//使能D-Cache    
    SCB->CACR|=1<<2;   //强制D-Cache透写,如不开启,实际使用中可能遇到各种问题     
} 
 
启动采集代码 
 
void StartOV2640() 
{ 
                int i =0; 
                __HAL_DCMI_ENABLE_IT(&hdcmi, DCMI_IER_FRAME_IE);                                                       //使用帧中断 
    memset(buffer, 0, 65535);                                                                                //把接收BUF清空 
    HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, (uint32_t)buffer, 65535);         //启动拍照 
} 
 
 
void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) 
{ 
          int i =0; 
          HAL_DCMI_Suspend(hdcmi); // 拍照完成,挂起 DCMI 
          HAL_DCMI_Stop(hdcmi);    // 拍照完成,停止 DMA传输 
    int pictureLength = 65535; 
    while (pictureLength > 0)     //循环计算出接收的JPEG的大小 
    { 
        if (buffer[pictureLength - 1] != 0x00000000) 
        { 
          break; 
        } 
        pictureLength--; 
    } 
                jpeglen = pictureLength * 4; 
                getPicture = 1; 
} 
 
 
配置IO也要注意一下D0,D1,D3可以复用到其他IO,一定不要弄错,配置完要对着IO检查一遍,频率使用也很重要,我这里用到的频率如下 
 
单片机主频280M 
 
摄像头主频8M 
 
摄像头分频配置 
 
SCCB_WR_Reg(0XFF,0X00); 
 
SCCB_WR_Reg(0XD3,0XF); 
 
SCCB_WR_Reg(0XFF,0X01); 
 
SCCB_WR_Reg(0X11,0X7); 
 
 
 
 
 
 
 
 
开启中断 
 
 
 
 
DMA配置,不要修改 
 
 
 
 
 NVIC给个优先级 
 
 
 
 
摄像头时钟,这个可以自由发挥,和摄像头分频配置一起可以有多重组合 
 
 
 
 
样张 
 
 
 
 
上位机软件用C#写的,关键部分代码 
 
private const int count = 200 * 1024; 
private byte[] buffer = new byte[count]; 
private int offset = 0; 
private int length = 0; 
private bool isData = false; 
public void DataCallBack(Object sender, SerialDataReceivedEventArgs e) 
{ 
    try 
    { 
        if (isData==false) 
        { 
            var data = _serialPort.ReadLine(); 
            if (!string.IsNullOrEmpty(data) && data.Length > 0) 
            { 
                if(data.IndexOf("jpeg data size:")>=0) 
                { 
                    var lengthStr = data.Split(':'); 
                    if(lengthStr != null && lengthStr.Length>1) 
                    { 
                        length = int.Parse(lengthStr[1]); 
                        if (length > count) 
                        { 
 
                        } 
                        else 
                        { 
                            isData = true; 
                        } 
                    } 
                    Console.WriteLine(data); 
                } 
                else 
                { 
                    Console.WriteLine(data); 
                } 
            } 
        } 
        else 
        { 
            int thisLength = _serialPort.Read(buffer, offset, length - offset); 
            offset = offset + thisLength; 
            if(offset >= length) 
            { 
                Console.WriteLine($"接收完一张图片,offset:{offset},length:{length}"); 
                string path = Directory.GetCurrentDirectory(); 
                DirectoryCheak(path + "\\out\\"); 
                bool ispictrue = false; 
                if (false)//bmp 
                { 
                    //bmp 
                    if (false) 
                    { 
                        //RGB888 
                        System.Drawing.Bitmap formBitmap = new System.Drawing.Bitmap(96, 96); 
                        for (int i = 0; i < 96; i++) 
                        { 
                            for (int j = 0; j < 96; j++) 
                            { 
                                formBitmap.SetPixel(i, j, System.Drawing.Color.FromArgb(buffer[i * j + j], buffer[i * j + j + 1], buffer[i * j + j + 2])); 
                            } 
                        } 
                        formBitmap.Save(path + "\\out\\" + DateTime.Now.ToString("yyyyMMdd-HHmmss.fff") + ".bmp"); 
                    } 
                    else 
                    { 
                        //RGB565 
                        List<UInt16> data = new List<UInt16>(); 
                        for (int i = 0; i < length; i += 2) 
                        { 
                            UInt16 thisData = (UInt16)((buffer << 8) | buffer[i + 1]); ; 
                            data.Add(thisData); 
                        } 
                        System.Drawing.Bitmap formBitmap = new System.Drawing.Bitmap(96, 96); 
                        for (int i = 0; i < 96; i++) 
                        { 
                            for (int j = 0; j < 96; j++) 
                            { 
                                byte red = (byte)((data[i * j + j] >> 11) << 3); //5位 移动3位 
                                byte green = (byte)(((data[i * j + j] << 5) >> 10) << 2); //6位 移动2位 
                                byte blue = (byte)(((data[i * j + j] << 11) >> 11) << 3); //5位 移动3位  
                                formBitmap.SetPixel(i, j, System.Drawing.Color.FromArgb(red, green, blue)); 
                            } 
                        } 
                        formBitmap.Save(path + "\\out\\" + DateTime.Now.ToString("yyyyMMdd-HHmmss.fff") + ".bmp"); 
                    } 
                } 
                else 
                { 
                    List<byte> data = new List<byte>(); 
                    for (int i = 1; i < length; i++) 
                    { 
                        //Console.WriteLine($"i:{i},length:{length}"); 
                        if (ispictrue == true) 
                        { 
                            data.Add(buffer); 
                        } 
                        else if ((buffer[i - 1] == 0xFF) && (buffer == 0xd8)) 
                        { 
                            ispictrue = true; 
                            data.Add(buffer[i - 1]); 
                            data.Add(buffer); 
                        } 
                        //if((buffer[i - 1] == 0xFF) && (buffer == 0xd9)) 
                        //{ 
                        //    data.Add(buffer[i - 1]); 
                        //    data.Add(buffer); 
                        //    ispictrue = false; 
                        //    break; 
                        //} 
                    } 
                    WriteFileUsingBinaryWriter(path + "\\out\\", DateTime.Now.ToString("yyyyMMdd-HHmmss.fff") + ".jpg", data.ToArray(), data.Count()); 
                } 
                offset = 0; 
                length = 0; 
                isData = false; 
 
            } 
        } 
    } 
    catch (Exception ex) 
    { 
        Console.WriteLine("串口解析出错" + ex.ToString()); 
    } 
} 
 
public void WriteFileUsingBinaryWriter(string path,string fileName,byte[] data,int length) 
{ 
    var outputStream = File.Create(path + fileName); 
    using (var writer = new BinaryWriter(outputStream)) 
    { 
        writer.Write(data, 0, length); 
    } 
} 
 
/// <summary> 
/// 效验文件夹,没有就创建 
/// </summary> 
private void DirectoryCheak(string path) 
{ 
    if (false == System.IO.Directory.Exists(path)) 
    { 
        System.IO.Directory.CreateDirectory(path); 
    } 
} 
 
private void OpenSerialPort_Click(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
        _serialPort = new SerialPort(); 
 
        _serialPort.PortName = SerialPort.Text; 
        _serialPort.BaudRate = int.Parse(SerialBaudRate.Text); 
        _serialPort.Parity = Parity.None; 
        _serialPort.DataBits = 8; 
        _serialPort.StopBits = StopBits.One; 
        _serialPort.ReadTimeout = 10000;//单位毫秒 
        _serialPort.WriteTimeout = 10000;//单位毫秒 
 
        //设置串口字节接收缓冲值,通常为1 
        //获得接收后,触发事件处理 
        _serialPort.ReceivedBytesThreshold = 1; 
        _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataCallBack); 
 
 
        _serialPort.Open();//Console.WriteLine(serialPort.IsOpen.ToString()); 
        OpenSerialPort.IsEnabled = false; 
        CloseSerialPort.IsEnabled = true; 
    } 
    catch (Exception ex) 
    { 
        MessageBox.Show("串口打开失败" + ex.ToString()); 
        //System.Environment.Exit(0);//退出应用程序 
    } 
} 
 
private void CloseSerialPort_Click(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
        if (_serialPort.IsOpen == true) 
        { 
            _serialPort.Close(); 
            OpenSerialPort.IsEnabled = true; 
            CloseSerialPort.IsEnabled = false; 
        } 
    } 
    catch (Exception ex) 
    { 
        MessageBox.Show("串口关闭失败" + ex.ToString()); 
        System.Environment.Exit(0);//退出应用程序 
    } 
} 
 
 
 
单片机关键部分代码 
 
/* USER CODE BEGIN Header */ 
/** 
  ****************************************************************************** 
  * @file    dcmi.c 
  * @brief   This file provides code for the configuration 
  *          of the DCMI instances. 
  ****************************************************************************** 
  * @attention 
  * 
  * Copyright (c) 2022 STMicroelectronics. 
  * All rights reserved. 
  * 
  * This software is licensed under terms that can be found in the LICENSE file 
  * in the root directory of this software component. 
  * If no LICENSE file comes with this software, it is provided AS-IS. 
  * 
  ****************************************************************************** 
  */ 
/* USER CODE END Header */ 
/* Includes ------------------------------------------------------------------*/ 
#include "dcmi.h" 
 
/* USER CODE BEGIN 0 */ 
#include <string.h> 
#include <stdio.h> 
 
__align(32) uint32_t buffer[65535] __attribute((at(0X24040000))); 
 
unsigned char getPicture = 0; 
unsigned int jpeglen = 0; 
//unsigned int recvOk = 0; 
 
/* USER CODE END 0 */ 
 
DCMI_HandleTypeDef hdcmi; 
DMA_HandleTypeDef hdma_dcmi_pssi; 
 
/* DCMI init function */ 
void MX_DCMI_Init(void) 
{ 
 
  /* USER CODE BEGIN DCMI_Init 0 */ 
 
  /* USER CODE END DCMI_Init 0 */ 
 
  /* USER CODE BEGIN DCMI_Init 1 */ 
 
  /* USER CODE END DCMI_Init 1 */ 
  hdcmi.Instance = DCMI; 
  hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE; 
  hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING; 
  hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW; 
  hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW; 
  hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME; 
  hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B; 
  hdcmi.Init.JPEGMode = DCMI_JPEG_ENABLE; 
  hdcmi.Init.ByteSelectMode = DCMI_BSM_ALL; 
  hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD; 
  hdcmi.Init.LineSelectMode = DCMI_LSM_ALL; 
  hdcmi.Init.LineSelectStart = DCMI_OELS_ODD; 
  if (HAL_DCMI_Init(&hdcmi) != HAL_OK) 
  { 
    Error_Handler(); 
  } 
  /* USER CODE BEGIN DCMI_Init 2 */ 
        //printf("MX_DCMI_Init ok\r\n"); 
  /* USER CODE END DCMI_Init 2 */ 
 
} 
 
void HAL_DCMI_MspInit(DCMI_HandleTypeDef* dcmiHandle) 
{ 
 
  GPIO_InitTypeDef GPIO_InitStruct = {0}; 
  if(dcmiHandle->Instance==DCMI) 
  { 
  /* USER CODE BEGIN DCMI_MspInit 0 */ 
         //printf("if(dcmiHandle->Instance==DCMI)\r\n"); 
  /* USER CODE END DCMI_MspInit 0 */ 
    /* DCMI clock enable */ 
    __HAL_RCC_DCMI_CLK_ENABLE(); 
 
    __HAL_RCC_GPIOE_CLK_ENABLE(); 
    __HAL_RCC_GPIOA_CLK_ENABLE(); 
    __HAL_RCC_GPIOB_CLK_ENABLE(); 
    __HAL_RCC_GPIOD_CLK_ENABLE(); 
    /**DCMI GPIO Configuration 
    PE4     ------> DCMI_D4 
    PE5     ------> DCMI_D6 
    PE6     ------> DCMI_D7 
    PA4     ------> DCMI_HSYNC 
    PA6     ------> DCMI_PIXCLK 
    PB13     ------> DCMI_D2 
    PA9     ------> DCMI_D0 
    PA10     ------> DCMI_D1 
    PD3     ------> DCMI_D5 
    PB7     ------> DCMI_VSYNC 
    PE1     ------> DCMI_D3 
    */ 
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_1; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; 
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 
 
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9|GPIO_PIN_10; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; 
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 
 
    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_7; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; 
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
 
    GPIO_InitStruct.Pin = GPIO_PIN_3; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
    GPIO_InitStruct.Alternate = GPIO_AF13_DCMI; 
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); 
 
    /* DCMI DMA Init */ 
    /* DCMI_PSSI Init */ 
    hdma_dcmi_pssi.Instance = DMA1_Stream0; 
    hdma_dcmi_pssi.Init.Request = DMA_REQUEST_DCMI_PSSI; 
    hdma_dcmi_pssi.Init.Direction = DMA_PERIPH_TO_MEMORY; 
    hdma_dcmi_pssi.Init.PeriphInc = DMA_PINC_DISABLE; 
    hdma_dcmi_pssi.Init.MemInc = DMA_MINC_ENABLE; 
    hdma_dcmi_pssi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; 
    hdma_dcmi_pssi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; 
    hdma_dcmi_pssi.Init.Mode = DMA_NORMAL; 
    hdma_dcmi_pssi.Init.Priority = DMA_PRIORITY_VERY_HIGH; 
    hdma_dcmi_pssi.Init.FIFOMode = DMA_FIFOMODE_ENABLE; 
    hdma_dcmi_pssi.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; 
    hdma_dcmi_pssi.Init.MemBurst = DMA_MBURST_SINGLE; 
    hdma_dcmi_pssi.Init.PeriphBurst = DMA_PBURST_SINGLE; 
    if (HAL_DMA_Init(&hdma_dcmi_pssi) != HAL_OK) 
    { 
      Error_Handler(); 
    } 
 
    /* Several peripheral DMA handle pointers point to the same DMA handle. 
     Be aware that there is only one channel to perform all the requested DMAs. */ 
    __HAL_LINKDMA(dcmiHandle,DMA_Handle,hdma_dcmi_pssi); 
 
    /* DCMI interrupt Init */ 
    HAL_NVIC_SetPriority(DCMI_PSSI_IRQn, 2, 0); 
    HAL_NVIC_EnableIRQ(DCMI_PSSI_IRQn); 
  /* USER CODE BEGIN DCMI_MspInit 1 */ 
                 
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET); 
                HAL_Delay(100); 
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET); 
                //printf("HAL_DCMI_MspInit ok\r\n"); 
  /* USER CODE END DCMI_MspInit 1 */ 
  } 
} 
 
void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* dcmiHandle) 
{ 
 
  if(dcmiHandle->Instance==DCMI) 
  { 
  /* USER CODE BEGIN DCMI_MspDeInit 0 */ 
 
  /* USER CODE END DCMI_MspDeInit 0 */ 
    /* Peripheral clock disable */ 
    __HAL_RCC_DCMI_CLK_DISABLE(); 
 
    /**DCMI GPIO Configuration 
    PE4     ------> DCMI_D4 
    PE5     ------> DCMI_D6 
    PE6     ------> DCMI_D7 
    PA4     ------> DCMI_HSYNC 
    PA6     ------> DCMI_PIXCLK 
    PB13     ------> DCMI_D2 
    PA9     ------> DCMI_D0 
    PA10     ------> DCMI_D1 
    PD3     ------> DCMI_D5 
    PB7     ------> DCMI_VSYNC 
    PE1     ------> DCMI_D3 
    */ 
    HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_1); 
 
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9|GPIO_PIN_10); 
 
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_7); 
 
    HAL_GPIO_DeInit(GPIOD, GPIO_PIN_3); 
 
    /* DCMI DMA DeInit */ 
    HAL_DMA_DeInit(dcmiHandle->DMA_Handle); 
 
    /* DCMI interrupt Deinit */ 
    HAL_NVIC_DisableIRQ(DCMI_PSSI_IRQn); 
  /* USER CODE BEGIN DCMI_MspDeInit 1 */ 
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET); 
                HAL_Delay(100); 
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET); 
          printf("HAL_DCMI_MspDeInit ok\r\n"); 
  /* USER CODE END DCMI_MspDeInit 1 */ 
  } 
} 
 
/* USER CODE BEGIN 1 */ 
 
 
void StartOV2640() 
{ 
                int i =0; 
                __HAL_DCMI_ENABLE_IT(&hdcmi, DCMI_IER_FRAME_IE);                                                       //使用帧中断 
    memset(buffer, 0, 65535);                                                                                //把接收BUF清空 
    HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, (uint32_t)buffer, 65535);         //启动拍照 
} 
 
 
void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) 
{ 
          int i =0; 
          HAL_DCMI_Suspend(hdcmi); // 拍照完成,挂起 DCMI 
          HAL_DCMI_Stop(hdcmi);    // 拍照完成,停止 DMA传输 
    int pictureLength = 65535; 
    while (pictureLength > 0)     //循环计算出接收的JPEG的大小 
    { 
        if (buffer[pictureLength - 1] != 0x00000000) 
        { 
          break; 
        } 
        pictureLength--; 
    } 
                jpeglen = pictureLength * 4; 
                getPicture = 1; 
} 
/* USER CODE END 1 */ 
 
 
单片机代码 
 
/* USER CODE BEGIN Header */ 
/** 
  ****************************************************************************** 
  * @file           : main.c 
  * @brief          : Main program body 
  ****************************************************************************** 
  * @attention 
  * 
  * Copyright (c) 2022 STMicroelectronics. 
  * All rights reserved. 
  * 
  * This software is licensed under terms that can be found in the LICENSE file 
  * in the root directory of this software component. 
  * If no LICENSE file comes with this software, it is provided AS-IS. 
  * 
  ****************************************************************************** 
  */ 
/* USER CODE END Header */ 
/* Includes ------------------------------------------------------------------*/ 
#include "main.h" 
#include "adc.h" 
#include "dcmi.h" 
#include "dma.h" 
#include "rtc.h" 
#include "usart.h" 
#include "gpio.h" 
 
/* Private includes ----------------------------------------------------------*/ 
/* USER CODE BEGIN Includes */ 
#include <stdio.h> 
#include "ov2640.h" 
#include "ov5640.h" 
#include <string.h> 
/* USER CODE END Includes */ 
 
/* Private typedef -----------------------------------------------------------*/ 
/* USER CODE BEGIN PTD */ 
 
/* USER CODE END PTD */ 
 
/* Private define ------------------------------------------------------------*/ 
/* USER CODE BEGIN PD */ 
/* USER CODE END PD */ 
 
/* Private macro -------------------------------------------------------------*/ 
/* USER CODE BEGIN PM */ 
 
/* USER CODE END PM */ 
 
/* Private variables ---------------------------------------------------------*/ 
 
/* USER CODE BEGIN PV */ 
 
/* USER CODE END PV */ 
 
/* Private function prototypes -----------------------------------------------*/ 
void SystemClock_Config(void); 
/* USER CODE BEGIN PFP */ 
 
/* USER CODE END PFP */ 
 
/* Private user code ---------------------------------------------------------*/ 
/* USER CODE BEGIN 0 */ 
 
#define OV2640_JPEG_WIDTH         1600        //JPEG拍照的宽度         
#define OV2640_JPEG_HEIGHT 1200                //JPEG拍照的高度 
 
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) 
PUTCHAR_PROTOTYPE 
{ 
                USART1->TDR = ch; 
                while(!(USART1->ISR& USART_ISR_TXE_TXFNF_Msk))  
                {;} 
                 return ch; 
} 
 
static void CPU_CACHE_Enable(void) 
{ 
        SCB_EnableICache();//使能I-Cache 
  SCB_EnableDCache();//使能D-Cache    
        SCB->CACR|=1<<2;   //强制D-Cache透写,如不开启,实际使用中可能遇到各种问题         
} 
 
void Send(uint8_t *pData) 
{ 
        uint32_t i = 0; 
        printf("jpeg data size:%d\r\n",jpeglen);//串口打印JPEG文件大小         
        HAL_Delay(1000);                 
        for(i = 0;i < jpeglen;i++) 
        { 
                //printf("%02x\t",pData); 
                printf("%c",pData); 
        } 
        HAL_Delay(1000);                 
        printf("\r\n"); 
} 
 
/* USER CODE END 0 */ 
 
/** 
  * @brief  The application entry point. 
  * @retval int 
  */ 
int main(void) 
{ 
  /* USER CODE BEGIN 1 */ 
        uint32_t i = 0; 
        uint32_t index = 1; 
        //CPU_CACHE_Enable(); 
  /* USER CODE END 1 */ 
 
  /* MCU Configuration--------------------------------------------------------*/ 
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 
  HAL_Init(); 
 
  /* USER CODE BEGIN Init */ 
 
  /* USER CODE END Init */ 
 
  /* Configure the system clock */ 
  SystemClock_Config(); 
 
  /* USER CODE BEGIN SysInit */ 
        HAL_Delay(5000); 
        //__enable_irq(); 
  /* USER CODE END SysInit */ 
 
  /* Initialize all configured peripherals */ 
  MX_GPIO_Init(); 
  MX_RTC_Init(); 
  MX_USART1_UART_Init(); 
  MX_USART2_UART_Init(); 
  MX_DMA_Init(); 
  MX_ADC1_Init(); 
  MX_USART3_UART_Init(); 
  /* USER CODE BEGIN 2 */ 
        HAL_Delay(100); 
        MX_DCMI_Init(); 
                 
        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET); 
        HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET); 
         
        HAL_Delay(1000); 
         
         
//        HAL_DCMI_DeInit(&hdcmi); 
//  PY_DCMI_Full_Init(); 
         
  /* USER CODE END 2 */ 
 
  /* Infinite loop */ 
  /* USER CODE BEGIN WHILE */ 
  while (1) 
  { 
                printf("OV2640 初始化!cam:%d\r\n",index); 
                while(OV2640_Init(index))                         
                { 
                        printf("OV2640 错误!cam:%d\r\n",index); 
                } 
                printf("OV2640 成功!cam:%d\r\n",index); 
                HAL_Delay(1000); 
                if(1) 
                { 
                        OV2640_JPEG_Mode();        //切换为JPEG模式  
                        printf("切换为JPEG模式 !\r\n"); 
                        OV2640_OutSize_Set(OV2640_JPEG_WIDTH,OV2640_JPEG_HEIGHT);  
                        printf("设置图像大小 !\r\n"); 
                        SCCB_WR_Reg(0XFF,0X00); 
                        SCCB_WR_Reg(0XD3,0X10); 
                        SCCB_WR_Reg(0XFF,0X01); 
                        SCCB_WR_Reg(0X11,0X8);  
                } 
                if(0) 
                { 
                        OV2640_RGB565_Mode();                        //RGB565模式 
                        printf("RGB565模式 !\r\n"); 
                        OV2640_OutSize_Set(OV2640_JPEG_WIDTH,OV2640_JPEG_HEIGHT);  
                        printf("设置图像大小 !\r\n"); 
                        SCCB_WR_Reg(0XFF,0X00);                 
                        SCCB_WR_Reg(0XD3,0X12);        //设置PCLK分频 
                        SCCB_WR_Reg(0XFF,0X01); 
                        SCCB_WR_Reg(0X11,0X1);        //设置CLK分频         
                } 
                printf("开始工作\r\n"); 
                HAL_Delay(100); 
                //Get_Photo(); 
                //DCMI_Start(); 
                StartOV2640(); 
                HAL_Delay(1000);                 
                while(1) 
                { 
                        if(getPicture==1) 
                        { 
                                Send((uint8_t *)buffer); 
                                break; 
                        } 
                        else 
                        { 
                                //printf("adc start\r\n"); 
                                //GetValue(); 
                                //printf("adc end\r\n"); 
                                HAL_Delay(10); 
                                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET); 
                                HAL_Delay(10); 
                                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET); 
                        }         
                        //printf("jpeg haven't finished\r\n");                 
                }         
                if(index>3) 
                { 
                        index = 1; 
                } 
                else 
                { 
                        index++; 
                } 
 
    /* USER CODE END WHILE */ 
 
    /* USER CODE BEGIN 3 */ 
  } 
  /* USER CODE END 3 */ 
} 
 
/** 
  * @brief System Clock Configuration 
  * @retval None 
  */ 
void SystemClock_Config(void) 
{ 
  RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 
 
  /** Supply configuration update enable 
  */ 
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); 
 
  /** Configure the main internal regulator output voltage 
  */ 
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); 
 
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {} 
 
  /** Macro to configure the PLL clock source 
  */ 
  __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSI); 
 
  /** Initializes the RCC Oscillators according to the specified parameters 
  * in the RCC_OscInitTypeDef structure. 
  */ 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI; 
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1; 
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 
  RCC_OscInitStruct.LSIState = RCC_LSI_ON; 
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 
  RCC_OscInitStruct.PLL.PLLM = 4; 
  RCC_OscInitStruct.PLL.PLLN = 35; 
  RCC_OscInitStruct.PLL.PLLP = 2; 
  RCC_OscInitStruct.PLL.PLLQ = 2; 
  RCC_OscInitStruct.PLL.PLLR = 2; 
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3; 
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; 
  RCC_OscInitStruct.PLL.PLLFRACN = 0; 
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 
  { 
    Error_Handler(); 
  } 
 
  /** Initializes the CPU, AHB and APB buses clocks 
  */ 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK 
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1; 
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; 
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1; 
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; 
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; 
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; 
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; 
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) 
  { 
    Error_Handler(); 
  } 
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_8); 
} 
 
/* USER CODE BEGIN 4 */ 
 
/* USER CODE END 4 */ 
 
/** 
  * @brief  This function is executed in case of error occurrence. 
  * @retval None 
  */ 
void Error_Handler(void) 
{ 
  /* USER CODE BEGIN Error_Handler_Debug */ 
        printf("Error_Handler\r\n"); 
  /* User can add his own implementation to report the HAL error return state */ 
  __disable_irq(); 
        HAL_Delay(1000);                 
  while (1) 
  { 
  } 
  /* USER CODE END Error_Handler_Debug */ 
} 
 
#ifdef  USE_FULL_ASSERT 
/** 
  * @brief  Reports the name of the source file and the source line number 
  *         where the assert_param error has occurred. 
  * @param  file: pointer to the source file name 
  * @param  line: assert_param error line source number 
  * @retval None 
  */ 
void assert_failed(uint8_t *file, uint32_t line) 
{ 
  /* USER CODE BEGIN 6 */ 
  /* User can add his own implementation to report the file name and line number, 
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 
  /* USER CODE END 6 */ 
} 
#endif /* USE_FULL_ASSERT */ 
 
 
———————————————— 
 
                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 
 
原文链接:https://blog.csdn.net/g313105910/article/details/126894008 
 
 |   
     
  
 |