I remembered a little hardcore in Hardwar with TWI interface, which takes a few years ago. Who would not say, and Assembler perfectly cleanses the brain and develops an understanding of the algorithms. The most important thing I learned while working with AVR microcontrollers on Assembler, is the fact that all the operations, all directives, all functions must be written in a clear sequence. After all, if the write data in the register is not in the sequence, then your controller firmware does not work. And when writing code in high-level languages, sometimes you can see a complete indifference to the sequence of calling functions and methods, though often in the instructions to the libraries can be read, in what order you need to initialize a particular functionality, to get everything working. But who would read them carefully? Well, if you dear reader to read this paragraph instead skopipastit immediately imagine a software library of code that is shown below.
TWI interface
This type of in-circuit is an analog interface I2C interface, which was developed by Philips in the 1980s. This interface is used as a hardware module and a microcontroller Atmega thus easier I2C bus on which the other devices operate. The name is different from I2C is a result of the impact of patent law.
As the bus I2C, TWI interface is also working on two bi-directional communication lines: SDA (English Serial DAta.) And SCL (anlg Serial CLock.). Both communication lines are tightened in the scheme of resistors to the power supply, which is typically +3.3 and +5 volts. Address space in the classic version is 128 addresses in the extended address 1024 standard.
There are four important kinds of states on the bus, which is the work of the interface:
- START - change the state of the SDA line from 1 to 0, with SCL unaltered state 1
- STOP - change of the SDA line status from 0 to 1, with SCL unaltered state 1
- Transfer bit equal to 1 - SDA is at 1, the SCL changes state 0-1-0
- Transfer bit equal to 0 - SDA is at 1, the SCL changes state 0-1-0
Changing the SDA status when SCL equal to 1 has no effect and is ignored.
TWI bus operates on the principle of Master-Slave. Lead submits the starting premise, then begins transmitting a byte of information. As soon as the slave received the information, it sends an acknowledge bit. End of data is determined by stop sending.
Library to work with TWI interface
This article presents a library to work with TWI interface, which is designed to Atmega48 microcontrollers, Atmega88, Atmega168, Atmega328. Also, the library can be used for work and other microcontrollers Atmega, which have a TWI interface.
Attention. Register names in different models may vary.
/* * i2c_lib.asm * * Library procedures for i2c bus (Atmega48) * The library is intended for use as a plug-in * To other projects. * * The library works with TWI interface to avr microcontrollers * * The library works with register r16 * * Created: 15.07.2013 23:51:32 * Author: Evgenii Legotckoi */ ;======= Start combination on i2c bus ================================================== i2c_start: push r16 ldi r16,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ; Execute starting combination sts TWCR,r16 ; Send byte received to TWCR rcall i2c_wait ; Waiting to form a start in the TWI unit pop r16 ; Returns data in r16 from the stack ret ;======= Stop combination on i2c bus =================================================== i2c_stop: push r16 ldi r16,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ; Send stop combination sts TWCR,r16 ; Send byte received to TWCR pop r16 ; Returns data in r16 from the stack ret ;======= Sending byte information via i2c bus ========================================== i2c_send: push r16 sts TWDR,r16 ; Write the bytes transmitted in the register TWDR ldi r16,(1<<TWINT)|(1<<TWEN) ; We form a byte, which answer ; for forwarding information byte sts TWCR,r16 ; Send byte received to TWCR rcall i2c_wait ; Waiting for the end of transfer bytes pop r16 ; Returns data in r16 from the stack ret ;======= Receiving data byte for i2c bus =============================================== i2c_receive: ; The received byte is placed in the register r16, ; so it is recommended to consider the program so that at this point ; there was no important information bytes are not stored ; on the stack in the code of the procedure ldi r16,(1<<TWINT)|(1<<TWEN)|(1<<TWEA) ; We form a byte, is responsible for receiving sts TWCR,r16 ; Send byte received to TWCR rcall i2c_wait ; Waiting for the end of transfer bytes lds r16,TWDR ; this information is read from TWDR ret ;======= Receive the last byte (NACK) ================================================== i2c_receive_last: ; The received byte is placed in the register r16, ; so it is recommended to consider the program so that at this point ; there was no important information bytes are not stored ; on the stack in the code of the procedure ldi r16,(1<<TWINT)|(1<<TWEN) ; We form a byte, is responsible for receiving the information bytes sts TWCR,r16 ; Send byte received to TWCR rcall i2c_wait ; Waiting for the end of transfer bytes lds r16,TWDR ; this information is read from TWDR ret ;======= Ожидание готовности TWI ======================================================= i2c_wait: lds r16,TWCR ; Load the value from TWCR to r16 sbrs r16,TWINT ; standby function is executed as long as the raised interrupt flag 1 rjmp i2c_wait ret ;=======================================================================================
Attention. Also for the library you want to initialize the stack of the microcontroller. For example as follows:
;======= Макросы ========================================================================= ; Output Macro to the port or Register .macro outi ldi r16, @1 out @0,R16 .endm ;========================================================================================= RESET: outi SPL,Low(RAMEND) ; Init stack outi SPH,High(RAMEND)