• STM32H7B0 HAL库中关于DMA的注意事项以及DCMI调试遇到的问题及解决方法


    先总结总结问题

    问题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透写,如不开启,实际使用中可能遇到各种问题    
    }

    启动采集代码

    1. void StartOV2640()
    2. {
    3. int i =0;
    4. __HAL_DCMI_ENABLE_IT(&hdcmi, DCMI_IER_FRAME_IE); //使用帧中断
    5. memset(buffer, 0, 65535); //把接收BUF清空
    6. HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, (uint32_t)buffer, 65535); //启动拍照
    7. }
    8. void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
    9. {
    10. int i =0;
    11. HAL_DCMI_Suspend(hdcmi); // 拍照完成,挂起 DCMI
    12. HAL_DCMI_Stop(hdcmi); // 拍照完成,停止 DMA传输
    13. int pictureLength = 65535;
    14. while (pictureLength > 0) //循环计算出接收的JPEG的大小
    15. {
    16. if (buffer[pictureLength - 1] != 0x00000000)
    17. {
    18. break;
    19. }
    20. pictureLength--;
    21. }
    22. jpeglen = pictureLength * 4;
    23. getPicture = 1;
    24. }

    配置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#写的,关键部分代码

    1. private const int count = 200 * 1024;
    2. private byte[] buffer = new byte[count];
    3. private int offset = 0;
    4. private int length = 0;
    5. private bool isData = false;
    6. public void DataCallBack(Object sender, SerialDataReceivedEventArgs e)
    7. {
    8. try
    9. {
    10. if (isData==false)
    11. {
    12. var data = _serialPort.ReadLine();
    13. if (!string.IsNullOrEmpty(data) && data.Length > 0)
    14. {
    15. if(data.IndexOf("jpeg data size:")>=0)
    16. {
    17. var lengthStr = data.Split(':');
    18. if(lengthStr != null && lengthStr.Length>1)
    19. {
    20. length = int.Parse(lengthStr[1]);
    21. if (length > count)
    22. {
    23. }
    24. else
    25. {
    26. isData = true;
    27. }
    28. }
    29. Console.WriteLine(data);
    30. }
    31. else
    32. {
    33. Console.WriteLine(data);
    34. }
    35. }
    36. }
    37. else
    38. {
    39. int thisLength = _serialPort.Read(buffer, offset, length - offset);
    40. offset = offset + thisLength;
    41. if(offset >= length)
    42. {
    43. Console.WriteLine($"接收完一张图片,offset:{offset},length:{length}");
    44. string path = Directory.GetCurrentDirectory();
    45. DirectoryCheak(path + "\\out\\");
    46. bool ispictrue = false;
    47. if (false)//bmp
    48. {
    49. //bmp
    50. if (false)
    51. {
    52. //RGB888
    53. System.Drawing.Bitmap formBitmap = new System.Drawing.Bitmap(96, 96);
    54. for (int i = 0; i < 96; i++)
    55. {
    56. for (int j = 0; j < 96; j++)
    57. {
    58. formBitmap.SetPixel(i, j, System.Drawing.Color.FromArgb(buffer[i * j + j], buffer[i * j + j + 1], buffer[i * j + j + 2]));
    59. }
    60. }
    61. formBitmap.Save(path + "\\out\\" + DateTime.Now.ToString("yyyyMMdd-HHmmss.fff") + ".bmp");
    62. }
    63. else
    64. {
    65. //RGB565
    66. List data = new List();
    67. for (int i = 0; i < length; i += 2)
    68. {
    69. UInt16 thisData = (UInt16)((buffer[i] << 8) | buffer[i + 1]); ;
    70. data.Add(thisData);
    71. }
    72. System.Drawing.Bitmap formBitmap = new System.Drawing.Bitmap(96, 96);
    73. for (int i = 0; i < 96; i++)
    74. {
    75. for (int j = 0; j < 96; j++)
    76. {
    77. byte red = (byte)((data[i * j + j] >> 11) << 3); //5位 移动3位
    78. byte green = (byte)(((data[i * j + j] << 5) >> 10) << 2); //6位 移动2位
    79. byte blue = (byte)(((data[i * j + j] << 11) >> 11) << 3); //5位 移动3位
    80. formBitmap.SetPixel(i, j, System.Drawing.Color.FromArgb(red, green, blue));
    81. }
    82. }
    83. formBitmap.Save(path + "\\out\\" + DateTime.Now.ToString("yyyyMMdd-HHmmss.fff") + ".bmp");
    84. }
    85. }
    86. else
    87. {
    88. List<byte> data = new List<byte>();
    89. for (int i = 1; i < length; i++)
    90. {
    91. //Console.WriteLine($"i:{i},length:{length}");
    92. if (ispictrue == true)
    93. {
    94. data.Add(buffer[i]);
    95. }
    96. else if ((buffer[i - 1] == 0xFF) && (buffer[i] == 0xd8))
    97. {
    98. ispictrue = true;
    99. data.Add(buffer[i - 1]);
    100. data.Add(buffer[i]);
    101. }
    102. //if((buffer[i - 1] == 0xFF) && (buffer[i] == 0xd9))
    103. //{
    104. // data.Add(buffer[i - 1]);
    105. // data.Add(buffer[i]);
    106. // ispictrue = false;
    107. // break;
    108. //}
    109. }
    110. WriteFileUsingBinaryWriter(path + "\\out\\", DateTime.Now.ToString("yyyyMMdd-HHmmss.fff") + ".jpg", data.ToArray(), data.Count());
    111. }
    112. offset = 0;
    113. length = 0;
    114. isData = false;
    115. }
    116. }
    117. }
    118. catch (Exception ex)
    119. {
    120. Console.WriteLine("串口解析出错" + ex.ToString());
    121. }
    122. }
    123. public void WriteFileUsingBinaryWriter(string path,string fileName,byte[] data,int length)
    124. {
    125. var outputStream = File.Create(path + fileName);
    126. using (var writer = new BinaryWriter(outputStream))
    127. {
    128. writer.Write(data, 0, length);
    129. }
    130. }
    131. ///
    132. /// 效验文件夹,没有就创建
    133. ///
    134. private void DirectoryCheak(string path)
    135. {
    136. if (false == System.IO.Directory.Exists(path))
    137. {
    138. System.IO.Directory.CreateDirectory(path);
    139. }
    140. }
    141. private void OpenSerialPort_Click(object sender, RoutedEventArgs e)
    142. {
    143. try
    144. {
    145. _serialPort = new SerialPort();
    146. _serialPort.PortName = SerialPort.Text;
    147. _serialPort.BaudRate = int.Parse(SerialBaudRate.Text);
    148. _serialPort.Parity = Parity.None;
    149. _serialPort.DataBits = 8;
    150. _serialPort.StopBits = StopBits.One;
    151. _serialPort.ReadTimeout = 10000;//单位毫秒
    152. _serialPort.WriteTimeout = 10000;//单位毫秒
    153. //设置串口字节接收缓冲值,通常为1
    154. //获得接收后,触发事件处理
    155. _serialPort.ReceivedBytesThreshold = 1;
    156. _serialPort.DataReceived += new SerialDataReceivedEventHandler(DataCallBack);
    157. _serialPort.Open();//Console.WriteLine(serialPort.IsOpen.ToString());
    158. OpenSerialPort.IsEnabled = false;
    159. CloseSerialPort.IsEnabled = true;
    160. }
    161. catch (Exception ex)
    162. {
    163. MessageBox.Show("串口打开失败" + ex.ToString());
    164. //System.Environment.Exit(0);//退出应用程序
    165. }
    166. }
    167. private void CloseSerialPort_Click(object sender, RoutedEventArgs e)
    168. {
    169. try
    170. {
    171. if (_serialPort.IsOpen == true)
    172. {
    173. _serialPort.Close();
    174. OpenSerialPort.IsEnabled = true;
    175. CloseSerialPort.IsEnabled = false;
    176. }
    177. }
    178. catch (Exception ex)
    179. {
    180. MessageBox.Show("串口关闭失败" + ex.ToString());
    181. System.Environment.Exit(0);//退出应用程序
    182. }
    183. }

    单片机关键部分代码

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file dcmi.c
    5. * @brief This file provides code for the configuration
    6. * of the DCMI instances.
    7. ******************************************************************************
    8. * @attention
    9. *
    10. * Copyright (c) 2022 STMicroelectronics.
    11. * All rights reserved.
    12. *
    13. * This software is licensed under terms that can be found in the LICENSE file
    14. * in the root directory of this software component.
    15. * If no LICENSE file comes with this software, it is provided AS-IS.
    16. *
    17. ******************************************************************************
    18. */
    19. /* USER CODE END Header */
    20. /* Includes ------------------------------------------------------------------*/
    21. #include "dcmi.h"
    22. /* USER CODE BEGIN 0 */
    23. #include
    24. #include
    25. __align(32) uint32_t buffer[65535] __attribute((at(0X24040000)));
    26. unsigned char getPicture = 0;
    27. unsigned int jpeglen = 0;
    28. //unsigned int recvOk = 0;
    29. /* USER CODE END 0 */
    30. DCMI_HandleTypeDef hdcmi;
    31. DMA_HandleTypeDef hdma_dcmi_pssi;
    32. /* DCMI init function */
    33. void MX_DCMI_Init(void)
    34. {
    35. /* USER CODE BEGIN DCMI_Init 0 */
    36. /* USER CODE END DCMI_Init 0 */
    37. /* USER CODE BEGIN DCMI_Init 1 */
    38. /* USER CODE END DCMI_Init 1 */
    39. hdcmi.Instance = DCMI;
    40. hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
    41. hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
    42. hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW;
    43. hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;
    44. hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
    45. hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
    46. hdcmi.Init.JPEGMode = DCMI_JPEG_ENABLE;
    47. hdcmi.Init.ByteSelectMode = DCMI_BSM_ALL;
    48. hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD;
    49. hdcmi.Init.LineSelectMode = DCMI_LSM_ALL;
    50. hdcmi.Init.LineSelectStart = DCMI_OELS_ODD;
    51. if (HAL_DCMI_Init(&hdcmi) != HAL_OK)
    52. {
    53. Error_Handler();
    54. }
    55. /* USER CODE BEGIN DCMI_Init 2 */
    56. //printf("MX_DCMI_Init ok\r\n");
    57. /* USER CODE END DCMI_Init 2 */
    58. }
    59. void HAL_DCMI_MspInit(DCMI_HandleTypeDef* dcmiHandle)
    60. {
    61. GPIO_InitTypeDef GPIO_InitStruct = {0};
    62. if(dcmiHandle->Instance==DCMI)
    63. {
    64. /* USER CODE BEGIN DCMI_MspInit 0 */
    65. //printf("if(dcmiHandle->Instance==DCMI)\r\n");
    66. /* USER CODE END DCMI_MspInit 0 */
    67. /* DCMI clock enable */
    68. __HAL_RCC_DCMI_CLK_ENABLE();
    69. __HAL_RCC_GPIOE_CLK_ENABLE();
    70. __HAL_RCC_GPIOA_CLK_ENABLE();
    71. __HAL_RCC_GPIOB_CLK_ENABLE();
    72. __HAL_RCC_GPIOD_CLK_ENABLE();
    73. /**DCMI GPIO Configuration
    74. PE4 ------> DCMI_D4
    75. PE5 ------> DCMI_D6
    76. PE6 ------> DCMI_D7
    77. PA4 ------> DCMI_HSYNC
    78. PA6 ------> DCMI_PIXCLK
    79. PB13 ------> DCMI_D2
    80. PA9 ------> DCMI_D0
    81. PA10 ------> DCMI_D1
    82. PD3 ------> DCMI_D5
    83. PB7 ------> DCMI_VSYNC
    84. PE1 ------> DCMI_D3
    85. */
    86. GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_1;
    87. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    88. GPIO_InitStruct.Pull = GPIO_NOPULL;
    89. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    90. GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    91. HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    92. GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9|GPIO_PIN_10;
    93. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    94. GPIO_InitStruct.Pull = GPIO_NOPULL;
    95. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    96. GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    97. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    98. GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_7;
    99. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    100. GPIO_InitStruct.Pull = GPIO_NOPULL;
    101. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    102. GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    103. HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    104. GPIO_InitStruct.Pin = GPIO_PIN_3;
    105. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    106. GPIO_InitStruct.Pull = GPIO_NOPULL;
    107. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    108. GPIO_InitStruct.Alternate = GPIO_AF13_DCMI;
    109. HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    110. /* DCMI DMA Init */
    111. /* DCMI_PSSI Init */
    112. hdma_dcmi_pssi.Instance = DMA1_Stream0;
    113. hdma_dcmi_pssi.Init.Request = DMA_REQUEST_DCMI_PSSI;
    114. hdma_dcmi_pssi.Init.Direction = DMA_PERIPH_TO_MEMORY;
    115. hdma_dcmi_pssi.Init.PeriphInc = DMA_PINC_DISABLE;
    116. hdma_dcmi_pssi.Init.MemInc = DMA_MINC_ENABLE;
    117. hdma_dcmi_pssi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    118. hdma_dcmi_pssi.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    119. hdma_dcmi_pssi.Init.Mode = DMA_NORMAL;
    120. hdma_dcmi_pssi.Init.Priority = DMA_PRIORITY_VERY_HIGH;
    121. hdma_dcmi_pssi.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    122. hdma_dcmi_pssi.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
    123. hdma_dcmi_pssi.Init.MemBurst = DMA_MBURST_SINGLE;
    124. hdma_dcmi_pssi.Init.PeriphBurst = DMA_PBURST_SINGLE;
    125. if (HAL_DMA_Init(&hdma_dcmi_pssi) != HAL_OK)
    126. {
    127. Error_Handler();
    128. }
    129. /* Several peripheral DMA handle pointers point to the same DMA handle.
    130. Be aware that there is only one channel to perform all the requested DMAs. */
    131. __HAL_LINKDMA(dcmiHandle,DMA_Handle,hdma_dcmi_pssi);
    132. /* DCMI interrupt Init */
    133. HAL_NVIC_SetPriority(DCMI_PSSI_IRQn, 2, 0);
    134. HAL_NVIC_EnableIRQ(DCMI_PSSI_IRQn);
    135. /* USER CODE BEGIN DCMI_MspInit 1 */
    136. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
    137. HAL_Delay(100);
    138. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
    139. //printf("HAL_DCMI_MspInit ok\r\n");
    140. /* USER CODE END DCMI_MspInit 1 */
    141. }
    142. }
    143. void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* dcmiHandle)
    144. {
    145. if(dcmiHandle->Instance==DCMI)
    146. {
    147. /* USER CODE BEGIN DCMI_MspDeInit 0 */
    148. /* USER CODE END DCMI_MspDeInit 0 */
    149. /* Peripheral clock disable */
    150. __HAL_RCC_DCMI_CLK_DISABLE();
    151. /**DCMI GPIO Configuration
    152. PE4 ------> DCMI_D4
    153. PE5 ------> DCMI_D6
    154. PE6 ------> DCMI_D7
    155. PA4 ------> DCMI_HSYNC
    156. PA6 ------> DCMI_PIXCLK
    157. PB13 ------> DCMI_D2
    158. PA9 ------> DCMI_D0
    159. PA10 ------> DCMI_D1
    160. PD3 ------> DCMI_D5
    161. PB7 ------> DCMI_VSYNC
    162. PE1 ------> DCMI_D3
    163. */
    164. HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_1);
    165. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9|GPIO_PIN_10);
    166. HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_7);
    167. HAL_GPIO_DeInit(GPIOD, GPIO_PIN_3);
    168. /* DCMI DMA DeInit */
    169. HAL_DMA_DeInit(dcmiHandle->DMA_Handle);
    170. /* DCMI interrupt Deinit */
    171. HAL_NVIC_DisableIRQ(DCMI_PSSI_IRQn);
    172. /* USER CODE BEGIN DCMI_MspDeInit 1 */
    173. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
    174. HAL_Delay(100);
    175. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
    176. printf("HAL_DCMI_MspDeInit ok\r\n");
    177. /* USER CODE END DCMI_MspDeInit 1 */
    178. }
    179. }
    180. /* USER CODE BEGIN 1 */
    181. void StartOV2640()
    182. {
    183. int i =0;
    184. __HAL_DCMI_ENABLE_IT(&hdcmi, DCMI_IER_FRAME_IE); //使用帧中断
    185. memset(buffer, 0, 65535); //把接收BUF清空
    186. HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, (uint32_t)buffer, 65535); //启动拍照
    187. }
    188. void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
    189. {
    190. int i =0;
    191. HAL_DCMI_Suspend(hdcmi); // 拍照完成,挂起 DCMI
    192. HAL_DCMI_Stop(hdcmi); // 拍照完成,停止 DMA传输
    193. int pictureLength = 65535;
    194. while (pictureLength > 0) //循环计算出接收的JPEG的大小
    195. {
    196. if (buffer[pictureLength - 1] != 0x00000000)
    197. {
    198. break;
    199. }
    200. pictureLength--;
    201. }
    202. jpeglen = pictureLength * 4;
    203. getPicture = 1;
    204. }
    205. /* USER CODE END 1 */

    单片机代码

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file : main.c
    5. * @brief : Main program body
    6. ******************************************************************************
    7. * @attention
    8. *
    9. * Copyright (c) 2022 STMicroelectronics.
    10. * All rights reserved.
    11. *
    12. * This software is licensed under terms that can be found in the LICENSE file
    13. * in the root directory of this software component.
    14. * If no LICENSE file comes with this software, it is provided AS-IS.
    15. *
    16. ******************************************************************************
    17. */
    18. /* USER CODE END Header */
    19. /* Includes ------------------------------------------------------------------*/
    20. #include "main.h"
    21. #include "adc.h"
    22. #include "dcmi.h"
    23. #include "dma.h"
    24. #include "rtc.h"
    25. #include "usart.h"
    26. #include "gpio.h"
    27. /* Private includes ----------------------------------------------------------*/
    28. /* USER CODE BEGIN Includes */
    29. #include
    30. #include "ov2640.h"
    31. #include "ov5640.h"
    32. #include
    33. /* USER CODE END Includes */
    34. /* Private typedef -----------------------------------------------------------*/
    35. /* USER CODE BEGIN PTD */
    36. /* USER CODE END PTD */
    37. /* Private define ------------------------------------------------------------*/
    38. /* USER CODE BEGIN PD */
    39. /* USER CODE END PD */
    40. /* Private macro -------------------------------------------------------------*/
    41. /* USER CODE BEGIN PM */
    42. /* USER CODE END PM */
    43. /* Private variables ---------------------------------------------------------*/
    44. /* USER CODE BEGIN PV */
    45. /* USER CODE END PV */
    46. /* Private function prototypes -----------------------------------------------*/
    47. void SystemClock_Config(void);
    48. /* USER CODE BEGIN PFP */
    49. /* USER CODE END PFP */
    50. /* Private user code ---------------------------------------------------------*/
    51. /* USER CODE BEGIN 0 */
    52. #define OV2640_JPEG_WIDTH 1600 //JPEG拍照的宽度
    53. #define OV2640_JPEG_HEIGHT 1200 //JPEG拍照的高度
    54. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    55. PUTCHAR_PROTOTYPE
    56. {
    57. USART1->TDR = ch;
    58. while(!(USART1->ISR& USART_ISR_TXE_TXFNF_Msk))
    59. {;}
    60. return ch;
    61. }
    62. static void CPU_CACHE_Enable(void)
    63. {
    64. SCB_EnableICache();//使能I-Cache
    65. SCB_EnableDCache();//使能D-Cache
    66. SCB->CACR|=1<<2; //强制D-Cache透写,如不开启,实际使用中可能遇到各种问题
    67. }
    68. void Send(uint8_t *pData)
    69. {
    70. uint32_t i = 0;
    71. printf("jpeg data size:%d\r\n",jpeglen);//串口打印JPEG文件大小
    72. HAL_Delay(1000);
    73. for(i = 0;i < jpeglen;i++)
    74. {
    75. //printf("%02x\t",pData[i]);
    76. printf("%c",pData[i]);
    77. }
    78. HAL_Delay(1000);
    79. printf("\r\n");
    80. }
    81. /* USER CODE END 0 */
    82. /**
    83. * @brief The application entry point.
    84. * @retval int
    85. */
    86. int main(void)
    87. {
    88. /* USER CODE BEGIN 1 */
    89. uint32_t i = 0;
    90. uint32_t index = 1;
    91. //CPU_CACHE_Enable();
    92. /* USER CODE END 1 */
    93. /* MCU Configuration--------------------------------------------------------*/
    94. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    95. HAL_Init();
    96. /* USER CODE BEGIN Init */
    97. /* USER CODE END Init */
    98. /* Configure the system clock */
    99. SystemClock_Config();
    100. /* USER CODE BEGIN SysInit */
    101. HAL_Delay(5000);
    102. //__enable_irq();
    103. /* USER CODE END SysInit */
    104. /* Initialize all configured peripherals */
    105. MX_GPIO_Init();
    106. MX_RTC_Init();
    107. MX_USART1_UART_Init();
    108. MX_USART2_UART_Init();
    109. MX_DMA_Init();
    110. MX_ADC1_Init();
    111. MX_USART3_UART_Init();
    112. /* USER CODE BEGIN 2 */
    113. HAL_Delay(100);
    114. MX_DCMI_Init();
    115. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET);
    116. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
    117. HAL_Delay(1000);
    118. // HAL_DCMI_DeInit(&hdcmi);
    119. // PY_DCMI_Full_Init();
    120. /* USER CODE END 2 */
    121. /* Infinite loop */
    122. /* USER CODE BEGIN WHILE */
    123. while (1)
    124. {
    125. printf("OV2640 初始化!cam:%d\r\n",index);
    126. while(OV2640_Init(index))
    127. {
    128. printf("OV2640 错误!cam:%d\r\n",index);
    129. }
    130. printf("OV2640 成功!cam:%d\r\n",index);
    131. HAL_Delay(1000);
    132. if(1)
    133. {
    134. OV2640_JPEG_Mode(); //切换为JPEG模式
    135. printf("切换为JPEG模式 !\r\n");
    136. OV2640_OutSize_Set(OV2640_JPEG_WIDTH,OV2640_JPEG_HEIGHT);
    137. printf("设置图像大小 !\r\n");
    138. SCCB_WR_Reg(0XFF,0X00);
    139. SCCB_WR_Reg(0XD3,0X10);
    140. SCCB_WR_Reg(0XFF,0X01);
    141. SCCB_WR_Reg(0X11,0X8);
    142. }
    143. if(0)
    144. {
    145. OV2640_RGB565_Mode(); //RGB565模式
    146. printf("RGB565模式 !\r\n");
    147. OV2640_OutSize_Set(OV2640_JPEG_WIDTH,OV2640_JPEG_HEIGHT);
    148. printf("设置图像大小 !\r\n");
    149. SCCB_WR_Reg(0XFF,0X00);
    150. SCCB_WR_Reg(0XD3,0X12); //设置PCLK分频
    151. SCCB_WR_Reg(0XFF,0X01);
    152. SCCB_WR_Reg(0X11,0X1); //设置CLK分频
    153. }
    154. printf("开始工作\r\n");
    155. HAL_Delay(100);
    156. //Get_Photo();
    157. //DCMI_Start();
    158. StartOV2640();
    159. HAL_Delay(1000);
    160. while(1)
    161. {
    162. if(getPicture==1)
    163. {
    164. Send((uint8_t *)buffer);
    165. break;
    166. }
    167. else
    168. {
    169. //printf("adc start\r\n");
    170. //GetValue();
    171. //printf("adc end\r\n");
    172. HAL_Delay(10);
    173. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
    174. HAL_Delay(10);
    175. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
    176. }
    177. //printf("jpeg haven't finished\r\n");
    178. }
    179. if(index>3)
    180. {
    181. index = 1;
    182. }
    183. else
    184. {
    185. index++;
    186. }
    187. /* USER CODE END WHILE */
    188. /* USER CODE BEGIN 3 */
    189. }
    190. /* USER CODE END 3 */
    191. }
    192. /**
    193. * @brief System Clock Configuration
    194. * @retval None
    195. */
    196. void SystemClock_Config(void)
    197. {
    198. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    199. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    200. /** Supply configuration update enable
    201. */
    202. HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
    203. /** Configure the main internal regulator output voltage
    204. */
    205. __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
    206. while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
    207. /** Macro to configure the PLL clock source
    208. */
    209. __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSI);
    210. /** Initializes the RCC Oscillators according to the specified parameters
    211. * in the RCC_OscInitTypeDef structure.
    212. */
    213. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
    214. RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
    215. RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    216. RCC_OscInitStruct.LSIState = RCC_LSI_ON;
    217. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    218. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    219. RCC_OscInitStruct.PLL.PLLM = 4;
    220. RCC_OscInitStruct.PLL.PLLN = 35;
    221. RCC_OscInitStruct.PLL.PLLP = 2;
    222. RCC_OscInitStruct.PLL.PLLQ = 2;
    223. RCC_OscInitStruct.PLL.PLLR = 2;
    224. RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
    225. RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
    226. RCC_OscInitStruct.PLL.PLLFRACN = 0;
    227. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    228. {
    229. Error_Handler();
    230. }
    231. /** Initializes the CPU, AHB and APB buses clocks
    232. */
    233. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    234. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
    235. |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
    236. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    237. RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
    238. RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
    239. RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
    240. RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
    241. RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
    242. RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
    243. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
    244. {
    245. Error_Handler();
    246. }
    247. HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_8);
    248. }
    249. /* USER CODE BEGIN 4 */
    250. /* USER CODE END 4 */
    251. /**
    252. * @brief This function is executed in case of error occurrence.
    253. * @retval None
    254. */
    255. void Error_Handler(void)
    256. {
    257. /* USER CODE BEGIN Error_Handler_Debug */
    258. printf("Error_Handler\r\n");
    259. /* User can add his own implementation to report the HAL error return state */
    260. __disable_irq();
    261. HAL_Delay(1000);
    262. while (1)
    263. {
    264. }
    265. /* USER CODE END Error_Handler_Debug */
    266. }
    267. #ifdef USE_FULL_ASSERT
    268. /**
    269. * @brief Reports the name of the source file and the source line number
    270. * where the assert_param error has occurred.
    271. * @param file: pointer to the source file name
    272. * @param line: assert_param error line source number
    273. * @retval None
    274. */
    275. void assert_failed(uint8_t *file, uint32_t line)
    276. {
    277. /* USER CODE BEGIN 6 */
    278. /* User can add his own implementation to report the file name and line number,
    279. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    280. /* USER CODE END 6 */
    281. }
    282. #endif /* USE_FULL_ASSERT */

  • 相关阅读:
    SQL sever中的索引
    electron + vue3 + ts 打包后安装打开白屏解决
    TeXLive 2023安装教程
    MySQL篇之SQL优化
    OpenAI变天:也许会有另一个OpenAI要崛起?
    HCIA网络基础7-VRP和命令行基础
    精准用户画像!商城用户分群2.0!⛵
    一个bug引发的对大端小端的深入思考
    《Vue.js实战》第7章答案
    python 装饰器
  • 原文地址:https://blog.csdn.net/g313105910/article/details/126894008