• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

stm32F103设计的长时间采集数据存储

STM32F103芯片属于中低端的32位ARM微控制器,ARM 32位的Cortex-M3的核,高达72MHz工作频率,小容量型号的FLASH大小是16K和32K、中容量型号的FLASH大小是64K和128K、大容量型号的FLASH大小是256K、384K和512K。

该芯片用的比较多,主要是低功耗,性能出色,集成的外设也多,满足大部分的电子产品应用功能开发。本次主要是用STM32F103自带的AD或者外扩高精度的ADC芯片采集数据,并将数据实时保存在SD卡上。

全部回复(36)
正序查看
倒序查看
k6666
LV.9
2
2021-04-23 13:56

SD卡有两种模式:SD模式(也称为SDIO模式)和SPI模式,这两种模式的引脚定义是不同的。

SD模式下,通常可以使用四根数据线进行传输(4-bits Data),传输速度非常快。四位数据传输要使用引脚1、7、8和9(DAT0~DAT3);在某些不支持四线数据的场合,也可以使用单根线进行数据传输(1-bit Data),此时使用引脚7(DAT0)。

SPI通信需要四根线:两条数据线(SPI_MISO、SPI_MOSI),一条时钟线(SPI_SCK)和一条片选(Chip Select)信号线。在SPI模式下,SD卡的8号、9号针脚没有用到。

普通SD卡和微型SD卡(Micro SD card,TF card),打卡正反面:

小卡TF卡的正反面

0
回复
k6666
LV.9
3
2021-04-23 14:04
@k6666
SD卡有两种模式:SD模式(也称为SDIO模式)和SPI模式,这两种模式的引脚定义是不同的。SD模式下,通常可以使用四根数据线进行传输(4-bitsData),传输速度非常快。四位数据传输要使用引脚1、7、8和9(DAT0~DAT3);在某些不支持四线数据的场合,也可以使用单根线进行数据传输(1-bitData),此时使用引脚7(DAT0)。SPI通信需要四根线:两条数据线(SPI_MISO、SPI_MOSI),一条时钟线(SPI_SCK)和一条片选(ChipSelect)信号线。在SPI模式下,SD卡的8号、9号针脚没有用到。普通SD卡和微型SD卡(MicroSDcard,TFcard),打卡正反面:[图片][图片]小卡TF卡的正反面[图片][图片]

SD卡三种模式的针脚定义

0
回复
k6666
LV.9
4
2021-04-23 14:10
@k6666
SD卡三种模式的针脚定义[图片]

两种SD卡类型的接线连接设计方式示意

0
回复
k6666
LV.9
5
2021-04-23 14:27
@k6666
两种SD卡类型的接线连接设计方式示意[图片][图片]

主控电路图和SD卡设计电路图

0
回复
k6666
LV.9
6
2021-04-23 14:37
@k6666
主控电路图和SD卡设计电路图[图片][图片]

STM32F103单片机配置SD卡的相关函数

0
回复
k6666
LV.9
7
2021-04-25 12:23
@k6666
主控电路图和SD卡设计电路图[图片][图片]

.SDIO完全兼容多媒体卡系统规范版本4.2,卡支持三种不同数据总线模式:1位(默认)、4位和8位。

兼容先前版本的多媒体卡,兼容SDI/O卡规范版本2.0:卡支持两种不同数据总线模式:1位(默认)和4位。

支持CE-ATA功能(完全符合CE-ATA数字协议版本1.1)。对于8位模式,数据传输高达48MHz。数据和命令输出使能信号,控制外部双向驱动程序。

0
回复
k6666
LV.9
8
2021-04-25 12:27
@k6666
STM32F103单片机配置SD卡的相关函数[图片][图片][图片][图片]

STM32F103采集的数据通道DMA向SD卡存储数据,外设要想通过DMA 来传输数据,必须先给DMA 控制器发送DMA 请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA  控制器收到应答信号之后,就会启动DMA 的传输,直到传输完毕。

0
回复
svs101
LV.8
9
2021-04-27 14:08

SD卡的存储需要稳定,且数据量大的时候速度要提升。

0
回复
svs101
LV.8
10
2021-04-27 14:09
@k6666
两种SD卡类型的接线连接设计方式示意[图片][图片]

常用micro sd卡,小容量还大

0
回复
svs101
LV.8
11
2021-04-27 14:09
@k6666
STM32F103单片机配置SD卡的相关函数[图片][图片][图片][图片]

楼主这个程序设计数据存储满了怎么办?

0
回复
k6666
LV.9
12
2021-04-28 14:04
@svs101
SD卡的存储需要稳定,且数据量大的时候速度要提升。

采用DMA方式传输数据,速度快,效率高,不怎么占用CPU资源。

0
回复
k6666
LV.9
13
2021-04-28 14:05
@k6666
STM32F103采集的数据通道DMA向SD卡存储数据,外设要想通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA 控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。

