Tiny AVR 1-series TWI woes

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using ATTiny412 because I needed an 8-pin with UART and I2C. The UART works fine, I got that going in 5 minutes. The TWI on the other hand is a total prick. I'm talking to an LTC2487 16-bit ADC, a sweet little chip I might add.

The first time I had this trouble it was with the ATTiny814, and I thought the troubles were isolated to that chip because it has a lot in the errata regarding TWI.

I'm using an ATTiny412 now (actually I ordered a 402 and that's what's written on the IC but Atmel Studio says its a 412), and the trouble I'm having is that I can't send I2C Stop sequences. The chip apparently has strobe commands, via register MCTRLB. In theory writing 0x03 to this register will issue a Stop command but it does nothing. I can only talk to the ADC once after power-up and then my I2C bus is jammed. My workaround is to take over the IO and bit-bang a stop sequence. Ugly but it works.

 

I'd like to know if anyone has succeeded in getting the TWI hardware to work as intended?

 

Here are my relevant functions:

void TWI_Init()
{
	TWI0.MBAUD = 0x1F;
	//TWI0.MCTRLA = 1 << TWI_ENABLE_bp | 1<<TWI_SMEN_bp | 1<<TWI_QCEN_bp;
	TWI0.MCTRLB |= TWI_FLUSH_bm;
	TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm);
}

void TWI_Enable()
{
	TWI0.MCTRLA = 1 << TWI_ENABLE_bp | 1<<TWI_SMEN_bp;
	TWI0_MSTATUS |= TWI_BUSSTATE_IDLE_gc;
}

void StopBitDelay()
{
	volatile int d;
	d=25;
	while(d--);
}

void TWI_Stop()
{	
	TWI0_MCTRLA &= ~TWI_ENABLE_bm;	//Disable TWI,
	TWI0_MCTRLB = 0;
	
	//Manual stop sequence :/
	PORTA_OUTCLR = 6;
	PORTA_DIRSET = 6;	//Both low.
	StopBitDelay();
	PORTA_DIRCLR = 4;	//SCL High.
	StopBitDelay();
	PORTA_DIRCLR = 2;	//SDA High.
	StopBitDelay();
}

 

 

And usage:

