0

I am currently trying to use an ATtiny84 to communicate with an RTC (DS1305) through SPI to make an buzzer vibrate every variable amount of time. I've been trying to set alarm0 on the DS1305. However, the 84 does not "technically" have SPI. It has USI which can be programmed to be like SPI. I was wondering if any of you could review my code/ board connections and let me know if you see any problems. The current problem is that I cannot get any communication going through SPI and I am having trouble finding what the issue could be.

Current board connections:

ATtiny84 | DS1305

MOSI ------ DI

MISO ------ DO

USCLK ---- CLK

Datasheets:

Attiny84

DS1305

Board View

Schematic view

enter image description here

enter image description here

    /*
 * Atmel_Jolt_Code.c
 *
 * Created: 11/28/2018 10:44:30 PM
 * Author : Nick Hulsey
 */ 

#include <avr/io.h>
#define F_CPU 16000000UL
#include <avr/interrupt.h>
#include <util/delay.h> 

//variables for SPI
#define SPI_DDR_PORT DDRA
#define CE_PIN DDA3 //I ADDED *****
#define DO_DD_PIN DDA5  // SHOULD WE 
#define DI_DD_PIN DDA6  // THEM FLIP
#define USCK_DD_PIN DDA4
#define SPI_MODE0 0x00
#define SPI_MODE1 0x04

#define MOTOR_PIN DDA7 //I ADDED *****

void SPI_begin();
void setDataMode(uint8_t spiDataMode);
uint8_t transfer(uint8_t spiData);
void flipLatch(uint8_t on);

int main(void)
{
    SPI_begin();
    setDataMode(SPI_MODE1);
    DDRA |= (1 << MOTOR_PIN);


    //**startup**
    uint8_t status_register = 0x10;
    uint8_t control_register = 0x8F;
    uint8_t control_byte = 0x05;

    uint8_t alarm_registers[] = {0x8A, 0x89, 0x88, 0x87};

    //set control
    flipLatch(1);
    transfer(control_register);
    transfer(0);
    flipLatch(0);

    flipLatch(1);
    transfer(control_register);
    transfer(control_byte);
    flipLatch(0);


    //set alarm:
    for (int i = 0; i < 4; i++){
        flipLatch(1);
        transfer(alarm_registers[i]);
        transfer(0x80); //0b10000000
        flipLatch(0);
    }

    //THIS MIGHT NEED WORK
    //GIMSK |= (1 << PCIE1);//set external interrupt (A1)
    PCMSK0 |= (1 << PCINT1);
    sei();


    while (1) //our main loop
    {
        //reading the flag from the status register
        uint8_t status = transfer(status_register);

        if(status == 0x01){//if alarm 0 has been flagged
            PORTA ^= (1 << MOTOR_PIN);
            _delay_ms(100);
        } 

    }   
}

//if A1 has changed state at all this function will fire
ISR(PCINT1_vect){
    PORTA ^= (1 << MOTOR_PIN);//invert motor power
    _delay_ms(100);
}
void SPI_begin(){
    USICR &= ~((1 << USISIE) | (1 << USIOIE) | (1 << USIWM0));//Turn off these bits
    USICR |= (1 << USIWM0) | (1 << USICS1) |  (1 << USICLK);//Turn on these bits
                            //REVIEW THIS PAGE 128
                            //external,positive edge software clock 
                            //What does this mean
    SPI_DDR_PORT |= 1 << USCK_DD_PIN;   // set the USCK pin as output
    SPI_DDR_PORT |= 1 << DO_DD_PIN;     // set the DO pin as output
    SPI_DDR_PORT |= 1 << CE_PIN;// ******** I ADDED
    SPI_DDR_PORT &= ~(1 << DI_DD_PIN);    // set the DI pin as input

}


void setDataMode(uint8_t spiDataMode)
{
    if (spiDataMode == SPI_MODE1)
        USICR |= (1 << USICS0);
    else
        USICR &= (1 << USICS0);
}

//returns values returned from the IC
uint8_t transfer(uint8_t spiData)
{
    USIDR = spiData;
    USISR = (1 << USIOIF);                // clear counter and counter overflow interrupt flag
    //ATOMIC_BLOCK(ATOMIC_RESTORESTATE)   // ensure a consistent clock period
    //{
        while ( !(USISR & (1 << USIOIF)) ) USICR |= (1 << USITC);
    //} 
    return USIDR;
}


void flipLatch(uint8_t on){ 
    if (on == 1)
        PORTA |= (1 << CE_PIN);
    else
        PORTA &= ~(1 << CE_PIN);


}
Nichos
  • 33
  • 2
  • 9
  • It will be hard to find the problem with so much going on at once. I'd start simple and build up to full working system in small testable steps. Maybe first try hanging an LED off one of the GPIO pins and make sure you can blink it. Next try just bitbanging the SPI connections to read the `seconds` register from the DS1305 and then blink that out on the LED so you know you can actually read registers. Then try writing a byte to a user ram register and reading it back to blink the LED to indicate if it worked. I know this seems like a lot of work, but only a few minutes and guaranteed to work! – bigjosh Nov 29 '18 at 15:58
  • Post back a new question when you hit your first roadblock on the above steps and me and everyone else on SE will be in a much better position to help pinpoint the specific issue - but really if you take the steps you will likely figure it out yourself! – bigjosh Nov 29 '18 at 15:59
  • @bigjosh Thank you for getting back to me! I really appreciate it. I had another look over my code and we are having trouble generating a SPI signal from the attiny84. So my next focus would be to look at the transfer and _begin functions. I think I am having trouble with generating a proper clock signal. – Nichos Nov 29 '18 at 17:10
  • I'd strongly recommend just bitbanging at least to get started. It will only take a couple of minutes to write the code and eliminates all of the complexity around using library code and the unfamiliar hardware. [Here](https://www.cl.cam.ac.uk/teaching/1112/P31/lib/spi.c) is an example of how simple that code can be and very straightforward. Once you can read, and then write, a register than you are home free. "Make it work.... then make it work better". :) – bigjosh Nov 29 '18 at 17:51
  • Hey @bigjosh, I was playing around with the board and code yesterday. I was able to pull some data from the spi lines. I added them to the post, could you tell me what you think of them? For some reason my miso and mosi lines are almost always equal to eachother. – Nichos Nov 30 '18 at 16:03
  • Well if you have a Saleae then everything is easy! :) You need to capture a full transaction that starts with the `CE` line going high and ends with it going low. It is also handy to enable the SPI decoder in the logic analyzer so you don't have to count bits. Send a command to read register 0 (seconds), then wait a couple seconds and read it again. Looking at hose traces will tell all! – bigjosh Nov 30 '18 at 16:33
  • @bigjosh I GOT IT! Turns out for DO and DI are backwards to MOSI and MISO. So I switched the 0 ohm jumpers. We also weren't receiving bytes correctly. it takes two transfer functions to fully receive data (page 8 on clock data sheet). Once we fixed those two issues we got it to pulse every x amount of seconds, minutes, and days. Thank you for all of your help! – Nichos Dec 01 '18 at 04:28
  • It is never just one thing wrong! :) Glad you got it fixed! – bigjosh Dec 01 '18 at 19:15

0 Answers0