主题中讨论的其他器件: ADS1292
工具与软件:
您好、 Fellows、
我认为有一个新问题、我认为这是 SPI 中的时钟通信问题。
或许、可以帮我解决这个问题、下面我分享了使用数字分析仪观察过程中拍摄的一些图片。


通信似乎不同步、因此这些值未正确显示。 为了实现通信、我使用 SMCLK 和12MHz、该 SMCLK 源自时钟系统、频率为24MHz 的 MCLK。 通过这种方式 、SPI 时钟为500kHz。
有人可以帮我吗?
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具与软件:
您好、 Fellows、
我认为有一个新问题、我认为这是 SPI 中的时钟通信问题。
或许、可以帮我解决这个问题、下面我分享了使用数字分析仪观察过程中拍摄的一些图片。


通信似乎不同步、因此这些值未正确显示。 为了实现通信、我使用 SMCLK 和12MHz、该 SMCLK 源自时钟系统、频率为24MHz 的 MCLK。 通过这种方式 、SPI 时钟为500kHz。
有人可以帮我吗?
您好、Ryan、
感谢您的快速响应、我与您分享 一帧的捕获。 
我阅读了所有常见问题解答、对我来说、代码中似乎存在 加电或 通信计时问题。 此外 、我共享用于与 AFE 进行通信的代码、该器件应在 AVDD = 3V 且 DVDD = 1.8V 的条件下工作
main.c
#include <msp432.h>
#include <stdio.h>
#include <stdbool.h>
#include "cs.h"
#include "uart.h"
#include "spi.h"
#include "delay.h"
#include "ads1292r.h"
#define LOW 0x00
#define HIGH 0x01
uint32_t DCO_FREQ;
uint8_t read_ADS1292R = 0;
extern uint8_t SPI_TX_BUFF[SPI_TX_BUFF_SIZE];
extern uint8_t SPI_RXBUFF[SPI_RXBUFF_SIZE], SPI_RX_COUNT, SPI_RX_EXP_COUNT;
volatile bool ADS1292R_RECEIVED_DATA = false;
unsigned long uecgTemp = 0;
signed long secgTemp = 0;
volatile signed long s32DaqVals[8];
uint8_t DataPacket[16];
uint8_t dataLength = 8;
void sendString(char *str);
void set_uart(void);
void set_gpio(void);
void processData(void);
void main(void){
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
uint16_t i;
set_gpio(); /*INITIALIZE GPIO*/
clockSystem(FREQ_24_MHz); /*INITIALIZE CLOCK SYSTEM*/
set_uart(); /*INITIALIZE UART*/
set_spi(); /*INITIALIZE SPI*/
set_ads1292r(); /*INITIALIZE ADS1292R*/
/*ENABLE GLOBAL INTERRUPT*/
NVIC->ISER[1] = 1 << ((PORT2_IRQn) & 31); /*ENABLE PORT2 INTERRUPT IN NVIC MODULE*/
NVIC->ISER[0] = 1 << ((EUSCIB0_IRQn) & 31); /*ENABLE EUSCI_B0 INTERRUPT IN NVIC MODULE*/
__enable_irq();
while(1){
/*VERIFY IF PIN IS LOW*/
while ((P2->IN & BIT3) == 0x00) {
read_ADS1292R = true;
//setDeviceOutBytes();
}
if(ADS1292R_RECEIVED_DATA == true){
}
}
}
ads1292.c
uint8_t SPI_TX_BUFF[SPI_TX_BUFF_SIZE];
uint8_t SPI_RXBUFF[SPI_RXBUFF_SIZE], SPI_RX_COUNT = 0, SPI_RX_EXP_COUNT = 0;
long ADS1292_ECG_DATA_BUFFER[6];
extern uint8_t read_ADS1292R;
extern volatile bool ADS1292R_RECEIVED_DATA;
static volatile uint8_t RX_Data = 0;
void set_ads1292r(void) {
drdy_interruptsADS();
_delay(1, 's');
resetADS();
_delay(100, 'm');
start_disableADS(); // Set START pin to LOW
start_enableADS(); // Set START pin to HIGH
start_disableADS(); // Set START pin to LOW
hard_stopADS();
_delay(10, 'm');
start_data_convertionCMD();
soft_stopADS();
_delay(50, 'm');
/*READ DATA IN CONTINUOUS MODE IS THE DEVICE DEFAULT MODE*/
/*THE DEVICE GOES TO THIS MODE ON POWER-UP, BY DEFAULT*/
stop_read_dataContinuous();
_delay(300, 'm');
/*INITIATE REGISTERS*/
read_regsADS(0x00);
register_writeADS(ADS1292_REG_CONFIG1, 0x02);
_delay(10, 'm');
register_writeADS(ADS1292_REG_CONFIG2, 0xE8);
_delay(10, 'm');
register_writeADS(ADS1292_REG_LOFF, 0xF0);
_delay(10, 'm');
register_writeADS(ADS1292_REG_CH1SET, 0x00);
_delay(10, 'm');
register_writeADS(ADS1292_REG_CH2SET, 0x00);
_delay(10, 'm');
register_writeADS(ADS1292_REG_RLDSENS, 0xAC);
_delay(10, 'm');
register_writeADS(ADS1292_REG_LOFFSENS, 0x0F);
_delay(10, 'm');
register_writeADS(ADS1292_REG_RESP1, 0xEA);
_delay(10, 'm');
register_writeADS(ADS1292_REG_RESP2, 0x07);
_delay(10, 'm');
start_read_dataContinuous();
_delay(10, 'm');
// start_enableADS();
}
void resetADS(void) {
P2->OUT |= BIT6; // Drive reset pin HIGH
_delay(100, 'm');
P2->OUT &= ~(BIT6); // Drive reset pin LOW
_delay(100, 'm');
P2->OUT |= BIT6; // Drive reset pin HIGH
_delay(100, 'm'); // Hold reset for 17 milliseconds
}
void drdy_interruptsADS(void) {
P2->DIR &= ~(BIT3); /*SET P2.3 DRDY TO INPUT*/
P2->OUT &= ~(BIT3);
P2->REN |= BIT3;
P2->SEL0&= ~(BIT3);
P2->SEL1&= ~(BIT3);
P2->IE |= BIT3;
P2->IES &= ~(BIT3);
P2->IFG &= ~(BIT3);
}
void clock_selectADS(uint8_t clock_in) {
if (clock_in == 1) {
P2->OUT |= BIT4; // Choose internal clock
} else {
P2->OUT &= ~(BIT4); // Choose external clock
}
}
void start_enableADS(void) {
P2->OUT |= BIT5; // Set START pin HIGH
_delay(20, 'm'); // Wait for 25 microseconds
}
void start_disableADS(void) {
P2->OUT &= ~BIT5; // Set START pin LOW
_delay(20, 'm'); // Wait for 17 microseconds
}
void chip_enableADS(void) {
P3->OUT |= BIT0; // Set CS pin HIGH
}
void chip_disableADS(void) {
P3->OUT &= ~BIT0; // Set CS pin LOW
}
void hard_stopADS(void) {
P2->OUT &= ~BIT5; // Set START pin LOW
_delay(35, 'm'); // Wait for 35 milliseconds
}
void start_data_convertionCMD(void) {
spi_transmit(START_);
}
void stop_read_dataContinuous(void) {
spi_transmit(SDATAC);
}
void start_read_dataContinuous(void) {
spi_transmit(RDATAC);
}
void soft_stopADS(void) {
spi_transmit(STOP_);
}
static void spi_transmit(uint8_t data) {
chip_disableADS();
_delay(1, 'm');
chip_enableADS();
_delay(1, 'm');
chip_disableADS();
EUSCI_B0->TXBUF = data;
while (EUSCI_B0->STATW & EUSCI_B_STATW_BBUSY);
_delay(2, 'm');
chip_enableADS();
}
static uint8_t spi_receive(void) {
EUSCI_B0->TXBUF = 0x00; // Send dummy byte to receive data
while (EUSCI_B0->STATW & EUSCI_B_STATW_BBUSY);
return EUSCI_B0->RXBUF;
}
void register_writeADS(uint8_t WRITE_ADDRESS, uint8_t DATA) {
// Apply bit masks based on register address
switch (WRITE_ADDRESS) {
case 1:
DATA &= 0x87;
break;
case 2:
DATA &= 0xFB;
DATA |= 0x80;
break;
case 3:
DATA &= 0xFD;
DATA |= 0x10;
break;
case 7:
DATA &= 0x3F;
break;
case 8:
DATA &= 0x5F;
break;
case 9:
DATA |= 0x02;
break;
case 10:
DATA &= 0x87;
DATA |= 0x01;
break;
case 11:
DATA &= 0x0F;
break;
default:
break;
}
SPI_TX_BUFF[0] = WRITE_ADDRESS | WREG;
SPI_TX_BUFF[1] = 0;
SPI_TX_BUFF[2] = DATA;
chip_disableADS();
_delay(1, 'm');
chip_enableADS();
_delay(1, 'm');
chip_disableADS();
_delay(1, 'm');
// Transmit command
spi_transmit(SPI_TX_BUFF[0]);
spi_transmit(SPI_TX_BUFF[1]);
spi_transmit(SPI_TX_BUFF[2]);
}
uint8_t read_regsADS(uint8_t READ_ADDRESS) {
SPI_TX_BUFF[0] = READ_ADDRESS | RREG;
SPI_TX_BUFF[1] = 0;
chip_disableADS();
_delay(1, 'm');
chip_enableADS();
_delay(1, 'm');
chip_disableADS();
spi_transmit(SPI_TX_BUFF[0]);
spi_transmit(SPI_TX_BUFF[1]);
/*RECEIVE THE RESPONSE*/
uint8_t response = spi_receive();
/*ENSURE THE CHIP IS ENABLED AFTER TRANSACTION*/
chip_enableADS();
return response;
}
void EUSCIB0_IRQHandler(void) {
if (EUSCI_B0->IFG & EUSCI_B_IFG_RXIFG) {
RX_Data = EUSCI_B0->RXBUF;
if (read_ADS1292R == true) {
printf("Waiting for 2...\n");
SPI_RXBUFF[SPI_RX_COUNT++] = RX_Data; // Store data
if (SPI_RX_COUNT > SPI_RX_EXP_COUNT) {
SPI_RX_COUNT = 0;
ADS1292R_RECEIVED_DATA = true; // Set flag to indicate data received
read_ADS1292R = false;
}
}
/* Delay between transmissions for slave to process information */
_delay(50,'u');
}
}
void PORT2_IRQHandler(void) {
if (P2->IFG & BIT3) {
P2->IFG &= ~(BIT3); // Clear the interrupt flag
SPI_RX_COUNT = 0;
EUSCI_B0->TXBUF = 0; // Send dummy byte
EUSCI_B0->IE |= EUSCI_B_IE_RXIE; // Re-enable RX interrupt
}
}
void setDeviceOutBytes(void) {
SPI_RX_EXP_COUNT = 9; // Set the expected byte count
}
SPI.c
您好 Armando:
ADS1292期望 CPOL = 0且 CPHA = 1、因此后沿用于采集数据。 逻辑分析仪捕获结果将前沿显示为捕获边沿。 请在您的逻辑分析仪和控制器设置中检查此配置。
话虽如此、上图中的第一个字节似乎是向地址0x01发送 WREG 命令、但我看不到帧的其余部分(即 NCS 返回高电平时)。 您是否已成功写入寄存器配置并读回已配置的设置?
另一个令人担忧的问题是 MISO 线路、它在高频率切换、比 SCLK 快得多。 请检查此连接。
AVDD = 3V 和 DVDD = 1.8V 没有问题。
此致、
Ryan
尊敬的 Armando:
是否有人将 PCB 上或通过 MCU 的 MISO 线路拉高?
另外、请注意、WREG 命令0x41 0x02意味着您要写入3个连续的寄存器、从地址01h 开始。 在这两个字节之后、您需要跟随要写入每个地址的寄存器数据、所有这些都在同一个 SPI 帧中。 MISO 上的数据不会包含转换结果、直到:
此致、
Ryan