TWI_Init();
while(1)
{
			TWI_Enable();
			
			TWI_Start(LT2487_ADDR_WRITE);
			TWI_Write(0b10100000);
			TWI_Write(0b10000000);
			
			TWI_Start(LT2487_ADDR_READ);
						
			regData[0] = TWI_Read(1);
			regData[1] = TWI_Read(1);
			regData[2] = TWI_Read(0);
			TWI_Stop();

 

 

I borrowed the bulk of the code from this post: https://www.avrfreaks.net/commen...

The stop function in that post doesn't work for me though.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

trevorg wrote:
TWI_Start(LT2487_ADDR_WRITE); TWI_Write(0b10100000); TWI_Write(0b10000000); TWI_Start(LT2487_ADDR_READ); regData[0] = TWI_Read(1); regData[1] = TWI_Read(1); regData[2] = TWI_Read(0); TWI_Stop();

 

Either your TWI functions are poorly written void functions or your ignoring the return status!

TWI will tell you what is wrong if you listen (ie. read and act on the status)

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Silly question but don't Atmel have TWI support in "Start" or "ASF" for tinyX ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

trevorg wrote:

I'm using an ATTiny412 now (actually I ordered a 402 and that's what's written on the IC but Atmel Studio says its a 412), and the trouble I'm having is that I can't send I2C Stop sequences.

 

402 or 412? Which is it?

 

I think you need to sort that out first before you worry too much about peripherals not working. It would be very rare for a chip to be mis-marked. Likewise, it would be very rare for a (working) chip to return the wrong signature bytes. Not so rare for the compiler to be mis-configured though.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems that while this certificate issue thing is happening no mechanism works for me to post pictures but what I found was:

 

If you visit start.atmel.com, create project, set "I2C=1" and search "tiny412" it seems willing to create a project for you. I'm guessing Atmel/Microchip know the right code to make its I2C work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

trevorg wrote:

 

I'm using an ATTiny412 now (actually I ordered a 402 and that's what's written on the IC but Atmel Studio says its a 412), and the trouble I'm having is that I can't send I2C Stop sequences.

 

 

 

402 or 412? Which is it?

 

This is a bug within Atmel Studio - the ATTINY4x2 series was not properly imported and was *supposed* to have been fixed post build 1645. 

 

As a workaround you can manually correct the signatures in the ATDF files yourself.

You find the ATDF files here: C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATtiny_DFP\1.3.172\atdf

 

The correct signature for ATtiny412 is 0x1e9223. If you edit the file ATtiny412.atdf lines 320:324 should look like this:

        <property-group name="SIGNATURES">

          <property name="SIGNATURE0" value="0x1E"/>

          <property name="SIGNATURE1" value="0x92"/>

          <property name="SIGNATURE2" value="0x23"/>

        </property-group>

 

The correct signature for ATtiny402 is 0x1e9227. If you edit the file ATtiny402.atdf lines 301:305 should look like this:

        <property-group name="SIGNATURES">

          <property name="SIGNATURE0" value="0x1E"/>

          <property name="SIGNATURE1" value="0x92"/>

          <property name="SIGNATURE2" value="0x27"/>

        </property-group>

 

 

I don't have a fix for the TWI issue, but hopefully this will help with the device signature issue.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mmedica wrote:

This is a bug within Atmel Studio - the ATTINY4x2 series was not properly imported and was *supposed* to have been fixed post build 1645. 

 

So the OP likely does have a 402 but thinks they have a 412.

 

I wonder if this explains their problem?

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would be surprised if it does but it's still worth a shot. All this fix does is allow Atmel Studio to properly recognize the chip. Realistically there is no functional issue programming, this is just a front-end recognition issue. I've programmed dozens of ATTiny412's that were recognized as ATTiny402's before implementing this fix and I didn't have any issue besides some slight macro annoyance. The chips are identical besides a few peripheral differences (timers, DAC, etc.) to my knowledge.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This has been fixed in DFP 1.3.229 (http://packs.download.atmel.com/)

 

Go to Tools/Device Pack Manager and update to get the correct IDs.

:: Morten

 

(yes, I work for Atmel, yes, I do this in my spare time, now stop sending PMs)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The TWI registers and functionality are no different between the 402 and the 412. My chip is labelled 402. I'm not concerned about the software bug for now, it's not the source of my problem. Thanks for the heads up though. I encountered the same TWI issue with the 814; there is no way to issue a stop sequence from the TWI hardware.

 

ki0bk wrote:

trevorg wrote:
TWI_Start(LT2487_ADDR_WRITE); TWI_Write(0b10100000); TWI_Write(0b10000000); TWI_Start(LT2487_ADDR_READ); regData[0] = TWI_Read(1); regData[1] = TWI_Read(1); regData[2] = TWI_Read(0); TWI_Stop();

 

Either your TWI functions are poorly written void functions or your ignoring the return status!

TWI will tell you what is wrong if you listen (ie. read and act on the status)

 

Jim

 

 

I don't need that "your functions a poorly written" bullcrap. The functions aren't returning because they get stuck waiting for data from the I2C ADC. I'm competent enough with the debugger and an oscilloscope to work out that the issue is with the hardware not sending stop sequences.

My question remains, has anyone here got the TWI hardware on the 1-series to work properly, without needing to take over the IO at any point?

 

I'm currently working remote and have very poor internet. I can't use the Atmel Start right now because it requires a decent internet connection.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, people have run TWI on a tiny817. There are app notes too.
The Tiny works in a similar way to Xmega. The Xmega has been made for 12 years.
I do not have a Tiny402. I do have Tiny817, Mega4809, various Xmegas.
I would expect the 402 to work exactly the same.
.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

trevorg wrote:
I don't need that "your functions a poorly written" bullcrap. The functions aren't returning because they get stuck waiting for data from the I2C ADC.

Whats "bullcrap" is your use of void functions and ignoring the return status!!!

The reason the "H/W" is not stopping is you purposely ignored the status and are in an illegal I2C state!  

Go back and do the proper actions required for proper I2C protocol and your issues with the h/w will go away.

 

Jim

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

trevorg wrote:
I borrowed the bulk of the code from this post: https://www.avrfreaks.net/commen...

 

Note what I wrote there too:  https://www.avrfreaks.net/commen...

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We get numerous home-made attempts to implement I2C.

 

void functions are the work of the Devil.

 

Confession:   I do not even read void code.

I am happy to help debug non-void functions.

 

If there is someone with real-life ATtiny402 or ATtiny412 chips I can post the tiny417/mega4809 code.

Although Atmel peripherals tend to use the same "Silicon" it is always wise to verify the behaviour on each family.

 

David.

Last Edited: Wed. Jan 9, 2019 - 02:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

mmedica wrote:

trevorg wrote:

 

I'm using an ATTiny412 now (actually I ordered a 402 and that's what's written on the IC but Atmel Studio says its a 412), and the trouble I'm having is that I can't send I2C Stop sequences.

 

 

 

402 or 412? Which is it?

 

This is a bug within Atmel Studio - the ATTINY4x2 series was not properly imported and was *supposed* to have been fixed post build 1645. 

 

As a workaround you can manually correct the signatures in the ATDF files yourself.

You find the ATDF files here: C:\Program Files (x86)\Atmel\Studio\7.0\packs\atmel\ATtiny_DFP\1.3.172\atdf

 

The correct signature for ATtiny412 is 0x1e9223. If you edit the file ATtiny412.atdf lines 320:324 should look like this:

        <property-group name="SIGNATURES">

          <property name="SIGNATURE0" value="0x1E"/>

          <property name="SIGNATURE1" value="0x92"/>

          <property name="SIGNATURE2" value="0x23"/>

        </property-group>

 

The correct signature for ATtiny402 is 0x1e9227. If you edit the file ATtiny402.atdf lines 301:305 should look like this:

        <property-group name="SIGNATURES">

          <property name="SIGNATURE0" value="0x1E"/>

          <property name="SIGNATURE1" value="0x92"/>

          <property name="SIGNATURE2" value="0x27"/>

        </property-group>

 

 

I don't have a fix for the TWI issue, but hopefully this will help with the device signature issue.

 

 

you should stop copy/pasting and refer to my comment from https://www.avrfreaks.net/forum/...

comment #11

 

A small search in the forum will reveal that this issue was already resolved about 5 months ago.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've succeeded in getting the TWI hardware to work in polled mode. I've tested this with an ATTiny402 and an ATTiny416, using a DS3231 and an LTC2487. I've attached the library files for others to refer to.

 

I believe the issues I encountered were due to the Quick Command feature, and attempting to read before waiting for the RIF interrupt flag.

 

#include <avr/io.h>


void TWI_Init(char baud)
{
	TWI0.MBAUD = baud;
	TWI0.MCTRLB |= TWI_FLUSH_bm;
	TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm);
}

