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.

CCS/AFE4300EVM-PDK: I want to have SPI communication between AFE4300 EVM board and atemega128

Part Number: AFE4300EVM-PDK
Other Parts Discussed in Thread: AFE4300

Tool/software: Code Composer Studio

I want to use BCM mode and just one channel.

when atemega128 gives AFE4300-EVM board "read ADC"protocol, the AFE4300 replys incorrect result value.

and add an oscilloscope capture photo.

yellow line is MOSI

puple line is MISO

here my code.

please help me

#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define USART_BAUDRATE 500000
#define BAUD_PRESCALE (((F_CPU/(USART_BAUDRATE*16UL)))-1)

#define sbi(PORTX , BitX) PORTX |= (1 << BitX) // 비트 SET 명령 정의
#define cbi(PORTX , BitX) PORTX &= ~(1 << BitX) // 비트 CLEAR 명령 정의

/***************************
AFE4300 register address definitions
****************************/

volatile unsigned char ADDRESS_ADC_DATA_RESULT=0x00; // (Address 0x00, Default 0x0000)
volatile unsigned char ADDRESS_ADC_CONTROL_REGISTER1=0x01; // (Address 0x01, Default 0x01C3)
volatile unsigned char ADDRESS_MISC_REGISTER1=0x02; // (Address 0x02, Default 0x8000)
volatile unsigned char ADDRESS_MISC_REGISTER2=0x03; // (Address 0x03, Default 0x7FFF)
volatile unsigned char ADDRESS_DEVICE_CONTROL1=0x09; // (Address 0x09, Default 0x0000)
volatile unsigned char ADDRESS_ISW_MUX=0x0A; // (Address 0x0A, Default 0x0000)
volatile unsigned char ADDRESS_VSENSE_MUX=0x0B; // (Address 0x0B, Default 0x0000)
volatile unsigned char ADDRESS_IQ_MODE_ENABLE=0x0C; // (Address 0x0C, Default 0x0000)
volatile unsigned char ADDRESS_WEIGHT_SCALE_CONTROL=0x0D; //(Address 0x0D, Default 0x0000)
volatile unsigned char ADDRESS_BCM_DAC_FREQ=0x0E; // (Address 0x0E, Default 0x0000)
volatile unsigned char ADDRESS_DEVICE_CONTROL2=0x0F; // (Address 0x0F, Default 0x0000)
volatile unsigned char ADDRESS_ADC_CONTROL_REGISTER2=0x10; // (Address 0x10, Default 0x0000)
volatile unsigned char ADDRESS_MISC_REGISTER3=0x1A; //(Address 0x1A, Default 0x0000)

volatile char action=0;
volatile char drdyokay = 0;
volatile char a = 0;
volatile int count=0;
volatile char status=0;

volatile char UART_Ready;
volatile char UART_RxChar;
volatile char UART_Buffer;
volatile char UART_ReceivedChar;

ISR(USART0_RX_vect)
{
UART_ReceivedChar = 1;
UART_RxChar = UDR0;
}

ISR(USART0_TX_vect)
{
UART_Ready = 1;

}


void USART_init()
{
DDRE = 0x02;

UCSR0A |= 0b00000000; // Double the USART1 Transmission Speed
UCSR0B = 0b11011000; // RX complete Interrupt enable(bit7), RX,TX enable(bit 4,3)
UCSR0C = 0b00000110; // no parity bit, 1 stop bit, 8bit data

UBRR0H=0x00;
UBRR0L=0x01;
}


void interrupt_init()
{
SREG=0x80;
EICRA = 0x02; // INT0 = falling edge trigger
EIMSK = 0x01; // enable INT0
EIFR = 0xFF; // clear interrupt flag
//인터럽트 전역 허용!
}


void TIMER_Init(void)
{
TIMSK=0x01;
TCCR0=0x05; // clk/128
//TCCR0=0x01;
TCNT0=0x83;
sei();
}


