打印

STM32的SPI驱动加速度芯片LIS33DE

[复制链接]
7343|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 xuqj4490 于 2011-2-16 14:01 编辑

前面用STM32的I2C来驱动加速度芯片LIS33DE,成功了,但感觉STM32的I2C比较麻烦,而LIS33DE(ST公司的)支持I2C和SPI两种总线,所以现在想用SPI来做,结果搞了很久LIS33DE一直没有输出。

问题:用示波器观察,CS和SCK都正常,STM32的MOSI脚有数据送出,但MISO一直没有数据。不知道是什么原因,让大家帮忙看看。对于我自己写的那几个读写程序比较怀疑,望大家指点下。

不多说了,上程序和图。


1 我使用的是STM32的SPI2 接LIS33DE。下面是SPI2的配置
void SPI_Configuration(void)
{
     SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    //启动SPI时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
     //////下面是SPI相关GPIO初始化//////
    //SPI2模块对应的SCK、MISO、MOSI为AF引脚
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_Init(GPIOB, &GPIO_InitStructure);

   //PB12 pin: SPI2_CS
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_Init(GPIOB, &GPIO_InitStructure);  
   
    //////SPI模块配置//////
    //一开始SD初始化阶段,SPI时钟频率必须<400K
    SPI_Cmd(SPI2, DISABLE);              //必须先禁能,才能改变MODE
    SPI2_CS_DISABLE();
     /* SPI2 configuration */
     SPI_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_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI2, &SPI_InitStructure);
     /* Enable SPI2  */
    SPI_Cmd(SPI2, ENABLE);
}
2  LIS33DE的SPI接口介绍

   SPI读写时序
   读程序:
   u8 Lis33de_SPI_RD(u8 add)
{
    u8  tmp;
SPI2_CS_ENABLE();
SPI_ReadWriteByte(add | 0x80);
tmp=SPI_ReadWriteByte(0xff);  
SPI2_CS_DISABLE();
return tmp;
}

写程序:
void Lis33de_SPI_WR(u8 add,u8 wrdata)
{
    SPI2_CS_ENABLE();
  SPI_ReadWriteByte(add);
  SPI_ReadWriteByte(wrdata);
  SPI2_CS_DISABLE();
}

SPI读写子函数:
u8 SPI_ReadWriteByte(u8 TxData)
{
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI2, TxData);
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
  return SPI_I2S_ReceiveData(SPI2);
}

LIS33DE的初始化
void SPI_Lis33de_Init()
{
  Lis33de_SPI_WR(0x20,0x47);
  Lis33de_SPI_WR(0x21,0x00);
  Lis33de_SPI_WR(0x22,0x00);
}

程序的主结构:
int main(void)
{   
    u8 DX,DY,DZ;
    RCC_Configuration();

    GPIO_Configuration();
    NVIC_Configuration();
    USART1_Configuration();
    SPI_Configuration() ;
    SPI_Lis33de_Init();
   while(1)
   {
         DX = Lis33de_RD(0x29);
         DY = Lis33de_RD(0x2B);
         DZ = Lis33de_RD(0x2D);
         printf("$\tg\t%d\t%d\t%d",DX,DY,DZ);
      }
}

SPI.jpg (115.43 KB )

SPI.jpg

SPIREAD.jpg (70.44 KB )

SPIREAD.jpg

SPIWRITE.jpg (69.74 KB )

SPIWRITE.jpg
沙发
xuqj4490|  楼主 | 2011-2-17 11:06 | 只看该作者
老天捉弄人,没有改什么地方,莫名其妙调试成功了。
就算是把这个驱动的代码和坛子里的网友共享了。

使用特权

评论回复
板凳
kinbing| | 2011-2-17 13:39 | 只看该作者
主要是写寄存器的时候.CS拉低后没加延迟,还有CS拉高结束之前要加入延迟.
虽然手册上写得是5ns左右.按道理说,没加也没事.
我觉得用GPIO拉低CS线,速度比较慢.而SPI发送数据比较快.所以造成片选延迟不够.
下面是我写的程序
/*                    库文件驱动说明

       
*/

