买到一个带编码器的电机,卖家留出来读取编码器数据的接口有SPI
具体的原理图如下:
P2标注的是SPI的接口,其中MISO和MOSI是硬件连接到一起的
使用ACM32G103的硬件SPI2去读取其角度数据
原理大概如下:
1、先发送读取数据的指令,然后再接收数据,一个半双工通信的过程
2、因为MOSI和MISO硬件上连接到了一起,根据TLE5102B的通信时序要求就要稍微修改一下MOSI引脚的状态,片选使用软件片选
3、SPI2的配置CPOL=0,CPHA=1
4、SPI2引脚:
PB9 CS AF3
PB8 SCK AF3
PB7 MOSI AF3
PB6 MISO AF3
其中CS的初始化要修改一下,要初始化为GPIO
接下来直接看代码
#define SPI_USE SPI2
void SPI_USE_Transfer_OneByte(uint8_t *sdata,uint16_t ssize)
{/* Clear Batch Done Flag */SET_BIT(SPI_USE->STATUS, SPI_STATUS_TX_BATCH_DONE);SET_BIT(SPI_USE->STATUS, SPI_STATUS_BATCH_DONE);/* Clear TX FIFO */SET_BIT(SPI_USE->TX_CTL, SPI_TX_CTL_FIFO_RESET);CLEAR_BIT(SPI_USE->TX_CTL, SPI_TX_CTL_FIFO_RESET);/* Set Data Size */SPI_USE->BATCH = ssize;/* Tx Enable */SPI_USE->TX_CTL |= SPI_TX_CTL_EN;/* Transmit Start */SPI_USE->CS |= SPI_CS_CS0;while(ssize > 0){while (SPI_USE->STATUS & SPI_STATUS_TX_FIFO_FULL){}SPI_USE->DAT = *sdata;sdata++;ssize--;}while (!(SPI_USE->STATUS & SPI_STATUS_TX_BATCH_DONE)){}/* Clear Batch Done Flag */SET_BIT(SPI_USE->STATUS, SPI_STATUS_TX_BATCH_DONE);SET_BIT(SPI_USE->STATUS, SPI_STATUS_BATCH_DONE);/* Tx Disable */SPI_USE->TX_CTL &= (~SPI_TX_CTL_EN);SPI_USE->CS &= (~SPI_CS_CS0);
}void SPI_USE_Receive_OneByte(uint8_t *rdata,uint16_t rsize)
{/* Clear Batch Done Flag */SET_BIT(SPI_USE->STATUS, SPI_STATUS_RX_BATCH_DONE);SET_BIT(SPI_USE->STATUS, SPI_STATUS_BATCH_DONE);/* Set Data Size */SPI_USE->BATCH = rsize;/* Rx Enable */SPI_USE->RX_CTL |= SPI_RX_CTL_EN;/* Receive Start */SPI_USE->CS |= SPI_CS_CS0;while(rsize > 0){/* Wait Rx FIFO Not Empty */while (SPI_USE->STATUS & SPI_STATUS_RX_FIFO_EMPTY){}*rdata = SPI_USE->DAT;rsize--;rdata++;}/* Wait Transmit Done */while (!(SPI_USE->STATUS & SPI_STATUS_RX_BATCH_DONE));/* Clear Batch Done Flag */SET_BIT(SPI_USE->STATUS, SPI_STATUS_RX_BATCH_DONE);SET_BIT(SPI_USE->STATUS, SPI_STATUS_BATCH_DONE);/* Rx Disable */SPI_USE->RX_CTL &= (~SPI_RX_CTL_EN);/* Receive End */SPI_USE->CS &= (~SPI_CS_CS0);
}
再来看读取角度的过程
// TxBuffer[0] = 0x80;
// TxBuffer[1] = 0x21;
GPIOB->BSC = GPIO_PIN_9 << 16U;
PB7_OUTPUT();
SPI_USE_Transfer_OneByte(TxBuffer,2);
PB7_INPUT();
SPI_USE_Receive_OneByte(RxBuffer,2);
GPIOB->BSC = GPIO_PIN_9;
Angle= (RxBuffer[0]<<8 | RxBuffer[1])&0x7FFF;
每次发送完读取数据的指令之后,因为MOSI和MISO硬件连接到一起,我们就要将MOSI引脚由复用为SPI设置为输入状态,下一次发指令的时候重新复用为SPI
其中将MOSI引脚设置成输入和复用的代码如下
void PB7_INPUT(void)
{GPIOB->MD &= ~(3<<14);
}void PB7_OUTPUT(void)
{GPIOB->AF0 |= GPIO_FUNCTION_3 << 28;GPIOB->DS0 |= GPIO_DRIVE_LEVEL3 <<28;GPIOB->OTYP &= (~GPIO_PIN_7);GPIOB->PUPD |= GPIO_PULLUP<<14;GPIOB->MD |= GPIO_MODE_AF_PP<<14;
}
读取速度,TLE5012B推荐的SPI速率最大是8M,可以根据实际情况提高,也能读到数据