AD采集-高速存储至SD卡

一、前言

  现在需要将ADC采集到的数据储存至SD卡中,ADC采用AD7764,处理器采用STM32F103ZET6。下面对设计过程进行记录。

1.1 AD7764介绍

  • 312K输出,109db信噪比。
  • 输出速率由外部时钟控制
  • DMA数据传输

1.2 SD卡储存方式介绍

  • SDIO协议
  • DMA数据传输
  • FatFs文件系统(传输速率最高1M)

1.3 控制方式

  • 开始采集按钮
  • 关闭采集按钮
  • 屏幕刷新按钮(后期实现)

二、方案介绍

2.1 方案一

  • AD7764采集数据存储到SRAM中,触发中断
  • 中断程序调用SD卡储存程序
    注:这种方法比较容易实现,但是可能会引起数据保存速率的降低,先用这种方法作为测试。

2.2 方案二

  • 开辟1024字节的储存空间BUFF。
  • AD7764采集到的数据储存到这个BUFF中,储存一半后触发中断。
  • 在中断程序中调用存储程序,储存一半结束,等待下一次中断

2.3 控制方案

  功能比较简单,三个按钮对应三个功能,用传统方式就好。注:复杂的控制推荐使用状态机的方式。

三、实现步骤

3.1 SD卡相关

3.1.1 SDIO+DMA基础驱动

  采用官方的驱动,驱动下载链接附上:sdio_sdcard.csdio_sdcard.h。如果引脚对应上了,就不需要进行修改。如果没有对应上,需要修改引脚,中断,DMA设置。我运气好,对应上了[滑稽]。
  测试方法可以使用SD_ReadBlock,和SD_WriteBlock两个函数进行测试,注:每次读可以的大小为:1~512,写的最小单位是512字节,对应不上则会出错。因为这个原因,我选择了死亡Fatfs文件系统。

3.1.2 Fatfs移植

  由于文件比较多,可以去官网下载,在上一小节移植成功了后,只需要修改ff.c这一个文件,修改两个地方如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
if(count==1)
{
SD_ReadBlock((u32 *)(&buff[0]),sector << 9 ,SECTOR_SIZE);

}
return RES_OK;
}

DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
if(count==1)
{
SD_WriteBlock((u32 *)(&buff[0]),sector << 9 ,SECTOR_SIZE);
}
return RES_OK;
}

  移植成功后,先进行测试。测试代码如下(要是代码可折叠显示就好了):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SD_Check();  //挂载SD卡,测试是否成功
if (f_open(&fsrc,path,FA_OPEN_ALWAYS | FA_WRITE) != FR_OK) //如果不存在则新建文件,只写模式
printf("file open failed \r\n");
f_lseek(&fsrc,fsrc.fsize); //跳转到文件末尾,进行添加
a = f_write(&fsrc,"hello worlasdfas",20,&br);
printf("%d \r\n",a); //打印返回数据,用于测试
f_close(&fsrc);

if (f_open(&fsrc,path,FA_READ) != FR_OK)
printf("file open failed2 \r\n");

a = f_read(&fsrc,buffsd,40,&br);
printf("%d \r\n",a);
f_close(&fsrc);

str_print((const char*)buffsd,40);

  至此,SD卡驱动已经全部移植成功。

3.2 AD7764电压采集

  目标实现功能如下:

3.2.1 SPI配置相关
3.2.2 DMA配置相关
3.3.3 中断配置相关
3.3.4 双缓存结构

  为了实现一边采集数据,一边储存至SD卡中,采用双缓存结构实现,可参考文章

3.2.5 读取控制程序相关
3.2.6 SPI从机模拟

  由于手上没有AD7764的板子,需要用STM32模拟一个,可参考文章

3.3 控制功能实现

  按键实现以下功能:

  • 按下按键后有效,只会生效一次,再次有效需要松开再按
  • 支持多个按键同时按下
  • 不阻塞
  • 软件消抖
  • 每个按键对应一个功能
    实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
u8 Get_key()
{
static u8 preKey = 0x00;
u8 temp;
temp = KEY_Scan();

delay_ms(20);

if (temp == KEY_Scan())
{
if (preKey != temp)
{
preKey = temp;
return preKey;
}
}

return 0;
}

int Key_Control()
{
u8 a = Get_key();

switch(a)
{
case 0x80:printf("wk_up");break; // wk_up
case 0x40:printf("key0");break; // key0
case 0x20:printf("key1");break; // key1
default:;break;
}
}

  担心有小伙伴不能理解KEY_Scan()的实现方式,他这个函数和硬件相关,不同硬件编写有些不一样,下面也附上代码作为参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
u8 KEY_Scan()
{
u8 temp = 0;
u8 i;

for (i = 0;i < 2;i ++)
{
temp >>= 1;
if (!PEin(i + 3))
temp |= 0x80;
}

temp >>= 1;
if (PAin(0))
{
temp |= 0x80;
}
return temp;
}

3.4 显示功能实现

  功能暂时用不上保留,后期有需求在补上

四、测试

4.1 ADC测试

4.2 SD卡测试

4.3 储存速度测试

五、总结

  虽然还没有做完,但是牛批!!!

-------------本文结束感谢您的阅读-------------
0%