0

我无法让我的 STM32f3 发现板(数据表)上的 SPI陀螺仪传感器(I3G4250D)一起工作在寄存器级别。我知道我正在发送数据,因为我处于全双工状态并使用 16 位数据打包从传感器接收虚拟字节,但是当我尝试使用 8 位访问 DR 寄存器接收数据时,我从传感器得到不一致的值,有时返回一个字节 0xff其他时候返回 2 个字节 0xffff (至少我认为这是正在发生的事情),但没有来自我想要读取的传感器寄存器的实际值。我认为这与我芯片上 STM32 SPI 的自动打包有关,但我认为我正在通过使用 uint8_t* 访问 DR 寄存器来解决这个问题,但它似乎不起作用。

这是我的 SPI 初始化函数,其中包括尝试在其末尾读取字节并将字节写入传感器寄存器函数:

void SPI_Init() {

/* Peripheral Clock Enable */
RCC->AHBENR |= RCC_AHBENR_GPIOEEN|RCC_AHBENR_GPIOAEN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;

/* GPIO Configuration */
GPIOA->MODER |= GPIO_MODER_MODER5_1|GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1;                            //Alternate function
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5|GPIO_OSPEEDER_OSPEEDR6|GPIO_OSPEEDER_OSPEEDR7;     //High speed
GPIOA->AFR[0] |= 0x00500000|0x05000000|0x50000000;                                                                              //AF for SCK,MISO,MOSI

GPIOE->MODER |= GPIO_MODER_MODER3_0;                                                                                                            //Port E for NSS Pin
GPIOE->MODER |= GPIO_MODER_MODER3_0;

/* SPI Configuration */
SPI1->CR2 |= SPI_CR2_FRXTH|SPI_CR2_RXDMAEN;     //Enable DMA but DMA is not used
// not sure if I need this?|SPI_CR1_CPOL|SPI_CR1_CPHA; 
SPI1->CR1 |= SPI_CR1_BR_1|SPI_CR1_SSM|SPI_CR1_SSI|SPI_CR1_MSTR|SPI_CR1_SPE;   //big endian, SPI@6MH, since using software set SPI_CR1_SSI to high for master mode


/* Slave Device Initialization */
SPI_WriteByte(CTRL_REG1_G,0x9f);
SPI_WriteByte(CTRL_REG4_G,0x10);
SPI_WriteByte(CTRL_REG5_G,0x10);

//receive test
uint8_t test =0xff;
uint8_t* spiDrPtr = (__IO uint8_t*)&SPI1->DR;
*spiDrPtr = 0x80|CTRL_REG1_G;
while(!(SPI1->SR & SPI_SR_TXE)){}
//SPI1->CR2 &= ~(SPI_CR2_FRXTH); //this is done in HAL not sure why though
*spiDrPtr = test;                                                   //Send dummy
while(!(SPI1->SR & SPI_SR_RXNE)){}
test = *spiDrPtr;
}

static void SPI_WriteByte(uint8_t regAdd, uint8_t data) {
  uint8_t arr[2] = {regAdd,data}; //16 bit data packing
  SPI1->DR = *((uint16_t*)arr);
}

有什么建议么?

4

2 回答 2

0
  1. 如果不使用 DMA,请不要启用它。
  2. 您需要强制 16 位访问(不是 32 位)
static void SPI_WriteByte(uint8_t regAdd, uint8_t data) {
  uint8_t arr[2] = {regAdd,data}; //16 bit data packing
  *(volatile uint16_t *)&SPI1->DR = *((volatile uint16_t*)arr);
}
于 2021-11-23T16:49:29.277 回答
0

尝试使用 FRXTH = 0,并以 16 位字执行所有 DR 读取和写入,然后丢弃第一个字节。

对于后面的问题,关于 CPOL/CPHA。这些位在位级别控制 SPI 传输格式。参考下图(来自维基百科)。 来自维基百科的 SPI 消息格式图像

CPOL = 0,CPHA = 0 也称为“SPI 模式 0”,数据位在 SCK 上升沿采样

CPOL = 1,CPHA = 1也称为“SPI模式3”,数据位也在上升沿采样。

两种模式之间的区别在于传输之间的 SCK 电平,以及第一位之前的额外下降沿。

一些芯片明确声明支持模式 0 和模式 3。然而在 I3G4250D 数据表中,第 5.2 节:“SDI 和 SDO 分别是串行端口数据输入和输出。这些线在 SPC 的下降沿驱动,应在 SPC 的上升沿捕获。”

当数据在模式 0 下从 mcu 发送到芯片时,mcu 在第一个上升沿之前驱动 MOSI 线。因此,从芯片可以在模式 0 和模式 3 下接收有效数据。但是当数据从芯片传输到单片机时,芯片可能需要第一个 SCK 下降沿将第一个数据位移位/锁存到 MISO 线和模式 0您将收到一位偏移的读数。

我强调了“可能”这个词,因为芯片仍然可以在两种模式下正确工作,用下降的 nSS 边缘锁存第一位,制造商只是没有进行测试,或者不保证它会工作在所有条件下进行其他修订。

于 2021-11-24T05:47:39.163 回答