ADXL345 三轴加速度数据SPI读取、多字节读取、DMA SPI读取和FIFO数据读取
ADXL345 三轴加速度数据SPI读取、多字节读取、DMA SPI读取和FIFO数据读取
1、简介及注意事项
ADXL345传感器分辨率13位,测量范围±16g(可选±2、±4、±8g),输出数据格式为16位补码,可通过SPI(三线或者四线)或者IIC接口读取。同时还支持32级的FIFO数据存储,满足快速读取数据的要求。
- 关于初始化
一般初始化0x31,0x2D,0x2C,0x2F,0x38,0x2E,0x1E,0x1F,0x20这些寄存器即可。关于这些寄存器的说明,具体可以参考手册。
需要注意的一点是:如果要使用中断进行数据读取,那么初始化之前对中断寄存器清零,所有其他功能初始化完之后,再设置中断使能。
SpiWriteCmd(0x2E,0x00); // 中断寄存器清零SpiWriteCmd(0x31,0x0B); // 4线SPI 全分辨率 g加速度范围SpiWriteCmd(0x2D,0x08); // 传感器测量模式SpiWriteCmd(0x2C,0x0E); // 传感器传输数据速率1600HZSpiWriteCmd(0x2F,0x03); // 中断映射SpiWriteCmd(0x38,0x94); // FIFO模式设置SpiWriteCmd(0x1E,0x00); // X轴偏移量SpiWriteCmd(0x1F,0x00); // Y轴偏移量SpiWriteCmd(0x20,0x00); // Z轴偏移量SpiWriteCmd(0x2E,0x83); //中断寄存器使能
- SPI时钟要求
在设置读取速率的时候,要和SPI的时钟匹配起来,否则可能读到错误的数据,比如设置1600HZ,SPI时钟要大于2MHZ。SPI读取数据时钟最大5MHZ。 - SPI总线的理解
SPI要读取一个数据,必须先写入一个数据。在写入数据的时候,时钟线才会启动。 - 读写以及多字节读取指令的区别
从上面可以看出,
读的时候,地址的最高位为1;
写的时候,地址的最高位为0;
在进行多字节读取的时候,次高位为1,这样才可以多字节写和读;
2、SPI数据读取
话不多说,直接上代码,本文采用STMF407读取数据,SPI数据位8位,全双工,软件控制片选,高位在前(MB First),
SPI.h#define ADS_SPI_PORT GPIOB
#define ADS_SPI_CS_PIN GPIO_Pin_12
#define ADS_SPI_SCK_PIN GPIO_Pin_13
#define ADS_SPI_MISO_PIN GPIO_Pin_14
#define ADS_SPI_MOSI_PIN GPIO_Pin_15#define ADS_SPI_CS_HIGH() GPIO_SetBits(ADS_SPI_PORT, ADS_SPI_CS_PIN)
#define ADS_SPI_CS_LOW() GPIO_ResetBits(ADS_SPI_PORT, ADS_SPI_CS_PIN)SPI.c
unsigned char ADXL345RXBuff[250]; //DMA 接收缓存
unsigned char ADXL345TXBuff[10]; //DMA 发送缓存// SPI IO口初始化
void Spi2IOInit(void)
{GPIO_InitTypeDef GPIO_InitStructure;// Enable GPIOC clocks RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);// Connect SPI2 pins to AF5GPIO_PinAFConfig(ADS_SPI_PORT, GPIO_PinSource13, GPIO_AF_SPI2); // SCKGPIO_PinAFConfig(ADS_SPI_PORT, GPIO_PinSource14, GPIO_AF_SPI2); // MISOGPIO_PinAFConfig(ADS_SPI_PORT, GPIO_PinSource15, GPIO_AF_SPI2); // MOSI// SPI SCK¡¢MOSI pin configurationGPIO_InitStructure.GPIO_Pin = ADS_SPI_SCK_PIN|ADS_SPI_MOSI_PIN|ADS_SPI_MISO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//GPIO_PuPd_DOWN;//GPIO_PuPd_UP;//GPIO_PuPd_NOPULL;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(ADS_SPI_PORT, &GPIO_InitStructure);//SPI2 NSS pin in output pushpull mode GPIO_InitStructure.GPIO_Pin = ADS_SPI_CS_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //GPIO_PuPd_NOPULL;GPIO_Init(ADS_SPI_PORT, &GPIO_InitStructure);ADS_SPI_CS_HIGH(); // cs default state is highADS_SPI_CS_LOW(); ADS_SPI_CS_HIGH();
}// SPI模式初始化
void SPI2Init(void)
{SPI_InitTypeDef SPI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;SPI_I2S_DeInit(SPI2);//Enable the SPI periph RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);Spi2IOInit();// SPI configurationSPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI2, &SPI_InitStructure);// Enable the SPI2SPI_Cmd(SPI2, ENABLE);
}
// SPI写指令
void SpiWriteCmd(u8 cmd,u8 data)
{ADS_SPI_CS_LOW(); while((SPI2->SR &0x0002)==0); SPI2->DR = (cmd);while((SPI2->SR &0x0001)==0);SPI_I2S_ReceiveData(SPI2); while((SPI2->SR &0x0002)==0); SPI2->DR = (data);while((SPI2->SR &0x0001)==0);SPI_I2S_ReceiveData(SPI2); ADS_SPI_CS_HIGH();
}
// SPI读指令
u8 SpiReadCmd(u8 cmd)
{ADS_SPI_CS_LOW(); unsigned char returnvalue;while((SPI2->SR &0x0002)==0); SPI2->DR = (cmd|0x80);while((SPI2->SR &0x0001)==0);returnvalue = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI buswhile((SPI2->SR &0x0002)==0); SPI2->DR = (0x00);while((SPI2->SR &0x0001)==0);returnvalue =(unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI busADS_SPI_CS_HIGH();return(returnvalue);
}void ADXL345Init()
{u8 TempData;SPI2Init();TempData = SpiReadCmd(0x00);while(TempData!=0xE5) //判断是否器件ID正确 验证SPI通信是否正常{SendData(&TempData,1);}SpiWriteCmd(0x2E,0x00); SpiWriteCmd(0x31,0x0B);SpiWriteCmd(0x2D,0x08);SpiWriteCmd(0x2C,0x0E);SpiWriteCmd(0x2E,0x00);SpiWriteCmd(0x38,0x00);SpiWriteCmd(0x2F,0x00);SpiWriteCmd(0x1E,0x00);SpiWriteCmd(0x1F,0x00);SpiWriteCmd(0x20,0x00);
}void ReadADXL345Data()
{unsigned char StrBuff[50];short int Acc_X=0,Acc_Y=0,Acc_Z=0;unsigned char Buf[6];Buf[0]=SpiReadCmd(0x32);Buf[1]=SpiReadCmd(0x33);Buf[2]=SpiReadCmd(0x34);Buf[3]=SpiReadCmd(0x35);Buf[4]=SpiReadCmd(0x36);Buf[5]=SpiReadCmd(0x37);Acc_X = ((Buf[1]<<8|Buf[0]));Acc_Y = ((Buf[3]<<8|Buf[2]));Acc_Z = ((Buf[5]<<8|Buf[4]));sprintf(StrBuff,"X=%4.3f m/s2 Y=%4.3f m/s2 Z=%4.3f m/s2 \r\n",Acc_X*3.9/1000*9.8,Acc_Y*3.9/1000*9.8,Acc_Z*3.9/1000*9.8);SendData(StrBuff,strlen(StrBuff));
读取加速度传感器结果,本文中将g转换成m/s2结果显示。
3、多字节读取
多字节读取的方式和常规不同的就是:
无需自己手动修改读取数据的地址,
外部传感器自动修改地址并传输,
多字节读取时序图如下:
从上面可以看出,在发送0xF2之后,无论发送什么数据,都自动传回六个数据。
有的好奇宝宝可能会问,为什么是0xF2呢?
因为读指令最高位为1,次高位为多字节位,要置1,而寄存器的数据地址为0x32,这样或则可以得到0xF2。
void ContinuousReadADXL345Data()
{unsigned char StrBuff[50];short int Acc_X=0,Acc_Y=0,Acc_Z=0;unsigned char Buf[6];ADS_SPI_CS_LOW(); unsigned char returnvalue;while((SPI2->SR &0x0002)==0); SPI2->DR = 0x32|0xC0;while((SPI2->SR &0x0001)==0);Buf[0] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI buswhile((SPI2->SR &0x0002)==0); SPI2->DR = 0x00;while((SPI2->SR &0x0001)==0);Buf[0] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI bus// Buf[1] = (unsigned char)(SPI_I2S_ReceiveData(SPI2));while((SPI2->SR &0x0002)==0); SPI2->DR = 0x00;while((SPI2->SR &0x0001)==0);Buf[1] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI buswhile((SPI2->SR &0x0002)==0); SPI2->DR = 0x00;while((SPI2->SR &0x0001)==0);Buf[2] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI buswhile((SPI2->SR &0x0002)==0); SPI2->DR = 0x00;while((SPI2->SR &0x0001)==0);Buf[3] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI buswhile((SPI2->SR &0x0002)==0); SPI2->DR = 0x00;while((SPI2->SR &0x0001)==0);Buf[4] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI buswhile((SPI2->SR &0x0002)==0); SPI2->DR = 0x00;while((SPI2->SR &0x0001)==0);Buf[5] = (unsigned char)(SPI_I2S_ReceiveData(SPI2)); // Return the Byte read from the SPI busADS_SPI_CS_HIGH();Acc_X = ((Buf[1]<<8|Buf[0]));Acc_Y = ((Buf[3]<<8|Buf[2]));Acc_Z = ((Buf[5]<<8|Buf[4]));sprintf(StrBuff,"X=%4.1f***Y=%4.1f***Z=%4.1f\r\n",Acc_X*3.9/1000*9.8,Acc_Y*3.9/1000*9.8,Acc_Z*3.9/1000*9.8);SendData(StrBuff,strlen(StrBuff));
}
从上面可以看出,只需填写第一个寄存器的地址之后,后面的数据可以直接读取,无需再修改寄存器。
4、DMA 多字节读取
使用DMA进行数据读取,在这里我使用数据更新中断去读取数据。
设置INT1数据更新中断使能,触发外中断去开始DMA数据数据传输。
void SPI2Init(void)
{SPI_InitTypeDef SPI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;SPI_I2S_DeInit(SPI2);//Enable the SPI periph RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);Spi2IOInit();// SPI configurationSPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI2, &SPI_InitStructure);// Enable the SPI2SPI_Cmd(SPI2, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;NVIC_Init(&NVIC_InitStructure);MyDMAInit(); EXTIX_Init();
}void MyDMAInit()
{DMA_InitTypeDef DMA_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA时钟DMA_DeInit(DMA1_Stream3); //SPI_RX/* DMA Stream 3 */DMA_InitStructure.DMA_Channel = DMA_Channel_0; //DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)(&(SPI2->DR));·DMA_InitStructure.DMA_Memory0BaseAddr = (u32)(&ADXL345RXBuff[0]);//DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//DMA_InitStructure.DMA_BufferSize = FIFO_COUNT*7;//DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//DMA_Init(DMA1_Stream3, &DMA_InitStructure);//³õʼ»¯DMA StreamSPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Rx,ENABLE);DMA_ITConfig(DMA1_Stream3, DMA_IT_TC, ENABLE);DMA_Cmd(DMA1_Stream3, DISABLE);DMA_DeInit(DMA1_Stream4); //SPI_TX/* DMA Stream 4*/DMA_InitStructure.DMA_Channel = DMA_Channel_0; //DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)(&(SPI2->DR));//DMA_InitStructure.DMA_Memory0BaseAddr = (u32)(&ADXL345TXBuff[0]);//DMADMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//DMA_InitStructure.DMA_BufferSize = 7;//DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//DMA_Init(DMA1_Stream4, &DMA_InitStructure);//SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);// DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);
}void EXTIX_Init()
{NVIC_InitTypeDef NVIC_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//GPIO_PuPd_DOWN;//GPIO_PuPd_UP;//GPIO_PuPd_NOPULL;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(GPIOD, &GPIO_InitStructure);SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource8);//EXTI_InitStructure.EXTI_Line = EXTI_Line8;//LINE8EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //EXTI_InitStructure.EXTI_LineCmd = ENABLE;//EXTI_Init(&EXTI_InitStructure);//NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//NVIC_Init(&NVIC_InitStructure);
}u8 ExtiFlag=0; // 数据更新中断标志位
void EXTI9_5_IRQHandler()
{if(EXTI_GetITStatus(EXTI_Line8)){DMA_Cmd(DMA1_Stream3, DISABLE); DMA_Cmd(DMA1_Stream4, DISABLE); u8 TempData = SpiReadCmd(0x30);if((TempData&0x80))ExtiFlag=1;EXTI_ClearITPendingBit(EXTI_Line8);}
}void SPIDMAReadADXL345Data()
{int pro=0;ADS_SPI_CS_LOW(); DMA_Cmd(DMA1_Stream3, ENABLE);ADXL345TXBuff[0]=0xF2;ADXL345TXBuff[1]=0x00;ADXL345TXBuff[2]=0x00;ADXL345TXBuff[3]=0x00;ADXL345TXBuff[4]=0x00;ADXL345TXBuff[5]=0x00;ADXL345TXBuff[6]=0x00;DMA_Cmd(DMA1_Stream4, DISABLE); DMA_SetCurrDataCounter(DMA1_Stream4,7); DMA_Cmd(DMA1_Stream4, ENABLE);while(DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET){pro=DMA_GetCurrDataCounter(DMA1_Stream4);}DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_BSY)==SET); //需要等待SPI总线传输完成最后一个字节,否则Z轴数据存在问题。ADS_SPI_CS_HIGH();ExtiFlag=0;
}u8 DMAReadFlag = 0; // DMA接收数据完成中断标志位
void DMA1_Stream3_IRQHandler()
{if (DMA_GetITStatus(DMA1_Stream3, DMA_IT_TCIF3) != RESET){DMA_ClearFlag(DMA1_Stream3, DMA_IT_TCIF3);DMAReadFlag=1;DMA_Cmd(DMA1_Stream3, DISABLE);}
}void ReadDMAData()
{short int Acc_X=0,Acc_Y=0,Acc_Z=0;unsigned char StrBuff[50];if(ExtiFlag==1) //数据更新中断,则开始DMA读取数据{SPIDMAReadADXL345Data();}if(DMAReadFlag) //读取数据完成之后,则开始计算三轴并显示{Acc_X = ((ADXL345RXBuff[2]<<8|ADXL345RXBuff[1]));Acc_Y = ((ADXL345RXBuff[4]<<8|ADXL345RXBuff[3]));Acc_Z = ((ADXL345RXBuff[6]<<8|ADXL345RXBuff[5]));sprintf(StrBuff,"X=%4.3f Y=%4.3f Z=%4.3f\r\n",Acc_X*3.9/1000*9.8,Acc_Y*3.9/1000*9.8,Acc_Z*3.9/1000*9.8);SendData(StrBuff,strlen(StrBuff));DMAReadFlag=0;}
}
5、DMA FIFO数据读取
FIFO模式共分为三种,FIFO模式,流模式和触发模式,一般使用前两种,FIFO模式存满缓存区之后则不再继续填充数据,而流模式则继续回覆盖之前已存在的数据。
FIFO最大缓存32级数据,即32个三轴数据,总共32*6=192个数据。FIFO可设置存满一定字节后触发中断,中断为水印中断(Watermark 奇怪的名字)。存满之后继续填充缓存器,直到存满32级缓存。所以不需要完全存满再去读取数据,那样时效性不高,可设置16级之后就读取数据,这样类似于半中断,效率更高。
这个FIFO唯一一点不好的地方我觉得是,FIFO数据不是一次性读出,而是多次通过寄存器去读取,意思就是FIFO数据的读取地址就是0x32-0x37,读完之后,FIFO缓存就往寄存器里填充缓存的数据,然后再去读,直到填充完。
使用水印中断来触发外中断去读取FIFO数据。
void ADXL345Init()
{u8 TempData;SPI2Init();TempData = SpiReadCmd(0x00);while(TempData!=0xE5){SendData(&TempData,1);}SpiWriteCmd(0x2E,0x00); SpiWriteCmd(0x31,0x0B); SpiWriteCmd(0x2D,0x08); SpiWriteCmd(0x2C,0x0E); SpiWriteCmd(0x2F,0x03); SpiWriteCmd(0x38,0x9F); // 设置FIFO模式 10011111 32条目 流模式 只保存最新数据SpiWriteCmd(0x1E,0x00); SpiWriteCmd(0x1F,0x00); SpiWriteCmd(0x20,0x00); SpiWriteCmd(0x2E,0x83); //设置INT2 为水印中断ADXL345TXBuff[0]=0xF2; //DMA 发送缓存ADXL345TXBuff[1]=0x00;ADXL345TXBuff[2]=0x00;ADXL345TXBuff[3]=0x00;ADXL345TXBuff[4]=0x00;ADXL345TXBuff[5]=0x00;ADXL345TXBuff[6]=0x00;
}u8 ExtiFlag=0;
void EXTI9_5_IRQHandler()
{if(EXTI_GetITStatus(EXTI_Line8)){DMA_Cmd(DMA1_Stream3, DISABLE); DMA_Cmd(DMA1_Stream4, DISABLE); u8 TempData = SpiReadCmd(0x30); //读取中断标志位 确定中断产生if((TempData&0x02))ExtiFlag=1;EXTI_ClearITPendingBit(EXTI_Line8);}
}void SPIDMAReadADXL345Data()
{u8 i=0;DMA_Cmd(DMA1_Stream3, ENABLE);for(i=0;i<FIFO_COUNT;i++) //FIFO_COUNT 代表触发FIFO缓存个数{ADS_SPI_CS_LOW(); DMA_Cmd(DMA1_Stream4, DISABLE); DMA_SetCurrDataCounter(DMA1_Stream4,7); /DMA_Cmd(DMA1_Stream4, ENABLE);while(DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET){DMA_GetCurrDataCounter(DMA1_Stream4);//}DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_BSY)==SET);ADS_SPI_CS_HIGH();}ExtiFlag=0;
}u8 DMAReadFlag = 0;
void DMA1_Stream3_IRQHandler()
{if (DMA_GetITStatus(DMA1_Stream3, DMA_IT_TCIF3) != RESET){DMA_ClearFlag(DMA1_Stream3, DMA_IT_TCIF3);DMAReadFlag=1;DMA_Cmd(DMA1_Stream3, DISABLE);}
}void ReadDMAData()
{short int Acc_X=0,Acc_Y=0,Acc_Z=0;unsigned char StrBuff[50];unsigned char C=10; if(ExtiFlag==1) {SPIDMAReadADXL345Data(); }if(DMAReadFlag) {Acc_X = ((ADXL345RXBuff[7*C+2]<<8|ADXL345RXBuff[7*C+1]));Acc_Y = ((ADXL345RXBuff[7*C+4]<<8|ADXL345RXBuff[7*C+3]));Acc_Z = ((ADXL345RXBuff[7*C+6]<<8|ADXL345RXBuff[7*C+5]));sprintf((char *)StrBuff,"X=%4.3f Y=%4.3f Z=%4.3f\r\n",Acc_X*3.9/1000*9.8,Acc_Y*3.9/1000*9.8,Acc_Z*3.9/1000*9.8);SendData(StrBuff,strlen((char *)StrBuff));DMAReadFlag=0;}
}
最后楼主分享一个完整的代码,使用STM32F407读取ADXL345三轴加速度传感器数据,keil工程。
下载链接:
工程文件 SPI协议版本
工程文件 SPI+DMA协议版本
如有雷同,纯属我抄你,有问题可以直接联系邮箱,在个人资料里面。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!