我正在编写与外部射频芯片的 SPI 通信。微控制器是 Microchip 的 PIC24FJ64GA102 型号。
我想使用SPI的增强缓冲模式。
问题:从接收缓冲区中获取接收到的字节。
用到的SPI功能:
void SPI1_get(uint8_t* data, uint16_t length) {
uint16_t i = 0, l = length;
uint8_t dummy;
while (length > 0) {
while (SPI1STATbits.SPITBF || SPI1STATbits.SPIRBF) {
dummy = SPI1STAT;
}
do {
SPI1BUF = 0xff;
} while (SPI1STATbits.SPIRBF == 0 && --length > 0);
do {
while (SPI1STATbits.SRMPT == 0) {
}
data[i] = SPI1BUF;
++i;
} while (i < l && SPI1STATbits.SRXMPT != 1);
}
}
这里的电话:
uint8_t cmd[2]; cmd[0] = length; cmd[1] = address;
SPI1_put(cmd,2); // e.g: 0x02, 0x01
SPI1_get(buf,2); // e.g: 0x05, 0x01 (received data)
通信很好,用示波器和 SPI 解码模块检查。SPI 总线上的数据就像上面的注释一样: send 0x02 0x01 0xff 0xff
, received 0x00 0x00 0x05 0x01
,但是上面的函数没有正确地从接收缓冲区中检索数据。我已经测试了很多检查标志和中断的星座,但最终我能得到的最好结果是:(0x00 0x01
只有最后一个字节是正确的)。
还检查了勘误表,其中提到了两个不(不应该)影响我的代码的 SPI 问题。
我到底做错了什么?!
如这里所要求的 SPI1_put() 函数:
void SPI1_put(uint8_t* data, uint16_t length) {
uint16_t i = 0;
uint8_t dummy;
for (; i < length; ++i) {
while (SPI1STATbits.SPITBF)
; // maybe change to (_SPI1BEC == 7) ?
SPI1BUF = data[i];
dummy = SPI1BUF; //dummy read
}
}
[最新编辑:2015-02-05]
所以今天我能够在这个特定问题上花更多的时间,并提出了 ElderBug 建议的一个端口,同时处理了勘误表中提到的错误:
uint8_t out_buf[128];
uint8_t in_buf[128];
void SPI1_com(uint8_t* out, uint8_t* in, uint16_t out_len, uint16_t in_len) {
uint16_t len = out_len + in_len;
uint16_t sent = 0, recv = 0, i = 0;
// while (!SPI1STATbits.SRXMPT)
sent = SPI1BUF; // empty buffer
sent = SPI1BUF; // empty buffer
sent = 0;
if (out != out_buf && out != 0)
memcpy(out_buf, out, out_len);
while (sent < len && recv < len) {
if (SPI1STATbits.SPIBEC != 7 && sent < len) {
SPI1BUF = out_buf[sent++];
}
if (!SPI1STATbits.SRXMPT && recv < len) {
in_buf[recv] = SPI1BUF, recv++;
}
}
if (in != 0) {
for (i = 0; i < in_len; ++i) {
in[i] = in_buf[out_len + i];
}
// memcpy(in, in_buf + out_len, in_len);
}
for (i = 0; i < len; ++i) {
out_buf[i] = 0xff;
in_buf[i] = 0xff;
}
}
这段代码基本上可以工作。除了我无法解决的例外:
通信工作如下:
- 1字节:读/写位+长度
- 1字节:地址
- 1-127byte:数据
因此,当我从从芯片读取 1 个字节,即发送 3 个字节(rw+len、地址、dummybyte)时,in_buf
缓冲区中的数据为 0xFF。现在发生了一件奇怪的事情:当我只读取一个字节,而不改变任何东西(总线上只有一个虚拟字节)时,我的第一个字节in_buf
得到了正确的数据。但这似乎并不总是有效,因为我的程序仍然卡在某些点上。
我留下了很多问号。
奇怪的第二件事:读取 8 个字节,数据在我的缓冲区中正确,直到最后一个字节,最后一个字节是 0xFF,应该是 0x00。什么?
PS:已经在 Microchip 提交了一张票,以获得此问题的支持。