一般同步ADC都是使用的FPGA,但是单片机也可以采集!虽然I2S和SAI都是传音频数据的,但其实可以传普通数据,本质都是二进制数据流嘛!(全网都没有相关的文章)
就是一个中断来了,然后通过SD线进来,DMA外设从SD搬到了内存,就是这么简单。
可以串行的从这里进去,4个SD口,4个ADC,数据太多还可以通过FIFO来缓冲,然后把FIFO的数据传到DMA里面。
我给了三个demo段:
采集使用的ADC是AD777x,他们不是单纯的SPI输出,而是并行的输出接口,在官方给出的代码里面有着不同数据输出的方式:
这里使用了SAI的外设,就使用这个模式
串行的输出
一帧数据
三个宏
三个宏,用于配置AD7779模数转换器(ADC)的寄存器。这些宏可以用来设置数据的输出格式、数据头格式和时钟分频系数。
AD7779_DOUT_FORMAT(x)
(x) & 0x3
: 取出输入值x的低两位。((x) & 0x3) << 6
: 将提取的两位左移6位,放到寄存器中的指定位置。AD7779_DOUT_HEADER_FORMAT
(1 << 5)
: 将值的第5位设置为1,其他位为0。这么多数据要加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
。启动DMA传输:
datas[0]
这个缓冲区中。同样,这行代码启动了SAI Block A1的DMA接收,并将数据存储到datas[1]
缓冲区中。
等待DMA传输完成:
检查条件: 确保ADC和DMA复用功能开启。
启动DMA: 同时启动两个SAI通道的DMA接收。
等待完成: 等待两个DMA传输都完成。
在ADC的数据传输的时候是有个信号的
条件判断:
数据读取循环:
datasBuffer[0]
中。数据打印:
print7_binary
函数:用于打印一个字节的二进制表示。print7_symbol(';')
: 用于打印分隔符';'。print7_line()
: 用于打印换行符。条件判断:
FREESMARTEEG_ADC
和 FREESMARTEEG_ADC_SAI_READ_INT
。只有当这两个宏定义都为真时,才会执行后续的代码。这意味着,只有当ADC功能和SAI读取中断功能都开启时,才会进行数据采集。启动数据采集:
HAL_SAI_Receive_DMA
: 启动四个SAI通道的DMA接收,并将数据分别存储到datas[0]
、datas[1]
、datas[2]
、datas[3]
这四个缓冲区中。SAI_RxCplt
标志位,表示数据采集周期结束。SAI_RxCplt
标志位。if (SAI_RxStart)
: 这行代码检查了一个标志位SAI_RxStart
,用于判断是否需要开始新的数据采集周期。SAI_DMA_INT_SHIFT
: 这个标志位表示是否启用了DMA中断。等待DMA传输完成:
HAL_SAI_GetState
函数来等待每个DMA传输完成。SAI_RxCplt
标志位,表示数据采集周期结束。
第一个的连接是这样的,全连接
第二个也是
然后时钟线就两个,外设4个,然后可以把时钟给到别人
音频子模块既可作为接收器,又可作为发送器;既可与另一模块同步,又可以不同步。SAI 可与其它 SAI 相连接来同步运行。
音频数据的量化位数可能不同,控制器支持16bit、24bit和32bit三种数据长度, 因为数据寄存器是16bit的,所以对于24bit和32bit数据长度需要发送两个。为此,可以产生四种数据和帧格式组合:
当使用32位数据包中的16位数据时,前16位(MSB)为有效位,16位LSB被强制清零,无需任何软件操作或DMA请求(只需一个读/写操作)。如果程序使用DMA传输(一般都会用),则24位和32位数据帧需要对数据寄存器执行两次DMA操作。24位的数据帧,硬件会将8位非有效位扩展到带有0位的32位。对于所有数据格式和通信标准而言,始终会先发送最高有效位(MSB优先)。
另外的外设,就没有时钟线了
是使用的第一个的时钟线
同理
这个是时钟树上面的位置
这个就是IO的输入的口