/*    意法lis3lv02qd传感器的CS片选       */
#define Lis_Cs_High         GPIO_SetBits(GPIOB,GPIO_Pin_7)
#define Lis_Cs_Low                GPIO_ResetBits(GPIOB,GPIO_Pin_7)

/*************** SPI0 写命令************************/
void SPI_Write(uint16_t address,uint16_t dat)  
{                                                                                       
        Lis_Cs_Low;       
        Delay(5);                    
        SPI2->DR=address;     
        while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);        //等待发送缓存空标志
        SPI2->DR=dat;
        while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);        //等待发送缓存空标志   
        Delay(10);        
        Lis_Cs_High;             
}

/************* SPI读两字节命令 ****************/
int16_t SPI_Read(int16_t address)
{               
        int16_t dat=0;
        Lis_Cs_Low;                            //片选拉低
        Delay(1);        
        while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);                  
        SPI2->DR=address;       
        while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
       
        SPI2->DR=0xff;                       
        while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
        dat= SPI2->DR;

        SPI2->DR=0xff;
        dat<<=8;                       
        while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
       
        dat|=SPI2->DR;

        Delay(2);
        Lis_Cs_High;                  //片选拉高  
         
        return  dat;                   //返回dat
}

/*  lis3lv02qd SPI初始化函数         */
void SPI_Lis3_Init()               
{

        SPI_InitTypeDef  SPI_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;                 
        /* 使能SPI2  GPIOB 的时钟 */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);                 

        /* Configure SPI1 pins: SCK, MISO and MOSI */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_15 ;                //Pin_5是SCK时钟 Pin7是MOSI输出信号
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                                         //设成复用推挽
        GPIO_Init(GPIOB, &GPIO_InitStructure);                 
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 ;             //MISO                                                                                   ;                //Pin_5是SCK时钟 Pin7是MOSI输出信号,设成复用推挽
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_10MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;                        //上拉输入
        GPIO_Init(GPIOB, &GPIO_InitStructure);          
       
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;                   // lis3 的片选脚
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);       
         
       
               
        SPI_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_Low ;
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;          
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_CRCPolynomial = 7;                     
        SPI_Init(SPI2, &SPI_InitStructure);         
        SPI_Cmd(SPI2,ENABLE);
        SPI_SSOutputCmd(SPI2,DISABLE);
}


void Lis3_Init()
{
        SPI_Lis3_Init();                  //初始化SPI设置       
        //Delay(1000);         
        SPI_Write(0x20,0xD7);          //CTRL_REG1
        SPI_Write(0x21,0x15);           //CTRL_REG2  15四线模式,17三线模式                   
}

使用特权

评论回复
地板
xuqj4490|  楼主 | 2011-2-20 23:06 | 只看该作者
非常谢谢kinbing的回复和程序分享。
我贴出的程序也调试成功了。

使用特权

评论回复
5
fengshutietou| | 2012-5-22 13:00 | 只看该作者
楼主,我用I2C驱动怎么都不能成功呢?只是发送起始信号有回应,等发送设备地址0x3a时就没有回应了,然后我认为可能设备地址错了,用了for循环来发送,还是没有任何回应,不知道是怎么回事,还请楼主指点一下啊

使用特权

评论回复
6
allen_1| | 2015-6-17 11:38 | 只看该作者
谢谢,参考一下

使用特权

评论回复
7
wgy851808815| | 2016-9-7 12:32 | 只看该作者
xuqj4490 发表于 2011-2-17 11:06
老天捉弄人,没有改什么地方,莫名其妙调试成功了。
就算是把这个驱动的代码和坛子里的网友共享了。 ...

读取到的数据总是0xff怎么办?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

33

帖子

2

粉丝