1.简述
STM32h743与adc芯片进行SPI通信,采集到的24位数据通过DMA搬运到指定的8位数组内存区,将24位数据转换成电压值后,通过两个FIFO将数据搬运到存放电压值的内存区。
2.STM32CUBMX配置
2.1 SPI配置如下
2.2 DMA配置
采用线0作为DMA触发同步信号,当线0来一个上升沿则触发一次DMA,并且一次搬运3个字节的数据,同时线0作为ADC芯片的触发信号,一个上升沿触发一次转换,SPI得到3个字节的数据.
3.DMA中断函数
3.1 发送接收半中断函数
注:SPI配置为全双工通信时,半发送和半完成是同时完成,并且半发送和半接收中断函数为同一个,则半发送和半接收都会进入半中断。
3.1.1中断函数的寻找
CUBMX配置完成后生成代码,在 it.c 文件里找到下图函数
跳入接收中断函数,找到XferHalfCpltCallback并跳入
可以看到这是DMA句柄面向对象思想的方法
但半中断函数在启动SPI_DMA传输的函数HAL_SPI_TransmitReceive_DMA中
对象DMA句柄中的半中断和全中断方法被此函数赋值,并且若定义中断函数在此函数里
3.2 中断函数的编写(使用FIFO)
半中断函数中把前一半数据存入FIFOA
全中断函数中把后一半数据存入FIFOB
/**********************************************************************************************************
* function : HAL_SPI_TxRxHalfCpltCallback
* brief : SPI发送接收 半 完成回调函数
* parm : hspi
* return : 无
**********************************************************************************************************/
void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI1)
{
fifoa_in(&spi_dma_Rx_buffer[0], Rx_Size/2);
flag_A_full = 1;//可以读取 FIFO A
}
}
/**********************************************************************************************************
* function : HAL_SPI_TxRxCpltCallback
* brief : SPI发送接收完成回调函数
* parm : hspi
* return : 无
**********************************************************************************************************/
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (hspi->Instance == SPI1)
{
fifob_in(&spi_dma_Rx_buffer[Rx_Size/2], Rx_Size/2);
flag_B_full = 1;//可以读取 FIFO B
}
}
4.FIFO的实现
FIFO的实现可参考此博客:用C语言实现FIFO (简单版_c fifo-CSDN博客
4.1 while循环
while中实现读取FIFO中的数据并把其转换成电压值
判断FIFOA是否存满,若存满,则关闭全局中断,把FIFOA的数据取出数组spi_dma_Outx_FIFO_u8_A里,将其转换为电压值再开启中断,FIFOB依次推理。
while (1)
{
//ads127l11 FIFO测试
if(flag_A_full == 1){
DISABLE_INT(); //禁止中断
fifoa_out(spi_dma_Outx_FIFO_u8_A,Rx_Size/2);
flag_A_full = 0;
for (int i = 0; i < Rx_Size/3/2; i++) {
ads127l11_32bit_data = signExtend(&spi_dma_Outx_FIFO_u8_A[i*3]);
ads127l11_Voltage[i] = (float) (ads127l11_32bit_data * 4096) / 8388608;//计算电压值,变成mv方便观察
}
ENABLE_INT(); //开启中断
}
if(flag_B_full == 1){
DISABLE_INT();
fifob_out(spi_dma_Outx_FIFO_u8_B,Rx_Size/2);
flag_B_full = 0;
for (int i = 0; i < Rx_Size/3/2; i++) {
ads127l11_32bit_data = signExtend(&spi_dma_Outx_FIFO_u8_B[i*3]);
ads127l11_Voltage[i+96] = (float) (ads127l11_32bit_data * 4096) / 8388608;//计算电压值,变成mv方便观察
}
ENABLE_INT();
bsp_LedToggle();
}