ISR(TIMER0_OVF_vect)
{

if(status>0)
{
if(count==10)
{
action=1;
count=0;
}
else
{
count++;
}
}
TCNT0=0x83; // (16000000/128)/125 = 1000 -> 0.001 sec

}

ISR(INT0_vect) // INT0 interrupt function
{

if(a==0)
{

sbi(PORTA, 0);
a=1;
}
else if(a==1)
{
cbi(PORTA, 0);
a=0;
}


drdyokay=1;

}

void AFE4300_WRITE(unsigned char address,unsigned char high,unsigned char low)
{

cbi(PORTB, 0); // CS = 0
SPDR = address;
while((SPSR&0x80)!=0x80); // transmit complete ?

SPDR = high;
while((SPSR&0x80)!=0x80); // transmit complete ?

SPDR = low;
while((SPSR&0x80)!=0x80); // transmit complete ?
sbi(PORTB, 0); // CS = 1

}


void set_up()
{

AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0x40);
AFE4300_WRITE(ADDRESS_MISC_REGISTER1,0x00,0x00);
AFE4300_WRITE(ADDRESS_MISC_REGISTER2,0xFF,0xFF);
AFE4300_WRITE(ADDRESS_DEVICE_CONTROL1,0x60,0x06);
AFE4300_WRITE(ADDRESS_IQ_MODE_ENABLE,0x00,0x00);
AFE4300_WRITE(ADDRESS_WEIGHT_SCALE_CONTROL,0x00,0x00);
AFE4300_WRITE(ADDRESS_BCM_DAC_FREQ,0x00,0x40); //DAC freq=64KHz
AFE4300_WRITE(ADDRESS_DEVICE_CONTROL2,0x00,0x00);
AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER2,0x00,0x63);
AFE4300_WRITE(ADDRESS_MISC_REGISTER3,0x00,0x30);

}

void measurement(char c_mode)
{
switch (c_mode)
{
case 0: // calibarion off
AFE4300_WRITE(ADDRESS_ISW_MUX, 0x00,0x00);
AFE4300_WRITE(ADDRESS_VSENSE_MUX,0x00,0x00);
break;

case 1: // calibration (R58 99ohm)
AFE4300_WRITE(0x0A,0x01,0x01);
AFE4300_WRITE(0x0B,0x01,0x01);
// AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC3);
break;

case 2: //calibration (R57 949ohm)
AFE4300_WRITE(0x0A,0x02,0x02);
AFE4300_WRITE(0x0B,0x02,0x02);
// AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC3);
break;

case 3: //calibration (R56 699ohm)
AFE4300_WRITE(0x0A,0x02,0x01);
AFE4300_WRITE(0x0B,0x02,0x01);
// AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC3);
break;
}
}


char Datachk(void)
{
if(UART_ReceivedChar!=0)
{
return 1;
}
else
{
return 0;
}
}

char UARTreceive(void)
{
while(!UART_ReceivedChar);
UART_ReceivedChar = 0;
return UART_RxChar;
}

void UARTsend(char TxData)
{

while(!UART_Ready);
UART_Ready = 0;
UDR0=TxData;
}

unsigned char SPI_transfer(unsigned char Data)
{
SPDR = Data; // Data 송신
while(!(SPSR & _BV(SPIF))); // 송신 확인
return SPDR; // 수신 받은 데이터 반환
}


void ADC_READ() // read a byte
{

unsigned char high=0, low=0;
cbi(PORTB, 0); // CS = 1
SPDR = 0x20; //read ADCresister
while((SPSR & 0x80) == 0x00); // transmit complete ?

SPDR=0x00;
while((SPSR & 0x80) == 0x00);
high=SPDR;

SPDR=0x00;
while((SPSR & 0x80) == 0x00);
low = SPDR;
sbi(PORTB, 0);

UARTsend(high);
UARTsend(low);
}

