一般同步ADC都是使用的FPGA,但是单片机也可以采集!虽然I2S和SAI都是传音频数据的,但其实可以传普通数据,本质都是二进制数据流嘛!(全网都没有相关的文章)
就是一个中断来了,然后通过SD线进来,DMA外设从SD搬到了内存,就是这么简单。
可以串行的从这里进去,4个SD口,4个ADC,数据太多还可以通过FIFO来缓冲,然后把FIFO的数据传到DMA里面。
我给了三个demo段:
实现了一个双通道SAI(串行音频接口)的DMA数据采集功能。也就是说,它会同时从两个SAI通道(Block B2和Block A1)采集数据,并将采集到的数据分别存储到两个不同的缓冲区中。
当ADC的引脚就绪,启动SAI模块读取数据,并通过UART7以二进制形式输出。
实现了一个多通道SAI(串行音频接口)的DMA数据采集功能,并且使用了中断来处理DMA完成事件。它可以同时从四个SAI通道(Block B2, Block A1, Block B1, Block A2)采集数据,并将采集到的数据分别存储到不同的缓冲区中。
多通道同时采集: 通过同时启动四个SAI通道的DMA传输,实现了多通道的数据同时采集。
DMA高效传输: 使用DMA方式进行数据传输,可以减轻CPU的负担,提高数据传输效率。
中断处理: 通过DMA中断,可以在DMA传输完成后立即进行后续处理,提高系统响应速度。
灵活配置: 可以根据需要选择是否启用DMA中断。
缓冲区存储: 将采集到的数据分别存储到不同的缓冲区中,方便后续的处理。
采集使用的ADC是AD777x,他们不是单纯的SPI输出,而是并行的输出接口,在官方给出的代码里面有着不同数据输出的方式:
这里使用了SAI的外设,就使用这个模式
串行的输出
一帧数据
三个宏
三个宏,用于配置AD7779模数转换器(ADC)的寄存器。这些宏可以用来设置数据的输出格式、数据头格式和时钟分频系数。
AD7779_DOUT_FORMAT(x)
(x) & 0x3
: 取出输入值x的低两位。((x) & 0x3) << 6
: 将提取的两位左移6位,放到寄存器中的指定位置。最终的结果用来配置AD7779寄存器中的数据输出格式。
作用: 定义数据输出格式,决定每个采样点的位数。
AD7779_DOUT_HEADER_FORMAT
(1 << 5)
: 将值的第5位设置为1,其他位为0。这个值用来在AD7779寄存器中启用数据头格式。
作用: 定义数据头格式,包括同步和帧同步等信息。
这么多数据要加CRC的,也就是要加个头
AD7779、AD7771都是这样的为了快速的移动数据使用了大量的DMA外设
SAI外设使用中断来启动
SD数据线
模式是非同步的从设备,就是等着数据来
这个就是一些设置,数据深度开到了最大
两个FIFO全开
FIFO在APB的下面
这个是中断的地址
这个函数就是就是接收DMA的数据
使用这样的结构直接获取来自SAI外设上面的数据
实现了一个双通道SAI(串行音频接口)的DMA数据采集功能。也就是说,它会同时从两个SAI通道(Block B2和Block A1)采集数据,并将采集到的数据分别存储到两个不同的缓冲区中。
条件判断:
if (FREESMARTEEG_ADC & FREESMARTEEG_ADC_SAI_READ_DMAMUX)
: 这一行代码首先检查了两个宏定义:FREESMARTEEG_ADC
和FREESMARTEEG_ADC_SAI_READ_DMAMUX
。只有当这两个宏定义都为真时,才会执行后续的代码。这意味着,只有当ADC功能和SAI读取DMA复用功能都开启时,才会进行数据采集。
启动DMA传输:
这行代码启动了SAI Block B2的DMA接收。它会将从SAI Block B2接收到的32位数据存储到
datas[0]
这个缓冲区中。HAL_SAI_Receive_DMA(&hsai_BlockB2, datas[0], SAI_DATASIZE_32):
同样,这行代码启动了SAI Block A1的DMA接收,并将数据存储到datas[1]
缓冲区中。
HAL_SAI_Receive_DMA(&hsai_BlockA1, datas[1], SAI_DATASIZE_32)
等待DMA传输完成:
这行代码会一直等待,直到SAI Block B2的DMA传输完成。
while (HAL_SAI_GetState(&hsai_BlockB2) != HAL_SAI_STATE_READY)
这行代码会一直等待,直到SAI Block A1的DMA传输完成。
while (HAL_SAI_GetState(&hsai_BlockA1) != HAL_SAI_STATE_READY)
检查条件: 确保ADC和DMA复用功能开启。
启动DMA: 同时启动两个SAI通道的DMA接收。
等待完成: 等待两个DMA传输都完成。
双通道同时采集: 通过同时启动两个SAI通道的DMA传输,实现了双通道的数据同时采集。
缓冲区存储: 将采集到的数据分别存储到不同的缓冲区中,方便后续的处理。
等待机制: 通过循环等待DMA传输完成,确保数据采集的完整性。
在ADC的数据传输的时候是有个信号的
条件判断:
检查是否开启了ADC和SAI读取功能。
FREESMARTEEG_ADC & FREESMARTEEG_ADC_SAI_READ
数据读取循环:
循环等待DMA传输完成。
HAL_SAI_GetState(&hsai_BlockB1) != HAL_SAI_STATE_READY:
启动DMA方式接收32位的数据,并将数据存储到
datasBuffer[0]
中。HAL_SAI_Receive_DMA(&hsai_BlockB1, datasBuffer[0], SAI_DATASIZE_32):
读取DRDY引脚的状态。
HAL_GPIO_ReadPin(AD_DRDY_GPIO_Port, AD_DRDY_Pin):
循环等待DRDY引脚变为高电平,表示数据准备就绪。
等待数据就绪:
启动SAI接收:
等待DMA传输完成:
数据打印:
遍历接收到的数据,逐字节打印成二进制形式。
print7_binary
函数:用于打印一个字节的二进制表示。print7_symbol(';')
: 用于打印分隔符';'。print7_line()
: 用于打印换行符。
检查是否开启了UART7文本输出。
FREESMARTEEG_OUT & FREESMARTEEG_SAI_TEXT_UART7:
检查输出模式:
循环打印数据:
SAI (Serial Audio Interface): 一种高速串行音频接口,用于音频数据的传输。
DMA (Direct Memory Access): 一种数据传输方式,可以高效地直接将数据从外设传输到内存,减轻CPU的负担。
DRDY (Data Ready): 数据就绪信号,表示新的数据已经准备好可以读取。
二进制输出: 将数据以二进制的形式打印出来。
条件判断:
这一行代码首先检查了两个宏定义:
FREESMARTEEG_ADC
和FREESMARTEEG_ADC_SAI_READ_INT
。只有当这两个宏定义都为真时,才会执行后续的代码。这意味着,只有当ADC功能和SAI读取中断功能都开启时,才会进行数据采集。if (FREESMARTEEG_ADC & FREESMARTEEG_ADC_SAI_READ_INT):
启动数据采集:
如果启用了DMA中断:
如果没有启用DMA中断:
HAL_SAI_Receive_DMA
: 启动四个SAI通道的DMA接收,并将数据分别存储到datas[0]
、datas[1]
、datas[2]
、datas[3]
这四个缓冲区中。程序会等待每个DMA传输完成,然后设置
SAI_RxCplt
标志位,表示数据采集周期结束。
程序直接等待每个DMA传输完成,然后设置
SAI_RxCplt
标志位。
if (SAI_RxStart)
: 这行代码检查了一个标志位SAI_RxStart
,用于判断是否需要开始新的数据采集周期。SAI_DMA_INT_SHIFT
: 这个标志位表示是否启用了DMA中断。
等待DMA传输完成:
无论是否启用了DMA中断,程序都会通过
HAL_SAI_GetState
函数来等待每个DMA传输完成。
检查条件: 确保ADC和SAI读取中断功能开启,并且需要开始新的数据采集周期。
启动DMA: 启动四个SAI通道的DMA接收。
等待完成: 等待所有DMA传输完成。
设置标志位: 设置
SAI_RxCplt
标志位,表示数据采集周期结束。
第一个的连接是这样的,全连接
第二个也是
然后时钟线就两个,外设4个,然后可以把时钟给到别人
音频子模块既可作为接收器,又可作为发送器;既可与另一模块同步,又可以不同步。SAI 可与其它 SAI 相连接来同步运行。
将16位数据封装在16位帧中 将16位数据封装在32位帧中 将24位数据封装在32位帧中 将32位数据封装在32位帧中
另外的外设,就没有时钟线了
是使用的第一个的时钟线
同理
这个是时钟树上面的位置
这个就是IO的输入的口