采用DMA方式传输数据,速度快,效率高,不怎么占用CPU资源。

0
回复
k6666
LV.9
14
2021-04-28 14:05
@k6666
STM32F103采集的数据通道DMA向SD卡存储数据,外设要想通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA 控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。

采用DMA方式传输数据,速度快,效率高,不怎么占用CPU资源。

0
回复
k6666
LV.9
15
2021-04-28 14:06
@svs101
SD卡的存储需要稳定,且数据量大的时候速度要提升。

采用DMA方式传输数据,速度快,效率高,不怎么占用CPU资源。

0
回复
k6666
LV.9
16
2021-04-28 14:06
@svs101
SD卡的存储需要稳定,且数据量大的时候速度要提升。

采用DMA方式传输数据,速度快,效率高,不怎么占用CPU资源。

0
回复
k6666
LV.9
17
2021-04-28 14:08
@svs101
楼主这个程序设计数据存储满了怎么办?

存储容量不足的时候,程序会判别,进行早期数据的擦除处理的、

SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr) { SD_Error errorstatus = SD_OK; uint32_t delay = 0; __IO uint32_t maxdelay = 0; uint8_t cardstate = 0; /*!< Check if the card coomnd class supports erase command */ if (((CSD_Tab[1] >> 20) & SD_CCCC_ERASE) == 0) { errorstatus = SD_REQUEST_NOT_APPLICABLE; return(errorstatus); } maxdelay = 120000 / ((SDIO->CLKCR & 0xFF) + 2); if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED) //卡已上锁 { errorstatus = SD_LOCK_UNLOCK_FAILED; return(errorstatus); } if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) { //在 sdhc 卡中,地址参数为块地址,每块 512 字节,而 sdsc 卡地址为字节地址 //所以若是 sdhc 卡要对地址/512 进行转换 startaddr /= 512; endaddr /= 512; } /*!< According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */ if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)) { /*!< Send CMD32 SD_ERASE_GRP_START with argument as addr */ SDIO_CmdInitStructure.SDIO_Argument = startaddr; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_START; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //R1 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_START); if (errorstatus != SD_OK) { return(errorstatus); } /*!< Send CMD33 SD_ERASE_GRP_END with argument as addr */ SDIO_CmdInitStructure.SDIO_Argument = endaddr; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_END; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SD_ERASE_GRP_END); if (errorstatus != SD_OK) { return(errorstatus); } } /*!< Send CMD38 ERASE */ SDIO_CmdInitStructure.SDIO_Argument = 0; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ERASE; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_ERASE); if (errorstatus != SD_OK) { return(errorstatus); } for (delay = 0; delay < maxdelay; delay++) {} /*!< Wait till the card is in programming state */ errorstatus = IsCardProgramming(&cardstate); while ((errorstatus == SD_OK) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate))) { errorstatus = IsCardProgramming(&cardstate); } return(errorstatus); }

