【实验室乱记】基于stm32的采集Adc与SD卡储存

懵懂的女人 提交于 2020-07-27 08:35:04

这篇文章向大家介绍下基于STM32F4的adc采集与SD卡储存

实验室

学长的要求是利用STM32采集Adc值转存于SD中 后利用Matlab进行快速傅里叶变化分析频率(FFT天下第一 )

简介

ST(意法半导体)推出了以基于ARM® Cortex™-M4为内核的STM32F4系列高性能微控制器,其采用了90 纳米的NVM 工艺和ART(据说以后可以操作学长的28nm工具FPGA )。
/这里用的是某点原子

调用的资源:Adc

模拟数字转换器即A/D转换器,简称ADC,通常是指一个将模拟信号转变为数字信号的电子元件。

调用的外设:SD卡

SD卡相对于u盘、flash来说是比较适合于单片机系统的大容量存储设备,容量选择尺度大(几十M 到几十G) 、更换简单、移动方便,是单片机大容量外部存储器的首选。

实现过程

Adc

ADC 的通道与引脚的对应关系在 STM32F4 的数据手册可以查到,这里使用 ADC1 的通道 5
首先初始化IO 设置为模拟输入

__HAL_RCC_ADC1_CLK_ENABLE(); //使能 ADC1 时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启 GPIOA 时钟
GPIO_Initure.Pin=GPIO_PIN_5;            //PA5
GPIO_Initure.Mode=GPIO_MODE_ANALOG;     //模拟
GPIO_Initure.Pull=GPIO_NOPULL;          //不带上下拉
HAL_GPIO_Init(GPIOA,&GPIO_Initure);		//

初始化ADC 设置ADC分频系数、分辨率、模式、扫描方式、对齐方式等信息
在 HAL 库中,初始化 ADC 是通过函数 HAL_ADC_Init 来实现的,该函数声明为:

HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc);

入口参数hadc 为 ADC_HandleTypeDef 结构体指针类型,结构体定义为:

//结构体 ADC_HandleTypeDef 
typedef struct
{
 ADC_TypeDef *Instance; 		//ADC1/ ADC2/ ADC3
 ADC_InitTypeDef Init; 			//初始化结构体变量
 __IO uint32_t NbrOfCurrentConversionRank; //当前转换序列
 DMA_HandleTypeDef *DMA_Handle; //DMA 方式使用
 HAL_LockTypeDef Lock;
 __IO HAL_ADC_StateTypeDef State;
 __IO uint32_t ErrorCode;
}ADC_HandleTypeDef;
//结构体 ADC_InitTypeDef 
typedef struct
{
 uint32_t ClockPrescaler;		//分频系数 2/4/6/8 分频 ADC_CLOCK_SYNC_PCLK_DIV4
 uint32_t Resolution; 			//分辨率 12/10/8/6 位:ADC_RESOLUTION_12B
 uint32_t DataAlign; 			//对齐方式:左对齐还是右对齐:ADC_DATAALIGN_RIGHT
 uint32_t ScanConvMode; 		//扫描模式 DISABLE
 uint32_t EOCSelection; 		//EOC 标志是否设置 DISABLE
 uint32_t ContinuousConvMode;	//开启连续转换模式或者单次转换模式 DISABLE
 uint32_t DMAContinuousRequests;//开启 DMA 请求连续模式或者单独模式 DISABLE
 uint32_t NbrOfConversion; 		//规则序列中有多少个转换 1
 uint32_t DiscontinuousConvMode;//不连续采样模式 DISABLE
 uint32_t NbrOfDiscConversion;	//不连续采样通道数 0
 uint32_t ExternalTrigConv; 	//外部触发方式 ADC_SOFTWARE_START
 uint32_t ExternalTrigConvEdge;	//外部触发边沿
}ADC_InitTypeDef;

在设置完了以上信息后,就可以开启 AD 转换器了(通过 ADC_CR2 寄存器控制)

HAL_ADC_Start(&ADC1_Handler); 	//开启 ADC

配置通道,读取通道ADC值
在完成上面的步骤后,ADC已经准备好。接下来设置规则序列 1 的通道,然后启动 ADC 转换。在转换结束后,读取转换结果值。
设置规则序列通道以及采样周期的函数是:

HAL_StatusTypeDef HAL_ADC_ConfigChannel(
	ADC_HandleTypeDef* hadc,
	ADC_ChannelConfTypeDef* sConfig);

第一个参数就不用多说了,第二个入口参数 sConfig,它
是 ADC_ChannelConfTypeDef 结构体指针类型,结构体定义如下:

typedef struct {
uint32_t Channel; 		//ADC 通道
uint32_t Rank;			//规则通道中的第几个转换
uint32_t SamplingTime; 	//采样时间
uint32_t Offset;		//备用,暂未用到
}ADC_ChannelConfTypeDef;
//实例
ADC1_ChanConf.Channel= ADC_CHANNEL_5;	//通道 5 
ADC1_ChanConf.Rank=1; 					//第 1 个序列,序列 1 
ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
ADC1_ChanConf.Offset=0; 
HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置

配置好通道并且使能 ADC 后,接下来就是读取 ADC 值。采取的是查询方式读取(最近期末时间紧迫 下次尝试DMA ), 所以还要等待上一次转换结束。此过程 HAL 库提供了专用函数 HAL_ADC_PollForConversion,函数定义为:

 HAL_StatusTypeDef HAL_ADC_PollForConversion(
 	ADC_HandleTypeDef* hadc, 
 	uint32_t Timeout);

等待上一次转换结束之后,接下来就是读取 ADC 值,函数为:

uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);

SD卡

通过今天的学习主要了解SD卡与文件系统FATFS的使用,具体实现原理可参考以下博客讲解
https://blog.csdn.net/vca821/article/details/80738151?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1
https://blog.csdn.net/nulidehahafr/article/details/84146148
hal 库 SD 卡支持源文件 stm32f4xx_hal_sd.cstm32f4xx_II_sdmmc.h以及对应头文件stm32f4xx_hal_sd.hstm32f4xx_II_sdmmc.h
而要想真正应用SD卡就必须使用文件系统管理,使用 FATFS 来管理 SD 卡实现 SD 卡文件的读写等。



FatFs 是一个通用的文件系统(FAT/exFAT)模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 组件的编写遵循ANSI C(C89),完全分离于磁盘 I/O 层,因此不依赖于硬件平台。它可以嵌入到资源有限的微控制器中,如 8051, PIC, AVR, ARM, Z80, RX等等,不需要做任何修改。

FATFS 是一个完全免费开源的 FAT 文件系统模块它完全用标准 C 语言编写,所以具有良好的硬件平台独立性。
FATFS 的源码可在http://elm-chan.org/fsw/ff/00index_e.html下载。
应用层的函数f_open f_read f_write f_close 等,可以像在PC 上读/写文件那样简单。(具体函数应用参考主函数代码)

主函数代码

核心代码如下

f_opendir((u8 *)"0:/");                //打开目录
delay_ms(5);                           //延迟5ms(开心就好
f_open((u8 *)"xdpnb.txt",2);           //打开目录下文件(模式2 r+)																										(Xdp牛逼
for(t = 0; t < 2048; t++){              //采样2048次
	adcx=Get_Adc_Average(ADC_CHANNEL_5,1);//获取Adc通道5的转换值 1次取平均
	rui[t] = adcx;                      //存于Rui数组    
}
        
for(t = 0; t < 2048; t++){              //为了保证采样质量 区分采集与转存过程
	myitoa(rui[t],tem,10);              //调用自定义数字转字符函数 存于临时数组
	f_write((u8 *)tem,0X4);            //向SD卡写入数组 长度4
	f_write((u8 *)"\r\n",0X2);         //换行符(用于Matlab解析
}
f_close();                             //关闭文件!

(Ps:打开文件后一定要close close close)
模拟采集的adc数值为实验室信号源所产生的正弦波
具体实验现象与原理移步学长博客
TerayTech
离线式数字信号处理(一)—— 使用Matlab读取TXT文件并做FFT分析
离线式数字信号处理(二)——使用Matlab对STM32F4 ADC采集到的数据进行分析
(即将接手学长的28nm)Xilinx ZYNQ学习笔记(一)——使用PS读写SD卡





易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!