void cailbration() // calibaration
{
measurement(1);
}

void Act(char cmd)
{
switch(cmd)
{
case 0x01: action=1; measurement(3); break; // Start Measurement
case 0x10: action=0; break; // Stop Measurement
case 0x0C: cailbration();break; // setting calibration
}
}


void MAIN_Init(void)
{
cbi(DDRE, 0); // RXD0 핀 입력으로 설정
sbi(DDRE, 1); // TXD0 핀 출력으로 설정

sbi(DDRB, 0); // /SS 출력으로 설정
sbi(DDRB, 1); // SCK 출력으로 설정
sbi(DDRB, 2); // MOSI 출력으로 설정
cbi(DDRB, 3); // MISO 입력으로 설정

//sbi(PORTB, 0); // /SS 1 입력


sbi(DDRA, 0); //test핀 설정
cbi(PORTA, 0);

SPSR = 0;
//SPCR = 85;
SPCR= 0x54;
}


int value = 0;

int main(void){

char command;

USART_init();
MAIN_Init();
TIMER_Init();
interrupt_init();

UART_Ready = 1;
set_up();

status = 1;


for(;;){



if(action==1)
{

action=0;
}


if(Datachk())
{
command = UARTreceive();
Act(command);
ADC_READ();

}

}
}

  • Hi Dongjun,

    Can you please verify the SPI write first?
    Observe the voltage at VLDO after and before enabling weight scale signal chain.

    Regards,
    Prabin
  • Hi Prabin
    Thanks for your reply.
    As in the picture above, SPI write was verified.

    and The voltage of VLD0 is 1.7V.

    my code is right?
  • Hi Dongjun,

    That's good news.
    How about reading any other register ( except ADC output)?
    Also note that once you read the register you have to write it back.

    Regards,
    Prabin
  • I read a register value other than ADC OUT.

    But it was not the register value I wrote.

    I don't think there is a problem with the code that writes the value to the register.

    This is my code.

    void AFE4300_WRITE(unsigned char address,unsigned char high,unsigned char low)
    {
    cbi(PORTB, 0); // CS = 0

    address = address & 0x1F; 

    SPI_transfer(address);
    SPI_transfer(high);
    SPI_transfer(low);

    sbi(PORTB, 0); // CS = 1

    }

  • Hi Dongjun,

    Since you have already verified the SPI write by observing the VLDO, I think the problem is in SPI read function.
    Can you please probe and verify the SPI lines during the read operation is as same as mentioned in the datasheet?

    Regards,
    Prabin

  • Thanks to your help, SPI communication is possible.

    but I have additional questions.

    I try to do a two-point calibration.

    and I read the resistors R56 (700 ohm) and R57 (950), but the expected values ​​are different.

    There are typical values ​​in the datasheet, but the measured values ​​are very low.

    R56 : high 0x00

              low  0xd4

    R57 : high 0x00

              low  0x20

    void calibration(char c_mode)
    {
    switch (c_mode)
    {
    case 0: // calibarion off
    AFE4300_WRITE(0x0A, 0x00,0x00);
    AFE4300_WRITE(0x0B,0x00,0x00);
    break;

    case 1: // calibration (R58 100ohm)
    AFE4300_WRITE(0x0A,0x01,0x01);
    AFE4300_WRITE(0x0B,0x01,0x01);

    break;

    case 2: //calibration (R57 950ohm)
    AFE4300_WRITE(0x0A,0x02,0x02);
    AFE4300_WRITE(0x0B,0x02,0x02);

    break;

    case 3: //calibration (R56 700ohm)
    AFE4300_WRITE(0x0A,0x02,0x01);
    AFE4300_WRITE(0x0B,0x02,0x01);

    break;

    case 4: //calibration (R59 200ohm)
    AFE4300_WRITE(0x0A,0x01,0x02);
    AFE4300_WRITE(0x0B,0x01,0x02);

    break;
    }
    }

  • Hi Dongjun,

    Have you inserted any series resistors in between DACOUT and DAC_FLT_IN?
    You can measure the voltage between OUTP_FLT and OUTM_FLT pins to validate the ADC output .
    Do you have data with the AFE4300EVM when it was controlled by the on-board MSP430?

    Regards,
    Prabin
  • I am using the AFE4300EVM with the MMB3 removed.(used Atmega128)
    and I want to measure the BCM in single-shot mode.
    Is there a problem with the register setting?

    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC0);
    AFE4300_WRITE(ADDRESS_MISC_REGISTER1,0x00,0x00);
    AFE4300_WRITE(ADDRESS_MISC_REGISTER2,0xFF,0xFF);
    AFE4300_WRITE(ADDRESS_DEVICE_CONTROL1,0x60,0x06);
    AFE4300_WRITE(ADDRESS_IQ_MODE_ENABLE,0x00,0x00);
    AFE4300_WRITE(ADDRESS_WEIGHT_SCALE_CONTROL,0x00,0x00);
    AFE4300_WRITE(ADDRESS_BCM_DAC_FREQ,0x00,0x40); //DAC freq=64KHz
    AFE4300_WRITE(ADDRESS_DEVICE_CONTROL2,0x00,0x00);
    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER2,0x00,0x63);
    AFE4300_WRITE(ADDRESS_MISC_REGISTER3,0x00,0x30);
  • #define F_CPU 16000000UL

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>

    #define USART_BAUDRATE 500000
    #define BAUD_PRESCALE (((F_CPU/(USART_BAUDRATE*16UL)))-1)

    #define sbi(PORTX , BitX) PORTX |= (1 << BitX) // 비트 SET 명령 정의
    #define cbi(PORTX , BitX) PORTX &= ~(1 << BitX) // 비트 CLEAR 명령 정의

    /***************************
    AFE4300 register address definitions
    ****************************/

    volatile unsigned char ADDRESS_ADC_DATA_RESULT=0x00; // (Address 0x00, Default 0x0000)
    volatile unsigned char ADDRESS_ADC_CONTROL_REGISTER1=0x01; // (Address 0x01, Default 0x01C3)
    volatile unsigned char ADDRESS_MISC_REGISTER1=0x02; // (Address 0x02, Default 0x8000)
    volatile unsigned char ADDRESS_MISC_REGISTER2=0x03; // (Address 0x03, Default 0x7FFF)
    volatile unsigned char ADDRESS_DEVICE_CONTROL1=0x09; // (Address 0x09, Default 0x0000)
    volatile unsigned char ADDRESS_ISW_MUX=0x0A; // (Address 0x0A, Default 0x0000)
    volatile unsigned char ADDRESS_VSENSE_MUX=0x0B; // (Address 0x0B, Default 0x0000)
    volatile unsigned char ADDRESS_IQ_MODE_ENABLE=0x0C; // (Address 0x0C, Default 0x0000)
    volatile unsigned char ADDRESS_WEIGHT_SCALE_CONTROL=0x0D; //(Address 0x0D, Default 0x0000)
    volatile unsigned char ADDRESS_BCM_DAC_FREQ=0x0E; // (Address 0x0E, Default 0x0000)
    volatile unsigned char ADDRESS_DEVICE_CONTROL2=0x0F; // (Address 0x0F, Default 0x0000)
    volatile unsigned char ADDRESS_ADC_CONTROL_REGISTER2=0x10; // (Address 0x10, Default 0x0000)
    volatile unsigned char ADDRESS_MISC_REGISTER3=0x1A; //(Address 0x1A, Default 0x0000)

    volatile char action=0;
    volatile char drdyokay = 0;
    volatile char a = 0;
    volatile int count=0;
    volatile char status=0;

    volatile char UART_Ready;
    volatile char UART_RxChar;
    volatile char UART_Buffer;
    volatile char UART_ReceivedChar;



    ISR(USART0_RX_vect)
    {
    UART_ReceivedChar = 1;
    UART_RxChar = UDR0;
    }

    ISR(USART0_TX_vect)
    {
    UART_Ready = 1;

    }




    void USART_init()
    {
    DDRE = 0x02;

    UCSR0A |= 0b00000000; // Double the USART1 Transmission Speed
    UCSR0B = 0b11011000; // RX complete Interrupt enable(bit7), RX,TX enable(bit 4,3)
    UCSR0C = 0b00000110; // no parity bit, 1 stop bit, 8bit data

    UBRR0H=0x00;
    UBRR0L=0x01;
    }


    void interrupt_init()
    {
    SREG=0x80;
    EICRA = 0x02; // INT0 = falling edge trigger
    EIMSK = 0x01; // enable INT0
    EIFR = 0xFF; // clear interrupt flag

    }


    void TIMER_Init(void)
    {
    TIMSK=0x01;
    TCCR0=0x05; // clk/128
    TCNT0=0x83;
    sei();
    }


    ISR(TIMER0_OVF_vect)
    {

    if(status>0)
    {
    if(count==10000)
    {
    action=1;
    count=0;
    }
    else
    {
    count++;
    }
    }
    TCNT0=0x83;

    }



    ISR(INT0_vect) // INT0 interrupt function
    {

    drdyokay=1;

    }

    unsigned char SPI_transfer(unsigned char Data)
    {
    SPDR = Data; // Data 송신
    while(!(SPSR & _BV(SPIF))); // 송신 확인
    return SPDR; // 수신 받은 데이터 반환
    }


    void AFE4300_WRITE(unsigned char address,unsigned char high,unsigned char low)
    {

    address = address & 0x1F;
    SPDR = address;
    while((SPSR&0x80)!=0x80); // transmit complete ?

    SPDR = high;
    while((SPSR&0x80)!=0x80); // transmit complete ?

    SPDR = low;
    while((SPSR&0x80)!=0x80); // transmit complete ?

    }


    void set_up()
    {

    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC0);
    AFE4300_WRITE(ADDRESS_MISC_REGISTER1,0x00,0x00);
    AFE4300_WRITE(ADDRESS_MISC_REGISTER2,0xFF,0xFF);
    AFE4300_WRITE(ADDRESS_DEVICE_CONTROL1,0x60,0x06);
    AFE4300_WRITE(ADDRESS_IQ_MODE_ENABLE,0x00,0x00);
    AFE4300_WRITE(ADDRESS_WEIGHT_SCALE_CONTROL,0x00,0x00);
    AFE4300_WRITE(ADDRESS_BCM_DAC_FREQ,0x00,0x40); //DAC freq=64KHz
    AFE4300_WRITE(ADDRESS_DEVICE_CONTROL2,0x00,0x00);
    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER2,0x00,0x63);
    AFE4300_WRITE(ADDRESS_MISC_REGISTER3,0x00,0x30);

    }

    void calibration(char c_mode)
    {
    switch (c_mode)
    {
    case 0: // calibarion off
    AFE4300_WRITE(0x0A,0x00,0x00);
    AFE4300_WRITE(0x0B,0x00,0x00);
    break;

    case 1: // calibration (R58 99ohm)
    AFE4300_WRITE(0x0A,0x01,0x01);
    AFE4300_WRITE(0x0B,0x01,0x01);
    break;

    case 2: //calibration (R59 196ohm)
    AFE4300_WRITE(0x0A,0x01,0x02);
    AFE4300_WRITE(0x0B,0x01,0x02);
    break;

    case 3: //calibration (R56 699ohm)
    AFE4300_WRITE(0x0A,0x02,0x01);
    AFE4300_WRITE(0x0B,0x02,0x01);
    break;

    case 4: //calibration (R57 949ohm)
    AFE4300_WRITE(0x0A,0x02,0x02);
    AFE4300_WRITE(0x0B,0x02,0x02);
    break;

    case 5:
    break;
    }
    }


    char Datachk(void)
    {
    if(UART_ReceivedChar!=0)
    {
    return 1;
    }
    else
    {
    return 0;
    }
    }

    char UARTreceive(void)
    {
    while(!UART_ReceivedChar);
    UART_ReceivedChar = 0;
    return UART_RxChar;
    }

    void UARTsend(char TxData)
    {
    while(!UART_Ready);
    UART_Ready = 0;
    UDR0=TxData;
    }

    void register_READ(unsigned char address) // read a byte
    {

    unsigned char high=0, low=0;

    address = address & 0x1F; //Last 5 bits specify address
    address = address | 0x20; //First 3 bits need to be 001 for read opcode

    SPI_transfer(address);
    high=SPI_transfer(0x00);
    low=SPI_transfer(0x00);

    UARTsend(high);
    UARTsend(low);
    }



    void ADC_READ() // read a byte
    {

    unsigned char high=0, low=0;

    SPDR = 0x20; //read ADCresister
    while((SPSR & 0x80) == 0x00); // transmit complete ?

    SPDR=0x00;
    while((SPSR & 0x80) == 0x00);
    high=SPDR;

    SPDR=0x00;
    while((SPSR & 0x80) == 0x00);
    low = SPDR;

    UARTsend(high);
    UARTsend(low);
    }

    void Act(char cmd)
    {
    switch(cmd)
    {
    case 0x01: calibration(1); break; // Start Measurement
    case 0x02: calibration(2); break; // Start Measurement
    case 0x03: calibration(3); break; // Start Measurement
    case 0x04: calibration(4); break; // Start Measurement
    case 0x10: break; // Stop Measurement
    }
    }


    void MAIN_Init(void)
    {
    cbi(DDRE, 0); // RXD0 핀 입력으로 설정
    sbi(DDRE, 1); // TXD0 핀 출력으로 설정

    sbi(DDRB, 0); // /SS 출력으로 설정
    sbi(DDRB, 1); // SCK 출력으로 설정
    sbi(DDRB, 2); // MOSI 출력으로 설정
    cbi(DDRB, 3); // MISO 입력으로 설정

    sbi(PORTB, 0); // /SS 1 입력


    sbi(DDRA, 0); //test핀 설정
    cbi(PORTA, 0);

    SPSR = 0;
    SPCR= 0x57;
    }
    int value = 0;

    int main(void){

    char command;

    MAIN_Init();
    USART_init();
    TIMER_Init();
    interrupt_init();

    UART_Ready = 1;

    cbi(PORTB, 0); // /SS 0 입력
    set_up();


    for(;;){


    if(action==1)
    {
    action=0;
    }


    if(Datachk())
    {
    //command = UARTreceive();
    //Act(command);

    command = UARTreceive();
    calibration(1);
    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC0);
    while(drdyokay==0);
    drdyokay=0;
    register_READ(ADDRESS_ADC_DATA_RESULT);
    calibration(2);
    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC0);
    while(drdyokay==0);
    drdyokay=0;
    register_READ(ADDRESS_ADC_DATA_RESULT);
    calibration(3);
    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC0);
    while(drdyokay==0);
    drdyokay=0;
    register_READ(ADDRESS_ADC_DATA_RESULT);
    calibration(4);
    AFE4300_WRITE(ADDRESS_ADC_CONTROL_REGISTER1,0xC1,0xC0);
    while(drdyokay==0);
    drdyokay=0;
    register_READ(ADDRESS_ADC_DATA_RESULT);

    }

    /*
    if(drdyokay==1)
    {
    register_READ(ADDRESS_ADC_DATA_RESULT);
    drdyokay=0;

    //sbi(PORTA, 0);

    }

    */

    }
    }
  • Hello,

    I will be closing this thread due to inactivity, if you have further questions feel free to ask a new question. Thanks