C语言 如何接收AVR SPI数据



我正在学习AVR。我的问题是,SPI0_exchangeData发送接收数据在同一时间与同一时钟。现在我希望在接收数据时,它应该向数组中添加1,我可以看到这是我接收到的数据。

注:我的母语不是英语,所以我阅读了数据表和一些在线文章,但没有成功。

#include <xc.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
void SPI0_init(void);
void LTCSelect(void);
void LTCDeselect(void);
uint8_t SPI0_exchangeData(uint8_t data);
void SPI0_init(void)
{
PORTA.DIR |= PIN4_bm; /* Set MOSI pin direction to output (output to LTC2983) */
PORTA.DIR &= ~PIN5_bm; /* Set MISO pin direction to input (input form LTC2983) */
PORTA.DIR |= PIN6_bm; /* Set SCK pin direction to output (output to LTC2983) */
PORTA.DIR |= PIN7_bm; /* Set CS pin direction to output  (output to LTC2983) */

SPI0.CTRLA = SPI_CLK2X_bm /* Enable double-speed */
| SPI_DORD_bm /* LSB is transmitted first */
| SPI_ENABLE_bm /* Enable module */
| SPI_MASTER_bm /* SPI module in Master mode */
| SPI_PRESC_DIV16_gc; /* System Clock divided by 16 */
}
uint8_t SPI0_exchangeData(uint8_t data)
{

SPI0.DATA = data;
while (!(SPI0.INTFLAGS & SPI_IF_bm))  /* waits until data is exchanged*/
{

}
return SPI0.DATA;
}

void LTCSelect(void)
{
PORTA.OUT &= ~PIN7_bm; // Set SS pin value to LOW
}
void LTCDeselect(void)
{
PORTA.OUT |= PIN7_bm; // Set SS pin value to HIGH
}
void sendArray(uint8_t data[], uint8_t length) {
for(uint8_t i = 0; i < length; i++) {
SPI0_exchangeData(data[i]);
}
}
// Suppose we have an array named buffer
uint8_t buffer[] = { 10, 20, 30};

int main(void)
{
SPI0_init();
while(1){

LTCSelect();
sendArray(buffer, sizeof(buffer));
LTCDeselect();  
}
}

SPI
我在我的AVR项目中使用两个函数,这是为我工作的。但是目前不支持中断。

我的SPI发送函数:

void spi_master_send(uint8_t *data, int len)
{
int i;

if (!data)
return;

if (len < 1)
return;

for (i = 0; i < len; i++) {
SPDR = data[i];

while (!(SPSR & (1 << SPIF)))
;
}
}

从我的代码的基本代码是相同的你的SPI0_exchangeData()。你的函数也应该在你的项目中工作。

我的SPI接收函数:

void spi_master_recv(uint8_t *data, int len)
{
int i;

if (!data)
return;

if (len < 1)
return;

for (i = 0; i < len; i++) {
/* send dummy */
SPDR = 0xFF;

while (!(SPSR & (1 << SPIF)))
;

data[i] = SPDR;
}
}

要在AVR上通过SPI接收数据,必须发送一个虚拟字节。AVR上的SPI实现是一个移位寄存器。

LTC2983
我现在还没有使用LTC2983。但是我对这个设备有一些建议。

第一:
你确定,你使用正确的SPI模式为这个设备?SPI有四种模式。有关更多信息,请参阅此描述。我没有检查这个设备的正确模式。但是您可以在设备的数据表(SPI时序图-第11页)中找到它。

秒:
您设置了错误的数据顺序。LTC2983使用MSB数据顺序(最高有效位优先)。→参见datasheet - page 15)

第三:
你在代码中循环发送10,20,3010不是读取LTC2983内存(寄存器文件)的正确SPI命令。


有效的命令有:
00000011b->0x03→从设备内存(寄存器文件)读取
00000010b->0x02→写入设备内存(寄存器文件)
XXXXXX0Xb->NOP (No operation)

要读取设备内存,首先发送0x03,然后发送您想要读取的地址。一个可能的例子:

#define LTC2983_RD    0x03   /* Command read */
#define LTC2983_CSR   0x0000 /* Command status register as example */
uint8_t data_cmd[3];
uint8_t data_out[1];
data_cmd[0] = LTC2983_WR;
data_cmd[1] = LTC2983_CSR << 8;
data_cmd[2] = LTC2983_CSR & 0xFF;
/* Select LTC2983 here */
spi_master_send(data_cmd, 3);
spi_master_recv(data_out, 1);
/* Deselect LTC2983 */

使用这个(伪)代码,您应该能够读取LTC2983的命令状态寄存器。

要写入设备,首先发送0x02,然后发送地址,然后发送要写入的值。

#define LTC2983_WR    0x02   /* Command write */
#define LTC2983_CSR   0x0000 /* Command status register as example */
uint8_t data_cmd[4];
data_cmd[0] = LTC2983_RD;
data_cmd[1] = LTC2983_CSR << 8;
data_cmd[2] = LTC2983_CSR & 0xFF;
data_cmd[3] = 0x42;
/* Select LTC2983 here */
spi_master_send(data_cmd, 4);
/* Deselect LTC2983 */

使用这个(伪)代码,您应该能够将0x42写入LTC2983。

详细信息请参考数据表。

最新更新