make TWI library for PCF8574 and ATMEGA

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

hello  

i want to command an I/O expander PCF8574 with atmega382p but i don't get a result i'm using Microchip studio . this is my code: 

/// twi_lib.h
/*
 * twi_lib.h
 *
 * Created: 09/01/2022 5:25:27 PM
 *  Author: User
 */ 


#ifndef TWI_LIB_H_
#define TWI_LIB_H_


#define SCL_CLOCK  100000L


void twi_init();
uint8_t twi_start(char);
void twi_write(char);
char twi_read_ack();
char twi_read_nack();
void twi_stop();




#endif /* TWI_LIB_H_ */
//// twi_lib.c
/*
 * twi_lib.c
 *
 * Created: 09/01/2022 5:22:43 PM
 *  Author: User
 */ 

#include <compat/twi.h>
#include <util/delay.h>
#include "twi_lib.h"


void twi_init()
{
	TWSR = 0;
	TWBR = (((F_CPU/SCL_CLOCK)-16)/2) & 0xff;
}

uint8_t twi_start(char write_address)
{
	uint8_t   twst;
	// send start condition
	TWCR = (1<<TWEN)|(1<<TWSTA)|(1<<TWINT);	
	// wait until transmission completed
	while(!(TWCR & (1<<TWINT)));
	twst = TWSR;
	if (twst==0x08)
	{
		return 1;
	}
	// send device address
	TWDR = write_address;
	
	TWCR = (1<<TWINT) | (1<<TWEN);

	// wail until transmission completed and ACK/NACK has been received
	while(!(TWCR & (1<<TWINT)));
	
	// check value of TWI Status Register. Mask prescaler bits.
	twst = TW_STATUS & 0xF8;
	
	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
	

	return 0;
	
}
void twi_write(char data)
{
		//uint8_t   twst;
		
		// send data to the previously addressed device
		//TWCR = (1<<TWINT) | (1<<TWEN);
		TWCR = 1<<TWINT;
		TWDR = data;
		TWCR = (1<<TWINT) | (1<<TWEN);

		// wait until transmission completed
		while(!(TWCR & (1<<TWINT)));
}
char twi_read_ack()
{
	TWCR = (1<<TWINT) | (1<<TWEN) ;
	while(!(TWCR & (1<<TWINT)));
	
	return TWDR;
}
char twi_read_nack()
{
	TWCR = (1<<TWINT) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)));
	
	return TWDR;
}
void twi_stop()
{
	/* send stop condition */
	TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
	
	// wait until stop condition is executed and bus released
	while(TWCR & (1<<TWSTO));
	
}
///// main.c
/*
 * carte_I2C_relais.c
 *
 * Created: 27/12/2021 5:38:56 PM
 * Author : User
 */ 

#include <avr/io.h>
#include <compat/twi.h>
//#include<TWI_lib.h>
#include <util/delay.h>
#include "twi_lib.h"
uint32_t CPU_FREQ = 16000000;
int main(void)
{            
			 twi_init();
			 
			twi_start(0x20);
			while (1)
			{
				twi_write(0x40);
				twi_read_ack();
				twi_write(0x01);
				
				twi_stop();
			}
			
			
			
	

}



please check my code. thanks 

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

jawherbenali wrote:

TWBR = (((F_CPU/SCL_CLOCK)-16)/2) & 0xff;

Where are you defining F_CPU? (possibly in Compiler Symbols?)

Are you SURE the m328 is REALLY running at F_CPU? (have you verified this?)

You are never referencing CPU_FREQ, is it even necessary since that should be the same as F_CPU?

David

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

My advice is always :  start with a respected I2C library e.g. Fleury.

 

Get your project working 100%.    I can see some serious errors in your main() function.

 

When your code is debugged you can think about hand-rolling your own TWI library.

I have not attempted to read your "twi_lib.h"

 

When you have verified your project with a proven I2C library,  I am happy to help debug "your" code.

 

David.

 

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

hello

it's mentioned in the datasheet the frequency 8MHz. i tried  it but i got nothing.  

thanks 

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

hello  @david.prentice 

i want to make my own library please can you mention the errors i have maked. 

thanks in advance. 

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

Why are you performing a STOP inside your loop ? The subsequent writes will surely fail (not that you could tell from your code, because you haven't implemented any error codes)

    while (1) {
        twi_write(0x40);
        twi_read_ack();
        twi_write(0x01);

        twi_stop();
    }
Last Edited: Tue. Jan 18, 2022 - 08:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello  

thanks for your time .

i writen the twi_stop() out of the loop but it doesn't work. also i delated it but it still the some. 

i don't get any errors. 

i don't understand why it didn't work!!

thanks. 

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

jawherbenali wrote:
i don't get any errors.

But you wrote:

twi_start(0x20);

and didn't check the return code for errors.

 

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

i don't understand what you want to mention !!

where is the error!

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

frog_jr wrote:
Where are you defining F_CPU? (possibly in Compiler Symbols?)

jawherbenali wrote:
it's mentioned in the datasheet the frequency 8MHz. i tried  it but i got nothing. 

Have you defined F_CPU in your code?

If not, then the value of F_CPU withing the code is probably defaulting to 1MHz.

 

HOWEVER, it is very important to note:

     F_CPU does not actual set the processor frequency, it is just used to let the software know the frequency of operation.

 

SO, ...  Have you verified the frequency at which the CPU is running?

David

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

jawherbenali wrote:
where is the error!

You defined twi_start with a return value of uint_8t:

jawherbenali wrote:

uint8_t twi_start(char write_address)

However, you do not check the return value to see if the twi_start actually completed successfully.

David