DRDY PIC18F45K80 до QT1481 - PullRequest
       34

DRDY PIC18F45K80 до QT1481

0 голосов
/ 20 ноября 2018

У меня также есть проблема с DRDY.Мне нужно включить DRDY.Выводы для DRDY - это RD2 и RD5.Они оба являются входными данными.

Вот информация для DRDY.

Вывод DRDY DRDY - это выход с открытым стоком (в режиме SPI) или двунаправленный вывод (в режиме UART) с внутренним подтягиванием от 20 до 50 тыс.резистор.
Большинство сбоев связи являются следствием неправильного соблюдения синхронизации DRDY.Шаг последовательной связи контролируется этим выводом.Использование DRDY имеет решающее значение для успешной связи с QT1481.В режиме UART или SPI хосту разрешено выполнять передачу данных только тогда, когда DRDY вернул высокий уровень.Кроме того, в режиме UART QT1481 задерживает ответы хосту, если хост удерживает DRDY на низком уровне.
После каждой байтовой передачи DRDY понижается после короткой задержки и остается низким, пока QT1481 не будет готов к другой передаче.Короткая задержка происходит до того, как DRDY доведется до низкого уровня, потому что в противном случае QT1481 может быть занят и для его ответа требуется ограниченное время.

DRDY может снижаться только на микросекунды.В течение периода от конца одной передачи до тех пор, пока DRDY не станет низким и снова не достигнет высокого уровня, хост не должен выполнять другую передачу.Следовательно, перед каждой передачей байтов хост должен сначала проверить, что DRDY снова высок.Если хост хочет выполнить байтовую передачу с QT1481, он должен вести себя следующим образом:
1. Подождите не менее 100 мкс после предыдущей передачи (время S5 на рисунке 3-2 на стр. 23: DRDY гарантированно станет низкимдо истечения этих 100 мкс).
2. Подождите, пока DRDY не станет высоким (возможно, уже высоким).
3. Выполните следующую передачу с помощью QT1481.
В большинстве случаев это занимает до 3 мсдля DRDY, чтобы вернуться высоко снова.Однако это время больше для некоторых команд или если включена настройка STS_DEBUG, как показано ниже:
0x01 (загрузка настроек): <20 мс <br>0x02 (калибровка низкого уровня и смещение): <20мс <br>Добавьте 15 мс к вышеуказанному времени, если включена настройка STS_DEBUG.Другие спецификации DRDY:
Мин. Время DRDY низкое: 1 мкс
Макс. Время DRDY низкое после сброса: 100 мс

Временная диаграмма такова: enter image description here

Как это реализовать?

Код, который я написал с моим другом, написан здесь:

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

1 Ответ

0 голосов
/ 20 ноября 2018

Нет.Не просто пишите кучу кода, а затем посмотрите, что он делает.Такой подход к дробовику (или, если вы предпочитаете, спагетти к стене) - пустая трата усилий.

Во-первых, отбросьте все эти макросы.Вместо этого напишите комментарии, которые описывают назначение каждого куска кода, например, первые три назначения в вашей функции SPI_Initialize().

Затем преобразуйте свою спецификацию в псевдокод.Формат не имеет большого значения, просто используйте что-то, что позволит вам сосредоточиться на цели , а не на деталях, как это сделать.

Лист данных говорит, что с SPI есть три выхода из PIC (^ SS, SCK, MOSI на QT1481) и два входа (^ DRDY и MISO на QT1481).Я буду использовать эти имена для линий данных и для их соответствующих имен выводов ввода / вывода на PIC.

Фаза настройки на 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 также есть оборудование (осциллограф), чтобы проверить, работает ли их код.

...