[STM32F4] STM32F4 使用 USB_OTG_FS + FatFS 高速数据记录

[复制链接]
37|2
codekid 发表于 2026-9-1 23:33 | 显示全部楼层 |阅读模式
我需要把多个传感器的数据记录到 U 盘,采样频率 500Hz。

我配置了定时器来设置数据记录的采样频率,整体运行正常。问题出在向日志文件写入数据时,写入操作会带来不规则的延时。

目前我已经试过:使用多种缓冲方案,对齐扇区大小;将 U 盘格式化为 FAT32、FAT16、exFAT;精简代码,只保留记录相关的写入逻辑等等。

有没有办法提升写入速度?

下面是 main 函数代码片段:

if(eff==1){
  if(fs==1){
    HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, RESET);
    myData = LIS3DSH_GetDataScaled();
    x=(int)(myData.x*9806.65);
    acc_raw[k]=x;
    k++;
    y=(int)(myData.y*9806.65);
    acc_raw[k]=y;
    k++;
    z=(int)(myData.z*9806.65);
    acc_raw[k]=z;
    k++;
    HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, SET);
    fs=0;
  }
  if(k==99){
    s++;
    for(int g=0; g<98; g=g+3){
      f_printf(&myFilea, "%d : %d, %d, %d\n", s, acc_raw[g], acc_raw[g+1], acc_raw[g+2] );
    }
    k=0;
    bufclear1();
  }

  if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET && write_var==0){
    i=0;
    write_var=1;
    while(deb<250){
    }
    eff=1;
  }

  if(one_sec==500 && write_var==1){
    for(int g=0; g<98; g=g+3){
      f_printf(&myFilea, "%d : %d, %d, %d\n", s+1, acc_raw[g], acc_raw[g+1], acc_raw[g+2] );
    }
    HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_RESET);
    f_close(&myFilea);
    f_close(&myFilet);
    write_var=0;
    s=0;
    deb=0;
    eff=0;
    open=0;
    one_sec=0;
    acqu_count++;
    HAL_Delay(500);
  }
}
if(Appli_state == APPLICATION_DISCONNECT){
  HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
  open=0;
}
if(open==0){
  switch(Appli_state){
    case APPLICATION_IDLE:
      break;
    case APPLICATION_START:
      res=f_mount(&myUsbFatFS, (TCHAR const*)USBHPath, 0);
      if( res != FR_OK)
      {
        /* FatFs Initialization Error */
        Error_Handler();
      }
      else
      {
        //HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
      }
      break;
    case APPLICATION_READY:
      sprintf (buffer, "A%d.bin",acqu_count);
      res=f_open(&myFilea, buffer, FA_OPEN_APPEND | FA_WRITE );
      bufclear();
      open=1;
      HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET );
      break;
    case APPLICATION_DISCONNECT:
      //tUTRN GREEN ON
      HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
      break;
  }
}

定时器中断回调函数:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
  HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);

  if(eff==1){
    one_sec++;
  }

  if(write_var==1){
    deb++;
    fs=1;
    if(temp_counter <250) temp_counter++;
    else {
      fs_temp=1;
      temp_counter=0;
    }
    //i=1-i;


香水城 发表于 2026-9-2 11:05 | 显示全部楼层
几点参考建议:
        采样优先级要高,要有保证。你现在每 2"ms"  采样一次,这条链路不要被写盘阻塞。

        先存 RAM,再写 U 盘。U 盘不是实时设备,适合后台批量写;

        f_printf 不适合实时记录,解析太费时间。f_write 适合日志;

        按块写,尽量回避不零碎写。比方以 4"KB"  或更大为单位写,减少抖动影响;

           缓冲容量按“U 盘最坏卡顿时间”来定,换句话说,缓冲要能扛卡顿。
亚瑟 发表于 2026-9-2 11:36 | 显示全部楼层
检查USB OTG的时钟配置,可能时钟不够稳定导致延时。可以考虑使用外部晶振,或者调整内部时钟分频设置。同时,写入时先清空缓冲区,减少数据写入中断次数。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

666

帖子

1

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