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
Ryan、您好!
在微控制器论坛上的各位同事的帮助下、我取得了一些进展。
现在我的 MISO 线似乎更好... 但读数的结果始终相同(0xFF)...
尊敬的 Armando:
是否有人将 PCB 上或通过 MCU 的 MISO 线路拉高?
另外、请注意、WREG 命令0x41 0x02意味着您要写入3个连续的寄存器、从地址01h 开始。 在这两个字节之后、您需要跟随要写入每个地址的寄存器数据、所有这些都在同一个 SPI 帧中。 MISO 上的数据不会包含转换结果、直到:
此致、
Ryan