Hi everyone,
I want to program ATtiny 412 with i2c communication protocol. Can anybody please help me how to start with for i2c programming?
Thank you
Hi everyone,
I want to program ATtiny 412 with i2c communication protocol. Can anybody please help me how to start with for i2c programming?
Thank you
Hi gkishor,
Welcome to AVRfreaks,
have you tried to look for examples in ATMEL start ?. The attiny412 MUX table in the datasheet is somehow wrong and contains wrong information..this is the right table:
for a simple application you can start looking in this forum for some codes, you can find it easily by a simple search.
Hi sir,
Thanks for your response. I am trying to understand some example i2c codes. After some study, I have following doubts
1) Which register & bits [SCTRLA, SCTRLB, SDATA], I have to configure to Enable TWI, Enable ack generation
2) Which register & bits are to be checked for, whether the master is requesting data or sending data to slave
3) How to use SDATA register to transmit multiple bytes of data to i2c master
4) How to configure PA3/PA6/PA7 to use them as GPIO pins
figure: TWI registers
I have read the datasheet, regarding configuration of the above registers for i2c slave operation. But I'm not getting proper information from datasheet.
Please help me.
Thank you sir,
have you checked the forum for examples ?
First Wecome to AVRFreaks!
Can you start by telling us what your experience writing micro controller code is?
If this is your first project, you are starting with a fairly complex project. Tell us what your I2C slave will do other then communicating with an I2C master (and tell us what your I2C master is as well).
Jim
Try to start from here:
https://www.avrfreaks.net/forum/...
these application notes descibes most of the functions to get through in ATtiny 1 & 0 series (compatible with your attiny412)
Can anybody please help me how to start with for i2c programming?
avr-libc: Example using the two-wire interface (TWI)
hopefully AVR libc's TWI will work.
/* Two-Wire Interface */ typedef struct TWI_struct { register8_t CTRLA; /* Control A */ register8_t reserved_0x01; register8_t DBGCTRL; /* Debug Control Register */ register8_t MCTRLA; /* Master Control A */ register8_t MCTRLB; /* Master Control B */ register8_t MSTATUS; /* Master Status */ register8_t MBAUD; /* Master Baurd Rate Control */ register8_t MADDR; /* Master Address */ register8_t MDATA; /* Master Data */ register8_t SCTRLA; /* Slave Control A */ register8_t SCTRLB; /* Slave Control B */ register8_t SSTATUS; /* Slave Status */ register8_t SADDR; /* Slave Address */ register8_t SDATA; /* Slave Data */ register8_t SADDRMASK; /* Slave Address Mask */ register8_t reserved_0x0F; } TWI_t;
The avr-libc example code has:
C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\doc\avr-libc\examples\twitest>grep "TW.. " twitest.c
* register to have valid contents while the TWINT bit in TWCR is set.
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
TWSR = 0;
TWBR = 10; /* smallest TWBR value, see note [5] */
TWBR = (F_CPU / 100000UL - 16) / 2;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send start condition */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = sla | TW_WRITE;
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = (eeaddr >> 8); /* 16-bit word address device, send high 8 bits of addr */
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = eeaddr; /* low 8 bits of addr */
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send (rep.) start condition */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = sla | TW_READ;
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWCR = twcr; /* clear int to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send start condition */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = sla | TW_WRITE;
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = (eeaddr>>8); /* 16 bit word address device, send high 8 bits of addr */
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = eeaddr; /* low 8 bits of addr */
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWDR = *buf++;
TWCR = _BV(TWINT) | _BV(TWEN); /* start transmission */
while ((TWCR & _BV(TWINT)) == 0) ; /* wait for transmission */
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
To quote Sesame Street "one of these things is not like the other one" ;-)
EDIT working on the assumption that in an AVR-0/AVR-1 there's got to be a strong chance that TWIn.MCTRLA is going to be accessed at some stage then a google for:
avr twi "MCTRLA"
seems quite fruitful (mainly back here at Freaks in fact)
I have checked some threads in the forum. Still I didn't get specific information
Hi Sir,
I am new to microcontroller programming.
Functions of ATtiny I2C slave
This thread has useful information regarding bit checks for slave read/write
https://www.avrfreaks.net/forum/attiny416-acting-twii2c-slave-device-failure-second-read
But how to configure registers to use ATtiny pins as GPIOs?
This thread has useful information regarding bit checks for slave read/write
https://www.avrfreaks.net/forum/attiny416-acting-twii2c-slave-device-failure-second-read
But how to configure registers to use ATtiny pins as GPIOs?
What is your experience in programming ? maybe you should start with arduino better
I am trying to program ATtiny416 which is embedded in ATtiny416 xplained nano board for I2C communication . One ATtiny416 is used as master and another ATtiny416 as slave.
In atmel start I have configured the following to use ATtiny416 as I2C master
1) I2C master
2) PB0 & PB1 as SCL & SDA
3) Clock frequency: 416kHz (20Mhz/48 prescaler division)
4) PB5: digital output which is connected to a test LED on Xnano board
5) Fast mode plus is enabled
6) Pull up resistor is connected between Vcc & PB0
The reference code with the above configuration is exported to atmel studio IDE. And the code is dumped to ATtiny416.
When I checked the clock signal frequency using oscilloscope, it is highly fluctuating. I tried blinking LED, which is working fine.
Here I am attaching solution explorer also. Kindly requesting you to help.
Kindly requesting you to help.
I am not able to observe clock frequency 416kHz.
And, where can I observe printf statements in atmel studio?
And, where can I observe printf statements in atmel studio?
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#details
BTW your .rar file above does not contain all your project files. It has only the single .atsln file so is of no use to explore your code.
gkishore wrote:You need to provide an output channel such as UART or LCD then you use FDEV_SETUP_STREAM to associate this with a filing stream with stdout and then printf()/puts()/etc will redirect to the output device. See the user manual:And, where can I observe printf statements in atmel studio?
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#details
BTW your .rar file above does not contain all your project files. It has only the single .atsln file so is of no use to explore your code.
Whole project is attached now
Clock issue is resolved. Now I am able to use i2c for data transfer.
New issue araised regarding serial communication.
I am using ATtiny416 Xnano board to program on board ATtiny416.
I have programmed i2c & USART in ATtiny416. I am using puTTy to
observe the log of serial communication.
Configuration:
1) Tx & Rx pins of ATtiny416 are connected to Tx & Rx of USB to serial converter.
And I tried vice versa connections also.
2) I have configured to puTTy to COM1 port and baud rate to 9600.
But I am not able to watch log on puTTy terminal window.
of USB to serial converter.
Now I am able to observe the log. But the displayed hex values are not as expected.
I am sending 0x12 but I am getting C9 C9.
Wha do you want your application to do exactly, I just see that you are initializing the driver ? look at your code...what is your expectation out of this ?
Wha do you want your application to do exactly, I just see that you are initializing the driver ? look at your code...what is your expectation out of this ?
I am sending a byte 0x12 using function USART_0_WRITE(0x12); over serial port TX.
But output on serial port terminal is C9 C9 instead of 0x12
Serial comms issues asked here usually relates to improper baud rate due to not knowing what the cpu clock rate really is set to.
Where in your code above do you set the baud rate and what is the real cpu clock rate on your hardware.
Also one more tip, if you send the letter "U" repeatedly, it produces a square wave at the actual baud rate freq, easy to measure with scope or frequency counter.
Compare this value with what you expect to see and note any difference.
Jim
Serial comms issues asked here usually relates to improper baud rate due to not knowing what the cpu clock rate really is set to.
Where in your code above do you set the baud rate and what is the real cpu clock rate on your hardware.
Also one more tip, if you send the letter "U" repeatedly, it produces a square wave at the actual baud rate freq, easy to measure with scope or frequency counter.
Compare this value with what you expect to see and note any difference.
Jim
with the above configuration: 1)F_CPU=250000
baud rate at Tx pin of serial port the clock frequency is 9.6kHz.[Tested with sending 'U' repeatedly]
still I am getting wrong output
Why are you using 250kHz as the clock speed in one place and 16MHz in another?
The idea would be that you define one system wide symbol somewhere (often on the command line with a -D) and then use that symbol (traditionally most use "F_CPU") to make all other temporal calculations. That way is you one day switch from a 16MHz crystal to a 1.8432MHz crystal you just change that one define, in one place and all the calculations are re-done for the new speed.
Besides, all those numbers are irrelevant to the actual speed the chip is running, which is set by the OSCCFG fuse (which is a permanent setting at run time), as well as the CLKCTRL.MCLKCTRLA and CLKCTRL.MCLKCTRLB registers (which can be changed at run time).
So please let us know how/if you changed these values.
Besides, all those numbers are irrelevant to the actual speed the chip is running, which is set by the OSCCFG fuse (which is a permanent setting at run time), as well as the CLKCTRL.MCLKCTRLA and CLKCTRL.MCLKCTRLB registers (which can be changed at run time).
So please let us know how/if you changed these values.
I am not configuring anything CLKCTRL.MCLKCTRLA and CLKCTRL.MCLKCTRLB registers.
Why are you using 250kHz as the clock speed in one place and 16MHz in another?
The idea would be that you define one system wide symbol somewhere (often on the command line with a -D) and then use that symbol (traditionally most use "F_CPU") to make all other temporal calculations. That way is you one day switch from a 16MHz crystal to a 1.8432MHz crystal you just change that one define, in one place and all the calculations are re-done for the new speed.
I have configured 250kHz clock frequency in atmel start. Hence F_CPU is 250000.
But with 250000 in USART_BAUD_RATE(BAUD_RATE) the displayed bytes are wrong.
So I have changed it to 16000000. Then I am getting Baud rate 9600 on Tx pin of ATtiny416.
So I have changed it to 16000000.
That's the problem of using Atmel Start without knowing what's happening.
Please post the content of the clkctrl.c file, namely the CLKCTRL_init function.
That's the problem of using Atmel Start without knowing what's happening.
Please post the content of the clkctrl.c file, namely the CLKCTRL_init function.
you are commenting out the whole main clk settings...I never used your chip, but what does the guys think about this ?
So, you are setting a 64x divisor in CLKCTRL.MCLKCTRL. This means the CPU frequency is either 20MHz/64 (312.5 KHz) or 16MHz/64 (250KHz) depending on the OSCCFG fuse.
Have you changed this fuse? The factory setting is 20MHz.
you are commenting out the whole main clk settings...I never used your chip, but what does the guys think about this ?
That's done by Atmel Start automatically, it has generic code and comments out the unused stuff.
With baud rate 4
ki0bk wrote:Serial comms issues asked here usually relates to improper baud rate due to not knowing what the cpu clock rate really is set to.
Where in your code above do you set the baud rate and what is the real cpu clock rate on your hardware.
Also one more tip, if you send the letter "U" repeatedly, it produces a square wave at the actual baud rate freq, easy to measure with scope or frequency counter.
Compare this value with what you expect to see and note any difference.
Jim
with the above configuration: 1)F_CPU=250000
baud rate at Tx pin of serial port the clock frequency is 9.6kHz.[Tested with sending 'U' repeatedly]
still I am getting wrong output
If I am setting USART_BAUD_RATE(460000), I am getting the data on Tx pin properly. But I am not understanding why it should be 460000 instead of 4600 which is one of the standard baud rates.
If I am setting USART_BAUD_RATE(460000), I am getting the data on Tx pin properly. But I am not understanding why it should be 460000 instead of 4600 which is one of the standard baud rates.
That's because you are telling the baud_rate function the CPU is running at 16MHz, when in fact it is running at 312.5KHz.
I suggest you try this:
#define USART0_BAUD_RATE(BAUD_RATE) ((float)(312500.0 * 64 / (16 * (float)BAUD_RATE)) + 0.5)
Then set the baud rate as 9600, as it should.
USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
16MHz/64 (250KHz)
No, the UART clock is connected after the clock divisor, so the base clock for the UART is also 250KHz (or 312.5KHz). See this annotated scheme:
The problem is the fuse, the OP doesn't say anything about it, so it's impossible to know if the base clock is 20 or 16MHz just from looking at the code.
edit: sorry the control registers are reversed, let me correct the pic... done.
so it's impossible to know if the base clock is 20 or 16MHz
BTW that diagram is confusing - it shows two outputs from "Main Clock Prescaler" so is that saying that CLK_CPU might be set to one thing (250kHz) while CLK_PER is 16MHz ?
BTW that diagram is confusing - it shows two outputs from "Main Clock Prescaler" so is that saying that CLK_CPU might be set to one thing (250kHz) while CLK_PER is 16MHz ?
Yeah, it's misleading, you could conclude they can be connected to different taps in the prescaler, but reading the datasheet, in practice CLK_CPU and CLK_PER are always the same.
Maybe it will be different in future chips.
edit: I remembered discussing this previously https://www.avrfreaks.net/forum/...
I am transmitting N bytes using I2C communication. To transmit 'N' bytes, If a delay of 1sec is given after transmitting each byte, the data transfer is proper.
Otherwise intended data is not transferred. Why the delay is required after transmitting each byte in I2C?.
.
I am transmitting N bytes using I2C communication. To transmit 'N' bytes, If a delay of 1sec is given after transmitting each byte, the data transfer is proper.
Otherwise intended data is not transferred. Why the delay is required after transmitting each byte in I2C?.
the nice thing about I2C is it will tell you what is wrong IF you look at the return status value and act accordingly.
Do your I2C functions return status? If not, then you need better I2C functions, we see a lot of bad home made I2C functions here with void return values.
If they do return status values, Are you using it?
If not, why not?
Jim
gkishore wrote:I am transmitting N bytes using I2C communication. To transmit 'N' bytes, If a delay of 1sec is given after transmitting each byte, the data transfer is proper.
Otherwise intended data is not transferred. Why the delay is required after transmitting each byte in I2C?.
the nice thing about I2C is it will tell you what is wrong IF you look at the return status value and act accordingly.
Do your I2C functions return status? If not, then you need better I2C functions, we see a lot of bad home made I2C functions here with void return values.
If they do return status values, Are you using it?
If not, why not?
Jim
Following is the function I am using for "master transmit data to slave". It has proper return type And more over the function is generated by atmel start