gpt4 book ai didi

c - DRDY PIC18F45K80 至 QT1481

转载 作者:行者123 更新时间:2023-11-30 19:03:49 25 4
gpt4 key购买 nike

我也有 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

时序图是这样的:enter image description here

如何实现?

我和 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com