2019-10-17 01:34 PM
Hello having a bit of a problem and was wondering if anyone here could spot what I am doing wrong.
I am interfacing to an Analog device part ADE7878 using HSDC interface. The datasheet for this device can be found here http://www.autex.spb.su/ad/ADE7878.pdf
Data sent from the ADE7878 is enclosed in an active low SS/HSA signal cycle.
The problem I am experiencing is that on the first ever capture I can see that
all 16 32-bit register sent by the ADE7878 are caputured by the STM32H750
and consistent with the trace from the logic analyser.
From the second capture cycle onward the first register always reads as zero and
and then the data from the ADE registers.
Example
Cycle 1
Logic Analyser: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
STM32 reads: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
Cycle 2 (onward)
Logic Analyser: a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p
STM32 reads: 0,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o
Any suggestions on what configuration needs changing. I can find a work around
by swallowing the first capture and read the last register in the
"if ( (isr & SPI_SR_EOT ) == SPI_SR_EOT )" block but I don't find this very neat
any suggestions is well come.
Below is the code snippet of what I am doing
#define HSDC_MAX_REG 16
#define MAX_TRACE_ENTRY 100
extern SPI_HandleTypeDef hspi2;
typedef struct hsdc_registers_struct
{
uint32_t IAWV, VAWV, IBWV, VBWV, ICWV, VCWV, INWV, AVA,
BVA, CVA, AWATT, BWATT, CWATT, AVAR, BVAR, CVAR;
}hsdc_registers_t;
class HSDC;
{
public:
int size(); // returns the number of item in the buf
void insert(hsdc_registers_t* src); // insert an item in the buf
void extract(hsdc_registers_t* dst);// extracts an item from the buffer
private:
hsdc_registers_t buf[MAX_TRACE_ENTRY];
int rear,front,count;
}
HSDC hsdc;
void thread()
{
SPI2_InterruptEnable();
while (1)
{
if (hsdc.size())
{
hsdc_registers_t hsdc_registers;
hsdc.extract(&hsdc_registers);
HAL_UART_Transmit(&huart3, (uint8_t*)&hsdc_registers, sizeof (hsdc_registers_t), HAL_MAX_DELAY);
}
}
}
void SPI2_InterruptEnable()
{
MODIFY_REG(hspi2.Instance->CR2, SPI_CR2_TSIZE, HSDC_MAX_REG);
__HAL_SPI_ENABLE(&hspi2);
__HAL_SPI_ENABLE_IT(&hspi2,
(SPI_IT_EOT | SPI_IT_RXP | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF | SPI_IT_TSERF));
}
void SPI2_IRQHandler(void)
{
static int count = 0;
static uint32_t rxbuf[HSDC_MAX_REG];
SPI_TypeDef* instance = hspi2.Instance;
uint32_t isr = instance->SR;
if ( (isr & SPI_SR_EOT ) == SPI_SR_EOT )
{
hsdc.insert((hsdc_registers_t*)rxbuf);
instance->IFCR |= SPI_FLAG_EOT;
count = 0;
}
if ( (isr & SPI_SR_TXTF ) == SPI_SR_TXTF )
{
instance->IFCR |= SPI_FLAG_TXTF;
}
if ( (isr & SPI_SR_UDR ) == SPI_SR_UDR )
{
instance->IFCR |= SPI_FLAG_UDR;
}
if ( (isr & SPI_SR_OVR ) == SPI_SR_OVR )
{
instance->IFCR |= SPI_FLAG_OVR;
}
if ( (isr & SPI_SR_TIFRE ) == SPI_SR_TIFRE )
{
instance->IFCR |= SPI_FLAG_FRE;
}
if ( (isr & SPI_SR_MODF ) == SPI_SR_MODF )
{
instance->IFCR |= SPI_FLAG_MODF;
}
if ( (isr & SPI_SR_TSERF ) == SPI_SR_TSERF )
{
instance->IFCR |= SPI_FLAG_TSERF;
}
if ( (isr & SPI_SR_SUSP ) == SPI_SR_SUSP )
{
instance->IFCR |= SPI_FLAG_SUSP;
}
if ( (isr & SPI_SR_RXP ) == SPI_SR_RXP )
{
rxbuf[count++] = instance->RXDR;
}
}
2019-10-17 10:46 PM
So, the STM32 SPI is master? Isn't that 0 from end of previous transaction? Don't you see extra SCK clocks after the end of transaction?
Rx-only in the STM32 SPI is notoriously hard to handle as it output clocks immediately after enable and won't stop until disable. I don't know whether this has changed somehow in the 'H7 and won't study it now, but the usual advice is to not use the Rx-only mode of SPI, use normal duplex where you have full control over the clocks - you don't need to bring out MOSI to a pin.
JW
2019-10-17 11:55 PM
Hi JW,
The STM32 is not the master but operating as an SPI Slave device (Rx Only Mode). The clock to the STM32 is driven from the ADE7878 chip.
The 0 seen is not from the previous transaction as it can't be seen on the logic analyser, in fact the last 2 register data sent from the ADE is 0xFFFFFFFF.
There is a burst of 16 separate 32-bits clock generated by the ADE device and for each clock one can see the corresponding register data on the logic analyser and consequently within the STM32 receive buffer.
As mentioned in my previous post the problem seems to be something to do with the internal STM32 RXDR reading an extra zero when NSS pin goes low the second time.
Regards
onio