我也有 DRDY 的问题。我需要包括 DRDY。 DRDY 的引脚是 RD2 和 RD5。它们都是输入。
这是 DRDY 的信息。
DRDY 引脚
DRDY 是一个开漏输出(在 SPI 模式下)或双向引脚(在 UART 模式下),具有内部 20 k – 50 k 上拉电阻
电阻。
大多数通信故障都是由于未能正确遵守 DRDY 时序造成的。
串行通信节奏由该引脚控制。 DRDY 的使用对于与系统的成功通信至关重要
QT1481。在 UART 或 SPI 模式下,仅当 DRDY 返回时才允许主机执行数据传输
高的。此外,在 UART 模式下,如果 DRDY 被主机保持为低电平,QT1481 会延迟对主机的响应。
每次字节传输后,DRDY 在短暂延迟后变低,并保持低电平,直到 QT1481 准备好进行另一个字节传输。
转移。在 DRDY 被驱动为低电平之前会发生短暂的延迟,因为 QT1481 可能很忙并且需要
有限的响应时间。
DRDY 可能只会变低一微秒。从一次传输结束到 DRDY 变为低电平期间
再次回到高电平,主机不应执行另一次传输。因此,在每个字节传输之前,主机
应首先检查 DRDY 是否再次变高。
如果主机想要与 QT1481 执行字节传输,其行为应如下:
1. 在上一次传输后等待至少 100 µs(第 23 页图 3-2 中的时间 S5:保证 DRDY 继续传输)
在此 100 µs 到期之前为低)。
2. 等到 DRDY 为高电平(可能已经为高电平)。
3. 使用QT1481进行下一次传输。
在大多数情况下,DRDY 需要长达 3 ms 的时间才能再次返回高电平。但是,有些命令的时间会更长
或者如果启用了 STS_DEBUG 设置,如下所示:
0x01
(设置加载):<20 毫秒
0x02
(低电平校准和偏移):<20 ms
如果启用了 STS_DEBUG 设置,则在上述时间上增加 15 毫秒。
其他 DRDY 规范:
DRDY 为低电平的最短时间:1 µs
复位后 DRDY 为低电平的最长时间:100 ms
如何实现?
我和 friend 写的代码写在这里:
#include <xc.h>
#include "PIC.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//#include <pic18f45k80.h>
#define MSB 1
#define LSB 0
// SPI PIN CONFIGURATION
#define SCK_TRIS TRISCbits.TRISC3 = 0 ;
#define SDO_TRIS TRISCbits.TRISC5 = 0 ;
#define SDI_TRIS TRISCbits.TRISC4 = 1 ;
#define QTA_SS_TRIS TRISDbits.TRISD4 = 0 ;
#define QTB_SS_TRIS TRISEbits.TRISE2 = 0 ;
#define QTA_SS_LAT_LOW LATDbits.LATD4 = 0 ;
#define QTA_SS_LAT_HIGH LATDbits.LATD4 = 1 ;
#define QTB_SS_LAT_LOW LATEbits.LATE2 = 0 ;
#define QTB_SS_LAT_HIGH LATEbits.LATE2 = 1 ;
#define QTA_DRDY_TRIS TRISDbits.TRISD5 = 1 ;
#define QTB_DRDY_TRIS TRISDbits.TRISD2 = 1 ;
#define QTA_DRDY_LAT_LOW LATDbits.LATD5 = 0 ;
#define QTA_DRDY_LAT_HIGH LATDbits.LAT52 = 1 ;
#define QTB_DRDY_LAT_LOW LATDbits.LAT25 = 0 ;
#define QTB_DRDY_LAT_HIGH LATDbits.LATD2 = 1 ;
#define QTB_DRDY PORTDbits.RD2 ;
#define QTA_DRDY PORTDbits.RD5 ;
// FREQUENCY SELECT
#define _XTAL_FREQ 16000000
// PIN SETUP
void PIN_MANAGER_Initialize(void)
{
/**
LATx registers
*/
LATE = 0x00;
LATD = 0x00;
LATA = 0x00;
LATB = 0b00010000;
LATC = 0x00;
/**
TRISx registers
*/
TRISE = 0x00;
TRISA = 0x08;
TRISB = 0x01;
TRISC = 0b00010000;
TRISD = 0xEF;
PORTC = 0b00010010 ;
/**
ANSELx registers
*/
ANCON0 = 0x00;
ANCON1 = 0x00;
/**
WPUx registers
*/
WPUB = 0x00;
INTCON2bits.nRBPU = 1;
}
// SPI
void SPI_Initialize(void)
{
// SMP Middle; CKE Idle to Active;
SSPSTAT = 0b00000000;
// SSPEN enabled; WCOL no_collision; CKP Idle:High, Active:Low; SSPM FOSC/4; SSPOV no_overflow;
SSPCON1 = 0b00111010;
// SSPADD 0;
SSPADD = 0x00;
ADCON0 = 0 ;
ADCON1 = 0x0F ; //Makes all I/O digital
SCK_TRIS ;
SDO_TRIS ;
SDI_TRIS ;
QTA_SS_TRIS ;
QTB_SS_TRIS ;
QTA_DRDY_TRIS ;
QTB_DRDY_TRIS ;
}
signed char WriteSPI( unsigned char data_out )
{
unsigned char TempVar;
TempVar = SSPBUF; // Clears BF
PIR1bits.SSPIF = 0; // Clear interrupt flag
SSPCON1bits.WCOL = 0; //Clear any previous write collision
SSPBUF = data_out; // write byte to SSPBUF register
if ( SSPCON1 & 0x80 ) // test if write collision occurred
return ( -1 ); // if WCOL bit is set return negative #
else
while( !PIR1bits.SSPIF ); // wait until bus cycle complete
return ( 0 ); // if WCOL bit is not set return non-negative#
}
unsigned char ReadSPI( void )
{
unsigned char TempVar;
TempVar = SSPBUF; // Clear BF
PIR1bits.SSPIF = 0; // Clear interrupt flag
SSPBUF = 0x00; // initiate bus cycle
while(!PIR1bits.SSPIF); // wait until cycle complete
return ( SSPBUF ); // return with byte read
}
unsigned char DataRdySPI( void )
{
if ( SSPSTATbits.BF )
return ( +1 ); // data in SSPBUF register
else
return ( 0 ); // no data in SSPBUF register
}
// SOFTWARE EUART
void out_char(char character, char bit_order){
uint8_t i = 0;
RSOUT = 1 ; // MSB
__delay_ms(1);
RSOUT = 0 ; // START
__delay_us(100);
for (i = 8; i>0; --i){
if (bit_order){ // Bit order determines how you will put the bits, from left to right (MSB) or right to left (LSB)
RSOUT = (character & 0x80) ? 1:0; // in MSB you compare the left-most bit doing an AND with 0x80, and put 1 if true, 0 elsewhere.
character <<= 1; // Shift the character to the left, discrading the bit just sent
} else {
RSOUT = (character & 0x01); // in LSB you compare the right-most bit doing an AND with 0x01, and put 1 if true, 0 else.
character >>= 1; // Shift the character to the right, discrading the bit just sent
}
__delay_us(100);
}
RSOUT = 1 ; // STOP
}
void out_str(char * string, uint8_t len, char bit_order){
uint8_t i = 0;
for (i = 0; i< len; i++){
out_char(string[i], bit_order);
}
}
void SYSTEM_Initialize(void)
{
PIN_MANAGER_Initialize() ;
SPI_Initialize() ;
}
void main(void)
{
SYSTEM_Initialize() ;
while (1)
{
QTB_SS_LAT_LOW ; // Transmit data
char temp ;
WriteSPI(0x0F) ; // Send a byte
while(!DataRdySPI()) ; // wait for a data to arrive
temp = ReadSPI(); // Read a byte from the
QTB_SS_LAT_HIGH ; // Stop transmitting data
__delay_us(100) ;
}
}
最佳答案
没有。不要只是编写一堆代码,然后看看它的作用。这种霰弹枪(或者,如果你愿意的话,也可以说是“意大利面条到墙上”)的方法是浪费精力。
首先,删除所有这些宏。相反,请编写描述每个代码块用途的注释,例如 SPI_Initialize()
函数中的前三个赋值。
接下来,将您的规范转换为伪代码。格式并不重要,只需使用能让您集中精力目的的内容,而不是关注如何做到这一点的细节。
datasheet表示使用 SPI,PIC 有 3 个输出(QT1481 上的 ^SS、SCK、MOSI)和两个输入(QT1481 上的 ^DRDY 和 MISO)。我将使用这些名称作为数据线以及 PIC 上各自的 I/O 引脚名称。
PIC 上的设置阶段应该很简单:
Make ^DRDY an input
Make ^SS an output, set it HIGH
Make SCK an output, set it LOW
Make MOSI an output, set it LOW
Make MISO an input
Set up SPI using SCK, MOSI, MISO
每次传输都是双向的。每当您发送数据时,您也会收到数据。数据表称,零命令保留用于接收多个数据。所以,你只需要一个发送一个字节,同时接收一个字节的函数:
Function SPITransfer(command):
Make sure at least 0.1ms has passed since the previous transfer.
Do:
Nothing
While (^DRDY is LOW)
Set ^SS LOW
response = Transfer(command)
Set ^SS HIGH
Return response
End Function
据我了解,对于 PIC 和正确初始化的硬件 SPI,response = Transfer(command)
行采用 C 语言
SSPBUF = command;
while (!DataRdySPI())
;
response = SSPBUF;
您也可以对它进行位爆炸,在这种情况下它是(伪代码):
response = 0
For bit = 7 down to 0, inclusive:
If (command & 128):
Set MOSI high
Else:
Set MOSI low
End If
Set SCK low
Sleep for a half period
command = command / 2
response = response * 2
If MISO high:
response = response + 1
End If
Set SCK high
Sleep for a half period
End For
但显然硬件 SPI 方法更好。
(当您开始工作时,您可以使用硬件 SPI,而无需定时器中断的等待循环,从而使通信对于 PIC 单片机的“主操作”来说基本上是透明的。这需要稍微不同的方法,使用命令和响应队列(几个字节),但将使 PIC 更容易执行实际工作,而不仅仅是扫描 QT1481。)
重置后,您实际上会发送 0x0F,直到收到 0xF0:
while (SPITransfer(0x0F) != 0xF0)
;
此时,您已经完成了在 C 中实现所需的步骤。OP 还拥有硬件(示波器)来验证其代码是否有效。
关于c - DRDY PIC18F45K80 至 QT1481,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53394889/