Anviori
Anviori

Reputation: 15

SPI Configuration for a MAX5402 Digital potentiometer using an ATmega16A

    //*----------------------------------
    //*
    //* PROGRAM NAME:
    //* MAX5402_test.asm
    //*
    //* AUTHOR(S):
    //* Wilmer
    //*
    //* Version:
    //* 1.0
    //*
    //* Last Updated:
    //* 12/01/2016
    //*
    //* Target:
    //* ATmega16A
    //*
    //* DESCRIPTION:
    //* This program tests the
    //* MAX5402 Digital POT. using
    //* subroutines MAX5402_SPI_init,
    //* to initialize the ATmega16A's
    //* hardware for SPI, and
    //* subroutine MAX5402_SPI_write
    //* to write an 8-bit value to the
    //* Digital POT to set the position
    //* of the wiper.
    //*
    //* PORTS:
    //*
    //* PORTA:
    //* Not Used.
    //*
    //* PORTB:
    //* PIN5 = MOSI OUPUT
    //* PIN7 = SCK OUTPUT
    //*
    //* PORTC:
    //* J-Tag Pins
    //* PIN0 = CHIP SELECT OUTPUT
    //*
    //* PORTD:
    //* Not Used.
    //*
    //* Version History:
    //* 1.0 Original Version
    //*
    //*----------------------------------

    start:
    //--------Port Configuration--------//
        sbi DDRC, 0 ; Port C, Pin0 as
                     ; output for chip
                     ; select

        ldi r16, $BF ; PORTB as output
        out DDRB, r16; and MISO as Input 

    //----------Initilize Stack----------//
    ldi r16, LOW(RAMEND)
    out SPL, r16
    ldi r16, HIGH(RAMEND)
    out SPH, r16

    //Initialize SPI//
    call MAX5402_SPI_init

    main_loop:
    //Write to the MAX5402//
        ldi r16, $AB
        call MAX5402_SPI_write

        rjmp main_loop

    //*-------------------------------------
    //*
    //* SUBROUTINE NAME:
    //* MAX5402_SPI_init
    //*
    //* AUTHOR(S):
    //* Wilmer
    //*
    //* MODIFIES:
    //* SPCR (SPI Control Register)
    //*
    //* DESCRITION:
    //* Initialize SPI hardware to
    //* communicate with the MAX5402
    //*
    //*-------------------------------------

    MAX5402_SPI_init:
        push r16 ; conserve

    //---Configuring SPI Control Register---//
        ;SPI Interrupt disabled
        ;SPI enabled
        ;MSB transmitted first
        ;Master Selected
        ;Clock Phase & Polarity = 0
        ;SCK Frequency = fosc/128

        ldi r16, (0 << SPIE) | (1 << SPE) | (0 << DORD) | (1 << MSTR) | 
        (0 << CPOL) | (0 << CPHA) | (1 << SPR1) | (1 << SPR0)
        out SPCR,r16 

    //-------Clear SPI Interrupt Flag-------//
        in r16, SPSR
        in r16, SPDR

        pop r16 ; restore
        ret

    //*--------------------------------
    //*
    //* SUBROUTINE NAME:
    //* MAX5402_SPI_write
    //*
    //* AUTHOR(S):
    //* Wilmer
    //*
    //* MODIFIES:
    //* R16
    //*
    //* DESCRITION:
    //* Writes 8-bit value in r16.
    //* This value is used to set the
    //* wiper position of the MAX5402.
    //*
    //*--------------------------------

    MAX5402_SPI_write:
        push r17 ; conserve
        push r18
        push r19

        ldi r19, $FF ; Max Value

        ldi r17, $00    ; select MAX5402
        out PINC, r17

    //----------Send Data to Slave----------//
    send_data:
        out SPDR, r16 ; send data to the
                      ; SPI Data Register

    //-----Wait for Data to be Transfered-----//
    wait:
        sbis SPSR, SPIF
        rjmp wait

        inc r16     ; cpmare r16 to max value
        cpse r16, r19 ; if equal, stop sending data
        rjmp send_data  ; and repeat

        ldi r17, 1    ; de-select MAX5402

        out PINC, R16

        pop r19
        pop r18
        pop r17 ; restore
        ret

Hello, I'm writing this program (a tester) for a MAX5402 Digital potentiometer using the ATmega16A. For this program, the H terminal of the MAX5402 is set to +5V and the terminal L to ground to create a simple potential divider with its output at terminal W (Datasheet for reference: https://datasheets.maximintegrated.com/en/ds/MAX5402.pdf).

What I need to do is write a subroutine that initializes the MCU's SPI hardware for the MAX5402 and another subroutine that sends an 8-bit value to it using r16 (0x00 --> 0xFF). This 8-bit value is used to set the position of the MAX5402's wiper.

My problem is that when using ATMEL STUDIO 7.0 for emulation, the wiper is outputting only 2.5V. No matter what value I send to it, the output does not change.

I've triple checked all physical connections, so the problem has to be in the code; but I cannot figure out what's wrong. Any help is greatly appreciated, Thank you!

Upvotes: 0

Views: 164

Answers (1)

UncleO
UncleO

Reputation: 8449

The MAX5402_SPI_write routine looks peculiar. Why are you sending so many bits over SPI?

From the data sheet, it looks like the device expects: notCS low, one byte over SPI, then notCS high again. You are sending many bytes over SPI in the middle step. This will corrupt the data, and the device will default to the middle value, as you are seeing.

Upvotes: 0

Related Questions