I2C KEYPAD PROBLEM

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

I am trying to make an i2c keypad by using atmega8 (master receive and slave transmit mode). here is the master code

 

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
void I2C_INIT()
{
	TWBR = 0x00; //CLEAR STATUS
	TWBR = 0x0C; //SET BIT RATE
}

void I2C_START()
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
	while((TWCR & (1<<TWINT)) == 0);
	while((TWSR & (0xF8)) != 0x08);
}
void I2C_READAdress(/*unsigned char adress*/)
{
	TWDR = 0b01000001;
	TWCR = (1<<TWINT)|(1<<TWEN);
	while((TWCR & (1<<TWINT)) == 0);
	while((TWSR & (0xF8)) != 0x40);
}
unsigned char i2c_read_data()
{
	TWCR = (1<<TWINT)|(1<<TWEN);
	while((TWCR & (1<<TWINT)) == 0);
	while((TWSR & (0xF8)) != 0x58);
	return TWDR;
}
void I2C_stop()
{
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}
int main(void)
{
	DDRD=0xFF;
	I2C_INIT();
    while (1)
    {
		I2C_START();
		_delay_ms(1000);

		I2C_READAdress();
		_delay_ms(1000);
		PORTD=i2c_read_data();
		_delay_ms(1000);

		I2C_stop();
		_delay_ms(1000);
    }
}

 

here is slave code.

 

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

////////////////////////	KEYAPD	/////////////////////////////
#define KEY_PRT 	PORTD
#define KEY_DDR		DDRD
#define KEY_PIN		PIND

unsigned char keypad[4][4] = {
	{'A','3','2','1'},
	{'B','6','5','4'},
	{'C','9','8','7'},
	{'D','#','0','*'}};

	unsigned char colloc, rowloc;

	char keyfind()
	{
		while(1)
		{
			KEY_DDR = 0xF0;           /* set port direction as input-output */
			KEY_PRT = 0xFF;

			do
			{
				KEY_PRT &= 0x0F;      /* mask PORT for column read only */
				asm("NOP");
				colloc = (KEY_PIN & 0x0F); /* read status of column */
			}while(colloc != 0x0F);

			do
			{
				do
				{
					_delay_ms(20);             /* 20ms key debounce time */
					colloc = (KEY_PIN & 0x0F); /* read status of column */
					}while(colloc == 0x0F);        /* check for any key press */

					_delay_ms (40);	            /* 20 ms key debounce time */
					colloc = (KEY_PIN & 0x0F);
				}while(colloc == 0x0F);

				/* now check for rows */
				KEY_PRT = 0xEF;            /* check for pressed key in 1st row */
				asm("NOP");
				colloc = (KEY_PIN & 0x0F);
				if(colloc != 0x0F)
				{
					rowloc = 0;
					break;
				}

				KEY_PRT = 0xDF;		/* check for pressed key in 2nd row */
				asm("NOP");
				colloc = (KEY_PIN & 0x0F);
				if(colloc != 0x0F)
				{
					rowloc = 1;
					break;
				}

				KEY_PRT = 0xBF;		/* check for pressed key in 3rd row */
				asm("NOP");
				colloc = (KEY_PIN & 0x0F);
				if(colloc != 0x0F)
				{
					rowloc = 2;
					break;
				}

				KEY_PRT = 0x7F;		/* check for pressed key in 4th row */
				asm("NOP");
				colloc = (KEY_PIN & 0x0F);
				if(colloc != 0x0F)
				{
					rowloc = 3;
					break;
				}
			}

			if(colloc == 0x0E)
			return(keypad[rowloc][0]);
			else if(colloc == 0x0D)
			return(keypad[rowloc][1]);
			else if(colloc == 0x0B)
			return(keypad[rowloc][2]);
			else
			return(keypad[rowloc][3]);
		}

void i2c_slaveinit()
{
	TWAR = 0b01000000;
	TWCR = (1<<TWEN)|(1<<TWEA)|(1<<TWINT);
}
void i2c_ACK()
{
	TWCR = (1<<TWEN)|(1<<TWINT);
	while((TWCR & (1<<TWINT)) == 0);
	while((TWSR & (0xF8)) != 0xA8);
	/*TWDR = data;
	TWCR &= ~(1<<TWEA);
	TWCR = (1<<TWEN)|(1<<TWEA);*/
}
void i2c_transmit(unsigned char data)
{
	TWDR = data;
	TWCR &= ~(1<<TWEA);
	TWCR = (1<<TWEN)|(1<<TWINT);
	while((TWCR & (1<<TWINT)) == 0);
	while((TWSR & (0xF8)) != 0xC0);
	TWCR = (1<<TWEN)|(1<<TWEA)|(1<<TWINT);
}
void i2c_Match_ACK()
{
	while((TWSR & (0xF8)) != 0xA8)
	{
		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
		while((TWCR & (1<<TWINT))==0);
	}
}

int main(void)
{
	char x;
	i2c_slaveinit();
    while (1)
    {
		//i2c_ACK();
		i2c_Match_ACK();
		x=keyfind();
		i2c_transmit(x);
    }
}

so it gives NACK after STA+R when I put x=keyfind(), and if I put x='a' or anything else I get ACK and code works fine then that's very weird . can someone help?

Last Edited: Mon. Jul 9, 2018 - 07:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Crosspost..

 

the OP has the same problem here:

https://www.avrfreaks.net/forum/...

 

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

No, they are different

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

IN both cases you are not able to get an ACK from the slave.

 

Till you get an ack from the slave all other things are pointless as your slave will not be responding to anything else you send out.

 

edit:

suggest you work on one side of the code at a time. Or you might be playing ping-pong all the time and keep running around in circles.

The master is the easiest to implement as there you are in full control of what you are doing.

what I always do is have for instance a PCF8574 + a AT24C02. first you get the PCF to work. that is all single byte oriented and should be up and running quickly.

then you extend with also using the 2402 that is more work as more data is to be send to the chip before you get anything back, also writing data to it for storage takes more information to be send.

When you can successfully talk to these 2 chips you know that in the basis your master code is working and is sending out the data you want it to be send.

Then you can concentrate on getting the slave part to work.

 

Note that there are a lot of pitfalls with respect to the ACK and NACK states transmitted and received. Also with regards on how you need to set-up/adjust the TWI interface in advance and during data reception. (single byte, multi byte / ack nack transmit / 7 bits address versus 8 bits address )

Personally I started by reading and understanding how the I2C interface works ( note that the spec is changing a lot but not in the basic operation, so if you look it up there will be a version online) then I just programmed the TWI interfacy by bitbanging and seeing that that worked, so I knew the hardware was OK. Then I moved over to start using the TWI peripheral and getting that to work. But there are also libraries like the peter fleury library that you can use and not care about what is below that to get things going.

 

Last Edited: Mon. Jul 9, 2018 - 07:46 AM
Topic locked