由于使用I2C读取MPU6000的数据速率有限,所以想用SPI来读取数据,但是调了两天SPI一直没调通,贴出源码请大神指教。
首先关于MPU6000的SPI描述我就没有看的很明白,一直没弄清楚其数据位是要求8位还是16位,两种数据位均尝试了也没有成功,下面是MPU6000中关于SPI的描述。
因为观察MPU6000的寄存器都是8位的,所以首先我是按照8位的数据格式来做的,SPI1的初始化程序如下:
//SPI1速度设置函数
//SpeedSet:0~7
//SPI速度=fAPB2/2^(SpeedSet+1)
//APB2时钟一般为72Mhz
void SPI1_SetSpeed(u8 SpeedSet)
{
SPI1->CR1|=0<<6; //关闭SPI设备
SpeedSet&=0X07; //限制范围
SPI1->CR1&=0XFFC7;
SPI1->CR1|=SpeedSet<<3; //设置SPI1速度
SPI1->CR1|=0<<7; //MSBfirst
SPI1->CR1|=1<<6; //SPI设备使能
}
//SPI1 读写8bit
//TxData:要写入的8bit
//返回值:读取到的8bit
u8 SPI1_ReadWriteByte(u8 TxData)
{
u16 retry=0;
// SPI_CS=0;//使能SPI1
while((SPI1->SR&1<<1)==0) //等待发送区空
{
retry++;
if(retry>=0XFFFE)return 0; //超时退出
}
SPI1->DR=TxData; //发送8个bit
retry=0;
// delay_us(1);
while((SPI1->SR&1<<0)==0) //等待接收完8个bit
{
retry++;
if(retry>=0XFFFE)return 0; //超时退出
}
return SPI1->DR; //返回收到的数据
// SPI_CS=1;//关闭SPI1
}
//以下是SPI模块的初始化代码,配置成主机模式,访问IMU
//SPI口初始化
//这里针是对SPI1的初始化
void SPI1_Init(void)
{
RCC->APB2ENR|=1<<2; //PORTA时钟使能
RCC->APB2ENR|=1<<12; //SPI1时钟使能
//这里只针对SPI口初始化
GPIOA->CRL&=0X0000FFFF;
GPIOA->CRL|=0XBBB30000; //PA5/6/7复用,功能转化为SPI,PA4为推免输出,用于软件片选
GPIOA->ODR|=0X7<<5; //PA5/6/7上拉
GPIOA->ODR|=1<<4; //PA4初始化为高电平,从设备没有使能
SPI1->CR1|=0<<10; //全双工模式
SPI1->CR1|=1<<9; //软件nss管理
SPI1->CR1|=1<<8; //SSI设置为高电平,关闭SPI1
SPI1->CR1|=1<<2; //SPI主机
SPI1->CR1&=~(1<<11); //8bit数据格式
SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
SPI1->CR1|=1<<0; //数据采样从第一个时间边沿开始,CPHA=1
//对SPI1属于APB2的外设.时钟频率最大为72M.
SPI1->CR1|=0x6<<3; //Fsck=Fpclk1/128
SPI1->CR1|=0<<7; //MSBfirst
SPI1->CR1|=1<<6; //SPI设备使能
}
然后最初的想法是通过读取MPU6000的I2C地址寄存器,读出地址并通过串口输出,如果地址读出正常说明与MPU6000连接正常,读取地址的程序如下:
SPI_CS=0;
s=SPI1_ReadWriteByte(MPU6050_RA_WHO_AM_I|0x80); //读取ID
SPI_CS=1;
printf("\r\n%d\r\n",s);
但是串口输出的一直都是初始化的s值0
然后我又尝试采用16位数据格式,16位数据格式的初始化程序就是将8位修改为16位,I2C的ID读取函数如下:
SPI_CS=0;
s=SPI1_ReadWriteByte((MPU6050_RA_WHO_AM_I|0x80)<<8); //读取ID
SPI_CS=1;
printf("\r\n%d\r\n",s);
但是依然输出都是0
其中:
#define SPI_CS    Aout(4) //SPI片选信号
SPI_CS是片选信号
请熟悉的大神帮忙看下,SPI的程序中哪里有问题?为什么一直都无法和MPU6000正常通讯?
不胜感激!!!!!!!!!
附上小弟的原始程序!
|