前言 SAI我也没有完全学会,文中说了一些问题,解决了但是不知道为什么,有知道的和我说一下,谢谢。 SAI的学习总结时序bit 组成 slot,slot 组成 frame,
slot:8bit-32bit,>= data_size
frame:1-16个slot,<= 256 bit
大的容器可以大于小的容器,不足补0
SCK是bit的时钟,FS是frame的时钟
时钟下图是STM32H750/743/753参考手册上的图
这里仅考虑主机模式
先看SAI_xCR1寄存器的NOMCK位,是0,(不知道CubeMX哪里控制,知道的说一下)。
FRL(Frame length)是帧长度寄存器的值,FRL+1就是CubeMX里帧长度的值,必须是2的幂。
OSR由下图中的master clock over sampling控制(没试过),默认是enable(1),
MCKDIV由下图中的master clock divider控制, 所以,SCK_x = ((RCC_SAI / MCKDIV) / (OSR+1)) / (256/FRL+1) CubeMX注意事项
slot active:激活slot,一定要设置,把需要的slot都打开。
output drive:不知道作用,官方例程上开了
问题
开机后发送的第一帧数据有问题,应该都像60us-80us时的时序一样,可以开机后阻塞式发送1-2帧数据“0”。 [C] 纯文本查看 复制代码 HAL_SAI_Transmit_DMA()
HAL_SAI_Transmit_IT()
HAL_SAI_Transmit() 使用DMA发送的问题:hsai_BlockB的时序会比hsai_BlockA的时序晚一帧,可以开机后阻塞式发送发送1-2帧数据“0”,可以解决(不知道为什么,知道的说一下)。
如果不开启DMA和SAI中断,DMA设置为normal模式DMA只能发送一次,DMA设置为circular模式DMA可以循环发送。DMA设置为normal模式,第二次发送时 [C] 纯文本查看 复制代码 HAL_SAI_Transmit_DMA()
{...
if (hsai->State == HAL_SAI_STATE_READY)
...} 会判断为否,从而导致发送失败(不知道为什么,知道的说一下)。
中断发送没问题。
调试的时候,中断发送和DMA发送函数完成后不能立即暂停或者打断点,需要延时1-2ms,否则DMA发送AB的时序错位,中断发送只发送前边的一部分。 自定义协议
协议设定:协议中的1位有2个阶段,相当于2个状态,
引脚A输出0b10,同时引脚B输出0b00,数据“1”,协议中的1位;
引脚A输出0b00,同时引脚B输出0b10,数据“0”,协议中的1位;
引脚A输出0b00,同时引脚B输出0b00,数据空,协议中的1位。
协议速率:100KHz, SAI设置1位429 = 2stage = 8bit
1slot = 1位 = 2stage = 8bit
1frame = 4slot = 32bit
所以,下图时CubeMX SAI A的设置,SAI B和这个一样,同步的。
Data Size: 8bit
slot size: Data Size
frame length: 32bit
number of slot: 4
slot active: all // 激活全部4个slot
audio frequency:user set // 时钟频率自己设置,
// 协议的频率时100khz,1位=8bit,那引脚频率就是800khz,RCC_SAI设置为64MHz,64000k/MCKDIV/2/(256/32)=800k,MCKDIV=5
Master Clock Divider:5
Master Clock No Divider:disabled 发送数据1位 = 1字节
BlockA 发送 0xF0
BlockB 发送 0x00 // 就是1 BlockA 发送 0x00
BlockB 发送 0xF0 // 就是0
|