void TWI_Enable()
{
	TWI0.MCTRLA = 1<<TWI_SMEN_bp | 1 << TWI_ENABLE_bp;
	TWI0_MSTATUS |= TWI_BUSSTATE_IDLE_gc;
}

char TWI_Start(char addr)
{
	if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) != TWI_BUSSTATE_BUSY_gc)
	{
		TWI0.MCTRLB &= ~(1<<TWI_ACKACT_bp);
		TWI0.MADDR = addr;
		
		if (addr & 1)
		{
			while (!(TWI0_MSTATUS & TWI_RIF_bm));
		}
		else
		{
			while (!(TWI0_MSTATUS & TWI_WIF_bm));
		}
		return TWI0.MSTATUS;
	}
	else
		return TWI0.MSTATUS;
}

char TWI_Read(char * c, char ACKorNACK)
{
	if ((TWI0.MSTATUS & TWI_BUSSTATE_gm)==TWI_BUSSTATE_OWNER_gc)
	{
		while (!(TWI0.MSTATUS & TWI_RIF_bm));
		
		if (ACKorNACK)
		TWI0.MCTRLB &= ~(1<<TWI_ACKACT_bp);	//Send ACK
		else
		TWI0.MCTRLB |= 1<<TWI_ACKACT_bp;	//Send NACK
		
		*c = TWI0.MDATA;
		
		return TWI0.MSTATUS;
	}
	else
		return TWI0.MSTATUS;
}

