Hello!
I'm programming an I2C communications for the first time and I just can't seem to get it to work.
Communications are between an Arduino Uno R3 and an Atmega1280 (external crystal 8MHz).
Pullup Resistors are 4.7kohm to a 5V line.
Arduino acting as Master, Atmega as Slave.
I'm trying to get the Arduino to send data to the uC and have it send it back, however it doesn't seem get into the states I expect it to.
Arduino Code:
// Code to test whether I2C of uC is working // Description: Send data, receive data sent, display #include <Wire.h> void setup() { // put your setup code here, to run once: Wire.begin(); Serial.begin(9600); uint8_t uC_Address = 0x1C; uint8_t sending = 3; uint8_t SendBuffer[sending]; uint8_t txsending; //command to let uC know to store SendBuffer[0] = 0x1; //data to send SendBuffer[1] = 0x17; SendBuffer[2] = 0x64; // Testing begin // Send test data Wire.beginTransmission(uC_Address); Wire.write(SendBuffer , sending); txsending = Wire.endTransmission(); if (txsending == 0){ Serial.println("Sending Success"); } else { Serial.println("Sending Failed. Bytes left to send:"); Serial.println(txsending); } //Receive test data Wire.requestFrom(uC_Address, uint8_t (sending-1)); Serial.println("Request complete"); while(Wire.available()) { Serial.println("Available confirmed"); uint8_t x = Wire.read(); Serial.println(x); } Serial.println("Receiving complete"); } void loop() { // put your main code here, to run repeatedly: }
Atmega1280 Code:
/** * Test code for receiving I2C * uC acting as Slave */ /* * Include header files for all drivers that have been imported from * Atmel Software Framework (ASF). */ /* * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> */ #define F_CPU 8000000UL #include <asf.h> #include <util/twi.h> uint8_t SlaveAddress = 0x1C; volatile uint8_t TWI_Command = 0; volatile uint8_t TWI_txbuffer[0xFF]; //buffer to store data being sent volatile uint8_t TWI_datacount = 0; //tracks how much data needs to be sent volatile uint8_t TWI_datatrack = 0; //tracks how much data has been sent ISR(TWI_vect){ // set pin to low if interrupt is called ioport_set_port_level(IOPORT_PORTD, (1<<PD6), IOPORT_PIN_LEVEL_LOW); // dummy variable to store data uint8_t data; if (TW_STATUS == TW_SR_SLA_ACK){ // if slave address comes up with write command (slave is receiver), New command TWCR |= (1<<TWINT)|(0<<TWSTO)|(1<<TWEA)|(1<<TWEN); } else if (TW_STATUS == TW_SR_DATA_ACK) { // if Data byte has been received in slave receive mode data = TWDR; if (TWI_Command == 0){ if ((data & 0x1) == 0x1) { // Communications test command, send ack and prepare to receive data to send back TWI_Command = 1; TWCR |= (1<<TWINT)|(1<<TWEA)|(1<<TWEN); } } else if (TWI_Command == 1) { // Data received is test data meant to be sent back, 0xFF total data bytes can be sent for test TWI_txbuffer[TWI_datacount] = data; TWI_datacount++; if (TWI_datacount == 0xFF){ // if too much data is set to be sent (overflow), reset the count, most recent data only data to be sent TWI_txbuffer[0] = data; TWI_datacount = 1; } TWI_datatrack = 0; // counter used to track data being sent, reset to 0 for new sending TWCR |= (1<<TWINT)|(1<<TWEA)|(1<<TWEN); //clear flag, send ack and prepare to receive more data } } else if (TW_STATUS == TW_SR_STOP){ // stop command or repeated start, set slave to prepare to be addressed. if repeated start likely going to be addressed again but as transmitter TWCR |= (1<<TWINT)|(1<<TWEA)|(1<<TWEN); } else if (TW_STATUS == TW_ST_SLA_ACK) { // if slave address comes up with read command (slave is transmitter) if (TWI_Command == 1){ // commands 1 (currently) are the commands that require transmission TWDR = TWI_txbuffer[TWI_datatrack]; TWI_datatrack++; TWCR = (1<<TWINT)|(0<<TWSTO)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE); } else { // if not one of these commands then the system has been commanded incorrectly, set to send 0xFF and receive nack TWDR = 0xFF; TWCR = (1<<TWINT)|(0<<TWSTO)|(0<<TWEA)|(1<<TWEN)|(1<<TWIE); } } else if (TW_STATUS == TW_ST_DATA_ACK){ // if there is still more transmitting to do TWDR = TWI_txbuffer[TWI_datatrack]; TWI_datatrack++; if (TWI_datatrack == TWI_datacount) {// is this data byte the last one to be sent?, if yes prepare to receive nack TWI_datacount = 0; TWI_datatrack = 0; TWCR = (1<<TWINT)|(0<<TWSTO)|(0<<TWEA)|(1<<TWEN)|(1<<TWIE); } else { TWCR = (1<<TWINT)|(0<<TWSTO)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE); } } else if (TW_STATUS == TW_ST_LAST_DATA) { // if last data has been sent and ack received when it shouldn't have, switch to not addressed TWCR = (1<<TWINT)|(0<<TWSTA)|(0<<TWSTO)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE); } else { // (command not recognized, state not accounted for), clear flag, set to prepare for next addressing TWCR |= (1<<TWINT)|(1<<TWEA)|(1<<TWEN); } } int main (void) { /* Insert application code here, after the board has been initialized. */ ioport_set_port_dir(IOPORT_PORTD, (1<<PD6), IOPORT_DIR_OUTPUT); ioport_set_port_level(IOPORT_PORTD, (1<<PD6), IOPORT_PIN_LEVEL_HIGH); sei(); TWAR = (SlaveAddress<<1); // Enable TWI and TWI interrupt flag TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWEA)|(1<<TWINT); while(1){} }
The Pin that I set to go low if the Atmega1280 ISR is entered properly goes low.
However No data is successfully sent (Arduino wire.endTransmission() state also reflects this, giving a value of 2), I can't seem to figure out why this is.