[应用相关] DMA从内存搬运数据到I2C

[复制链接]
749|12
 楼主| 598330983 发表于 2023-4-26 22:03 | 显示全部楼层 |阅读模式
  1. #include "stm32f4xx_hal.h"

  2. I2C_HandleTypeDef hi2c1;
  3. DMA_HandleTypeDef hdma_i2c1_tx;

  4. /* 定义数据缓存区 */
  5. uint8_t data_buf[10] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A};

  6. int main(void)
  7. {
  8.   /* STM32初始化 */
  9.   HAL_Init();

  10.   /* 配置I2C1 */
  11.   hi2c1.Instance = I2C1;
  12.   hi2c1.Init.ClockSpeed = 100000;
  13.   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  14.   hi2c1.Init.OwnAddress1 = 0;
  15.   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  16.   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  17.   hi2c1.Init.OwnAddress2 = 0;
  18.   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  19.   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  20.   if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  21.   {
  22.     Error_Handler();
  23.   }

  24.   /* 配置I2C1的DMA传输 */
  25.   hdma_i2c1_tx.Instance = DMA1_Stream7;
  26.   hdma_i2c1_tx.Init.Channel = DMA_CHANNEL_1;
  27.   hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  28.   hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  29.   hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
  30.   hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  31.   hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  32.   hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
  33.   hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_HIGH;
  34.   hdma_i2c1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
  35.   if (HAL_DMA_Init(&hdma_i2c1_tx) != HAL_OK)
  36.   {
  37.     Error_Handler();
  38.   }
  39.   __HAL_LINKDMA(&hi2c1, hdmatx, hdma_i2c1_tx);

  40.   /* 启动I2C1的DMA传输 */
  41.   if (HAL_I2C_Mem_Write_DMA(&hi2c1, 0xA0, 0x00, I2C_MEMADD_SIZE_8BIT, data_buf, 10) != HAL_OK)
  42.   {
  43.     Error_Handler();
  44.   }

  45.   /* 死循环 */
  46.   while (1)
  47.   {
  48.   }
  49. }

  50. /* 错误处理函数 */
  51. void Error_Handler(void)
  52. {
  53.   while (1)
  54.   {
  55.   }
  56. }

  57. /* DMA中断处理函数 */
  58. void DMA1_Stream7_IRQHandler(void)
  59. {
  60.   HAL_DMA_IRQHandler(&hdma_i2c1_tx);
  61. }


 楼主| 598330983 发表于 2023-4-26 22:03 | 显示全部楼层
以上代码中,首先初始化了I2C1接口和DMA传输通道。然后将数据缓存区data_buf中的数据通过DMA传输到I2C1的0xA0地址中,传输长度为10字节。传输的过程使用了HAL库提供的HAL_I2C_Mem_Write_DMA函数,该函数会将数据缓存区的数据通过DMA传输到指定地址中。

在初始化DMA传输通道之后,使用__HAL_LINKDMA宏将I2C1接口的发送DMA通道和DMA传输通道关联起来。然后,调用HAL_I2C_Mem_Write_DMA函数启动I2C1的DMA传输。
 楼主| 598330983 发表于 2023-4-26 22:04 | 显示全部楼层
最后,在代码中还提供了一个错误处理函数Error_Handler,以及一个DMA中断处理函数DMA1_Stream7_IRQHandler。当DMA传输完成或出现错误时,会触发DMA中断,该中断处理函数会被调用。在中断处理函数中调用HAL_DMA_IRQHandler函数处理中断。

注意,在使用DMA传输时,需要确保数据缓存区的空间和传输长度的大小是足够的,否则会导致数据溢出。同时,需要根据具体的硬件平台和需求设置DMA传输通道的参数,以确保传输的正确性和稳定性。
童雨竹 发表于 2024-6-11 08:02 | 显示全部楼层

让PCB顶层和底层一样,将它们通过一些过孔(或通孔)连接
Wordsworth 发表于 2024-6-11 09:05 | 显示全部楼层

孔璧里头必须经过电镀
Clyde011 发表于 2024-6-11 10:08 | 显示全部楼层

需要将阻焊漆(阻焊油墨)覆盖在最外层的PCB设计布线上
公羊子丹 发表于 2024-6-11 11:01 | 显示全部楼层

电源中都有一个交流电压最大的节点
万图 发表于 2024-6-11 12:04 | 显示全部楼层

做多层板可将做好的两块双面板用特制的粘合剂“压合”起来
Uriah 发表于 2024-6-11 13:07 | 显示全部楼层

清除与电镀动作都会在化学过程中完成
帛灿灿 发表于 2024-6-11 15:03 | 显示全部楼层

将整个表面铺上一层薄薄的铜箔,并且把多余的部份给消除
Bblythe 发表于 2024-6-11 16:06 | 显示全部楼层

在开始电镀之前,必须先清掉孔内的杂物。
周半梅 发表于 2024-6-11 18:02 | 显示全部楼层

电容工作在额定的纹波电流下
Pulitzer 发表于 2024-6-11 19:05 | 显示全部楼层

在孔璧内部作金属处理后,可以让内部的各层线路能够彼此连接。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

267

主题

5575

帖子

22

粉丝
快速回复 在线客服 返回列表 返回顶部