char TWI_Write(char data)
{
	if ((TWI0.MSTATUS&TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc)
	{
		while (!((TWI0.MSTATUS & TWI_WIF_bm) | (TWI0_MSTATUS & TWI_RXACK_bm)));
		
		TWI0.MDATA = data;
		return TWI0.MSTATUS;
	}
	else
		return TWI0.MSTATUS;
}

void TWI_Stop()
{
	TWI0.MCTRLB |= TWI_MCMD_STOP_gc;
}

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Trevorg, I could use your help to be able to use your code. Could you give me a help? I have some questions about your code.

 

For instance, the order I should call your functions is:

 

TWI_Init(baud);

TWI_Enable();

TWI_Start(addr);

TWI_Read(&sensorVal);

TWI_Stop();

 

If this is correct, where and how you send the Read setting bit?

Last Edited: Thu. Apr 25, 2019 - 08:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

No problem. Here's how I've used it for talking to as DS3231 (ignore the Atmel Start stuff, I just used it for it uart):

#include <atmel_start.h>
#include <stdio.h>

#include "I2C.h"

#define DS3231_ADDR 0xD0


char s,m,h;
volatile char trigger;
volatile char t[10];

ISR(TCA0_OVF_vect)
{
	TCA0_SINGLE_INTFLAGS = 1;	//Clear OVF.
	trigger=1;
}

int main(void)
{
    /* Initializes MCU, drivers and middleware */
    atmel_start_init();
    
    TCA0_SINGLE_CTRLA = 1<<TCA_SINGLE_CLKSEL2_bp | 1<<TCA_SINGLE_ENABLE_bp;
    TCA0_SINGLE_INTCTRL = 1;
    
    sei();
    
    TWI_Init(0x1F);
    TWI_Enable();
    
    puts("Enter Time\r");
    scanf("%8s",t);
    //hh:mm:ss

    TWI_Start(DS3231_ADDR);
    TWI_Write(0b00000000);
    TWI_Write(((t[6]-48)<<4) + ((t[7]-48)&0x0F));
    TWI_Write(((t[3]-48)<<4) + ((t[4]-48)&0x0F));
    TWI_Write(((t[0]-48)<<4) + ((t[1]-48)&0x0F));

    TWI_Stop();

    
    while (1) 
    {
        
        if (trigger)
        {
            TWI_Start(DS3231_ADDR);
            TWI_Write(0b00000000);
            TWI_Start(DS3231_ADDR+1);
            
            TWI_Read(&s,1);
            TWI_Read(&m,1);
            TWI_Read(&h,0);
            
            LED_toggle_level();
            TWI_Stop();
            
            s = (s & 0b00001111) + (s>>4) * 10;
            m = (m & 0b00001111) + (m>>4) * 10;
            h = (h & 0xF) + (h>>4 & 0x3) * 10;
            printf("%d:%d:%d\r\n",h,m,s);
            
            trigger = 0;
        }
    }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks.

 

I am trying to make this work with a Mega4808 but I think I might be missing a couple of things. I have no experience whatsoever with TWI or with this Mega4808 and I might be struggling due to my lack of experience and knowledge.

 

I don't want to make a mess here at your thread with a different subject so I'll send you a PM so that I can understand something!

 

Thanks for replying!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi trevorg and other interested people,

 

I have written a set of Master/Slave I2C drivers for Series 1 chips (should also work for Series 0) with the intent of generating a much more concise and robust code than Michrochip's original version.

 

Please have a look at:

 

https://www.avrfreaks.net/forum/i2c-masterslave-code-attiny-series-1

 

I would be glad if you could help testing and provide feedback. So far I have only used the code for direct connection between two ATtiny processors.