我正在尝试模拟10位AEAT-6010旋转编码器中的数据,并将其通过ATtiny3217上SPI协议的MISO引脚发送出去。 ATtiny充当从设备,并接收CLK和SS信号作为输入,以通过输出数据(编码器值)进行响应。编码器遵循SSI协议发送数据,如下所示:
尝试在ATtiny上通过8位SPI协议发送10位数据时出现问题。 SPI协议的主设备是TMS320F2808芯片,从中我接收11个时钟脉冲和SS信号。测量的信号和数据如下所示:
这里我尝试发送的数据是0b10
,仅用于测试。我可以在MISO线上看到正确的数据,但是信号中间还有三个1。如下面的配置所示,这是ATtiny的SPI设置中的BUFEN=1
和BUFWR=1
(在没有缓冲模式的情况下,后3位是3,而在前3位是)读为1):
int8_t SPI_0_init()
{
SPI0.CTRLA = 0 << SPI_CLK2X_bp /* Enable Double Speed: disabled */
| 0 << SPI_DORD_bp /* Data Order Setting: enabled */
| 1 << SPI_ENABLE_bp /* Enable Module: enabled */
| 0 << SPI_MASTER_bp /* SPI module in slave mode */
| SPI_PRESC_DIV4_gc; /* System Clock / 4 */
SPI0.CTRLB = 1 << SPI_BUFEN_bp /* Buffer Mode Enable: enabled */
| 1 << SPI_BUFWR_bp /* Buffer Write Mode: enabled */
| SPI_MODE_0_gc /* SPI Mode 1 */
| 0 << SPI_SSD_bp; /* Slave Select Disable: disabled */
SPI0.INTCTRL = 0 << SPI_DREIE_bp /* Data Register Empty Interrupt Enable: enabled */
| 1 << SPI_IE_bp /* Interrupt Enable: enabled */
| 0 << SPI_RXCIE_bp /* Receive Complete Interrupt Enable: disabled */
| 0 << SPI_SSIE_bp /* Slave Select Trigger Interrupt Enable: disabled */
| 0 << SPI_TXCIE_bp; /* Transfer Complete Interrupt Enable: disabled */
return 0;
}
我已经确认TMS320F2808的SPI模块和ATtiny的数据相同(在时钟下降沿读取)。关于SPI的缓冲区如何工作或SPI的中断,我是否缺少某些东西?我不确定在启用不同的中断时要在ISR中做什么(比清除标志还要多)。这是我的主要功能(ISR目前为空):
int main(void)
{
/* Initializes MCU, drivers and middleware */
atmel_start_init();
sei(); // Enable global interrupts
/* Replace with your application code */
while (1) {
SPI_transmit(enc_data_L);
}
SPI_transmit()
如下:
void SPI_transmit(uint16_t enc_data)
{
// Then start the transmission by assigning the data to the SPI data register
SPI0.DATA = enc_data;
//SPI0.DATA = enc_data_H;
// Now wait for the data transmission to complete by periodically checking the SPI status register
//the SPI_IF is the only interrupt flag with a function in non-buffered mode.
while(!(SPI0.INTFLAGS & (SPI_RXCIF_bm)));
SPI0.DATA; //Dummy read to clear flag
}
我也尝试按照建议的here拆分16位数据,但是对于8位数据也仍然存在问题。希望这是足够的背景信息。我感谢任何想法!
答案 0 :(得分:0)
SPI_transmit
中的您正在等待直到传输完成。此后,输入缓冲区已完全传输,现在为空。
while(!(SPI0.INTFLAGS & (SPI_RXCIF_bm))); // waits until data is transmitted
RXCIF
在接收缓冲区中有数据时设置,即输出缓冲区的传输也已完成。
因此,当主机发送下一个字节时,输出缓冲区中尚无新数据要发送。可能SPI模块只是重复发送前一个字节。
因此,当发送缓冲区为空并准备好下一个字节时,请等待设置的DREIF标志,而不是等待RXCIF标志。 您可以忽略传入的数据,因为您无论如何都不使用
void SPI_transmit(uint16_t enc_data)
{
// Wait until buffer is ready to get the next data byte
while(!(SPI0.INTFLAGS & (SPI_DREIF_bm)));
// Then start the transmission by assigning the data to the SPI data register
SPI0.DATA = enc_data;
// Don't care about read buffer
}