0
回复
k6666
LV.9
18
2021-04-28 14:09
@k6666
存储容量不足的时候,程序会判别,进行早期数据的擦除处理的、SD_ErrorSD_Erase(uint32_tstartaddr,uint32_tendaddr){SD_Errorerrorstatus=SD_OK;uint32_tdelay=0;__IOuint32_tmaxdelay=0;uint8_tcardstate=0;/*!<Checkifthecardcoomndclasssupportserasecommand*/if(((CSD_Tab[1]>>20)&SD_CCCC_ERASE)==0){errorstatus=SD_REQUEST_NOT_APPLICABLE;return(errorstatus);}maxdelay=120000/((SDIO->CLKCR&0xFF)+2);if(SDIO_GetResponse(SDIO_RESP1)&SD_CARD_LOCKED)//卡已上锁{errorstatus=SD_LOCK_UNLOCK_FAILED;return(errorstatus);}if(CardType==SDIO_HIGH_CAPACITY_SD_CARD){//在sdhc卡中,地址参数为块地址,每块512字节,而sdsc卡地址为字节地址//所以若是sdhc卡要对地址/512进行转换startaddr/=512;endaddr/=512;}/*!<Accordingtosd-cardspec1.0ERASE_GROUP_START(CMD32)anderase_group_end(CMD33)*/if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType)){/*!<SendCMD32SD_ERASE_GRP_STARTwithargumentasaddr*/SDIO_CmdInitStructure.SDIO_Argument=startaddr;SDIO_CmdInitStructure.SDIO_CmdIndex=SD_CMD_SD_ERASE_GRP_START;SDIO_CmdInitStructure.SDIO_Response=SDIO_Response_Short;//R1SDIO_CmdInitStructure.SDIO_Wait=SDIO_Wait_No;SDIO_CmdInitStructure.SDIO_CPSM=SDIO_CPSM_Enable;SDIO_SendCommand(&SDIO_CmdInitStructure);errorstatus=CmdResp1Error(SD_CMD_SD_ERASE_GRP_START);if(errorstatus!=SD_OK){return(errorstatus);}/*!<SendCMD33SD_ERASE_GRP_ENDwithargumentasaddr*/SDIO_CmdInitStructure.SDIO_Argument=endaddr;SDIO_CmdInitStructure.SDIO_CmdIndex=SD_CMD_SD_ERASE_GRP_END;SDIO_CmdInitStructure.SDIO_Response=SDIO_Response_Short;SDIO_CmdInitStructure.SDIO_Wait=SDIO_Wait_No;SDIO_CmdInitStructure.SDIO_CPSM=SDIO_CPSM_Enable;SDIO_SendCommand(&SDIO_CmdInitStructure);errorstatus=CmdResp1Error(SD_CMD_SD_ERASE_GRP_END);if(errorstatus!=SD_OK){return(errorstatus);}}/*!<SendCMD38ERASE*/SDIO_CmdInitStructure.SDIO_Argument=0;SDIO_CmdInitStructure.SDIO_CmdIndex=SD_CMD_ERASE;SDIO_CmdInitStructure.SDIO_Response=SDIO_Response_Short;SDIO_CmdInitStructure.SDIO_Wait=SDIO_Wait_No;SDIO_CmdInitStructure.SDIO_CPSM=SDIO_CPSM_Enable;SDIO_SendCommand(&SDIO_CmdInitStructure);errorstatus=CmdResp1Error(SD_CMD_ERASE);if(errorstatus!=SD_OK){return(errorstatus);}for(delay=0;delay<maxdelay;delay++){}/*!<Waittillthecardisinprogrammingstate*/errorstatus=IsCardProgramming(&cardstate);while((errorstatus==SD_OK)&&((SD_CARD_PROGRAMMING==cardstate)||(SD_CARD_RECEIVING==cardstate))){errorstatus=IsCardProgramming(&cardstate);}return(errorstatus);}

0
回复
k6666
LV.9
19
2021-04-28 14:10
@k6666
STM32F103单片机配置SD卡的相关函数[图片][图片][图片][图片]

部分电路

0
回复
k6666
LV.9
20
2021-04-30 16:50
@k6666
[图片]

5.1快乐。后续在更新

0
回复
jsj01q
LV.2
21
2021-05-07 09:50

学习中,期待楼主更新

0
回复
2021-05-07 14:54

数据的存储没有采用文件系统吗?FAT32之类的,这样对数据管理要好点

0
回复
cwm4610
LV.5
23
2021-05-12 14:55

STM32F,是出了名的低功耗,请教下功耗分别是什么样的?有几种工作模式?低功耗是否支持电池供电,在此条件下,电压跌落到多少后会主动进入sleep模式?

AD自带的分辨率是多少bit?是否有实例参考?

0
回复
lkings
LV.6
24
2021-05-13 13:18

此芯片不用外部晶振,节省空间,layout也变得容易了.确实是很优秀的一款芯片

0
回复
k6666
LV.9
25
2021-05-18 15:44
@zhangjiantao
数据的存储没有采用文件系统吗?FAT32之类的,这样对数据管理要好点

采用的就是FAT32

0
回复
k6666
LV.9
26
2021-05-18 15:46
@cwm4610
STM32F,是出了名的低功耗,请教下功耗分别是什么样的?有几种工作模式?低功耗是否支持电池供电,在此条件下,电压跌落到多少后会主动进入sleep模式?AD自带的分辨率是多少bit?是否有实例参考?

STM32 F不同型号是有差异的,自带的AD分辨率是12bit

0
回复
k6666
LV.9
27
2021-05-18 15:46
@lkings
此芯片不用外部晶振,节省空间,layout也变得容易了.确实是很优秀的一款芯片

内部RTC精度不高,稳定性也差。可以外接个32768HZ

0
回复
飞翔2004
LV.10
28
2021-05-21 12:40
@k6666
内部RTC精度不高,稳定性也差。可以外接个32768HZ

定时等需要时间准确的才需要外接个32768HZ的,跑程序系统时钟源没必要,如果用32768HZ的频率跑系统太慢了。

0
回复
飞翔2004
LV.10
29
2021-05-21 12:50
@k6666
STM32F103采集的数据通道DMA向SD卡存储数据,外设要想通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA 控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。

快速读写数据量大的文件等用DMA方式具有很大的优势,这种方式的话不同速度的硬件可以沟通,而不需要单片机大量中断。

0
回复
lkings
LV.6
30
2021-05-28 08:23

數據是以文件方式存儲還是,還是隨存隨取的字節方式

0
回复
2021-05-28 13:34
@飞翔2004
快速读写数据量大的文件等用DMA方式具有很大的优势,这种方式的话不同速度的硬件可以沟通,而不需要单片机大量中断。

读写卡比较占用时间的,尤其存储数据量大的时候,操作时间比较长

0
回复