我对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毫秒才能再次返回高电平。但是,某些命令的时间更长
或如果启用了STS_DEBUG设置,如下所示:
0x01(设置加载):0x02(低电平校准和偏移):如果启用了STS_DEBUG设置,则将上述时间增加15 ms。
其他DRDY规格:
最小时间DRDY低:1 µs
复位后最大时间DRDY为低:100毫秒

时序图是这样的:c - DRDY PIC18F45K80至QT1481-LMLPHP

如何实现呢?

我和朋友一起编写的代码写在这里:

#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) ;
     }
}

最佳答案

不。不要只写一堆代码,然后看看它能做什么。这种shot弹枪(或者,如果您愿意,也可以是通心粉)方法是在浪费精力。

首先,删除所有这些宏。而是编写描述每个代码块用途的注释,例如SPI_Initialize()函数中的前三个分配。

接下来,将您的规范转换为伪代码。格式没什么大不了,只是使用一些可以让您专注于目的的东西,而不是专注于如何做的细节。

datasheet表示,对于SPI,有PIC的三个输出(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


每次传输都是双向的。每当您发送数据时,您也会接收数据。数据表说,zero命令保留用于接收多个数据。因此,您只需要一个发送字节并同时接收一个字节的函数:

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微控制器的“主要操作”本质上是透明的。这需要使用命令和响应的方法稍有不同。队列(只有几个字节),但除了扫描QT1481之外,这将使PIC更加轻松地进行实际工作。)

重置后,您实际上发送0x0F,直到返回0xF0为止:

    while (SPITransfer(0x0F) != 0xF0)
        ;


此时,您具有在C中需要实现的步骤。OP还具有用于验证其代码工作的硬件(示波器)。

09-18 08:51