problem in twi reading data from pcf8574

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

I have written the below codes in CV compiler for interfacing mega 32 as master and pcf8574 as slave ,writing data is ok and it is done correctly but didn.t find the codes for reading from slave,

any help is appreciated.

 


#include <mega32a.h> 
#include <delay.h>
#include "TWI_Master.h"
//#include <twi_master.h>
#define SEND_DATA             0x01
#define REQUEST_DATA          0x02
#define READ_DATA_FROM_BUFFER 0x03
#define START 		       0x08 
#define Repeated_START 	 0x10
// Master Transmitter
#define MT_SLA_ACK       0x18
#define MT_SLA_NACK      0x20
#define MT_DATA_ACK      0x28
#define MT_DATA_NACK     0x30
#define MT_ARB_LOST      0x38
// Master Receiver
#define MR_ARB_LOST      0x38
#define MR_SLA_ACK       0x40
#define MR_SLA_NACK      0x48
#define MR_DATA_ACK      0x50
#define MR_DATA_NACK     0x58

//TWCR    _SFR_IO8(0x36)
//#define TWIE    0
//#define TWEN    2
//#define TWWC    3
//#define TWSTO   4
//#define TWSTA   5
//#define TWEA    6
//#define TWINT   7

static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer
static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.
static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.


interrupt [TWI] void TWI_ISR(void)  
{
  static unsigned char TWI_bufPtr ;
  
  switch (TWSR)
  {
    case TWI_START:             // START has been transmitted  
    case TWI_REP_START:         // Repeated START has been transmitted
      TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location
    case TWI_MTX_ADR_ACK:       // SLA+W has been tramsmitted and ACK received
    case TWI_MTX_DATA_ACK:      // Data byte has been tramsmitted and ACK received
      if (TWI_bufPtr < TWI_msgSize)
      {
        TWDR = TWI_buf[TWI_bufPtr++];
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
               (0<<TWWC);                                 //  
      }else                    // Send STOP after last byte
      {
        TWI_statusReg_lastTransOK = TRUE;                 // Set status bits to completed successfully. 
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
               (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
               (0<<TWWC);                                 //
      }
      break;
    case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK tramsmitted
      TWI_buf[TWI_bufPtr++] = TWDR;
    case TWI_MRX_ADR_ACK:       // SLA+R has been tramsmitted and ACK received
      if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
               (0<<TWWC);                                 //  
      }else                    // Send NACK after next reception
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
               (0<<TWWC);                                 // 
      }    
      break; 
    case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK tramsmitted
      TWI_buf[TWI_bufPtr] = TWDR;
      TWI_statusReg_lastTransOK = TRUE;                 // Set status bits to completed successfully. 
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
             (0<<TWWC);                                 //
      break;      
    case TWI_ARB_LOST:          // Arbitration lost
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag
             (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
             (0<<TWWC);                                 //
      break;
    case TWI_MTX_ADR_NACK:      // SLA+W has been tramsmitted and NACK received
    case TWI_MRX_ADR_NACK:      // SLA+R has been tramsmitted and NACK received    
    case TWI_MTX_DATA_NACK:     // Data byte has been tramsmitted and NACK received
//    case TWI_NO_STATE              // No relevant state information available; TWINT = “0”
    case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
    default:     
      TWI_state = TWSR;                                 // Store TWSR and automatically sets clears noErrors bit.
                                                        // Reset TWI Interface
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
             (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt
             (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
             (0<<TWWC);                                 //
  }
}
 int i=0;
 //  unsigned char messageBuf[4],firsttime =1;
  // unsigned char TWI_targetSlaveAddress,  TWI_operation=0,pressedButton =0, myCounter=0;
   void twi_start(void){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);    	  	
	while(!(TWCR & (1<<TWINT))); 
   }
void twi_write(unsigned char data){
		TWDR = data;                       	
		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);		 
		while (!(TWCR & (1<<TWINT)));		                               
    }

/*unsigned char twi_read  (unsigned char get_data){
	//unsigned  char   get_data; 
	if((TWSR & 0xF8) == MR_SLA_ACK) {     	
    	TWCR = (1<<TWINT)| (1<<TWEN)| (1<<TWEA);    	
    while (!(TWCR & (1<<TWINT)));       
	 get_data=TWDR;	
	 TWCR = (1<<TWINT)|(1<<TWEN);   
	while (!(TWCR & (1<<TWINT)));	  
	return get_data;                         			      
  	}	                    
}*/




void twi_stop(void){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); 	  	   	
}


  void MT_TWI(unsigned char data,unsigned char address_device)   //Master transmits the data to the address of the Slave 
 {                                            
  twi_start();
  twi_write((address_device<<1)&0xFE);
  twi_write(data);                             
  twi_stop();
 }


unsigned  char  val;
unsigned char Senddata,Slaveaddress=0x20;
void main( void )
{
 
  DDRA  = 0xFF;
  DDRC  = 0x00;
  DDRD=0xff;
 for(i=0;i<=3;i++) //Startup Led
    {
        PORTD.7=~PORTD.7;
        delay_ms(1000);
    }
  while(1)
  {
      Senddata=0xf3;
      MT_TWI(Senddata,Slaveaddress);
      
      PORTD=Senddata;
      delay_ms(2000);
      
     Slaveaddress=0x20;
     Senddata=0xf2;
     MT_TWI(Senddata,Slaveaddress);
     PORTD=Senddata;
     delay_ms(2000);
     
   }
   
  }

The codes which I have commented has no effect and it reads no data from the slave.

This topic has a solution.
Last Edited: Tue. Mar 31, 2020 - 10:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Typically, you issue a start with the device address in write mode, then write the address of the register to be read.

 

Then, you issue a repeated start, in read mode, to read the register (and any following ones if it offers auto address increment). The repeated start means that you send the device address again, but the read/write bit is set to read. You send the repeated start WITHOUT sending a stop for the first part of the transaction.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Tue. Mar 31, 2020 - 12:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry Jim, I did not get your point ,will you please say with an example what you mean?

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

Don't have an example. Here is the read process, again, where the data is in an addressed register in the slave:

 

1) Send start with slave address and a write bit

2) When the addressed slave ACKs, send the address of the register to be read.

3) When the addressed slave ACKs, send a NEW start; DO NOT send a stop for the preceding part. This is called a "repeated start". As part of this repeated start, send the slave address, again, but with read instead of write.

4) I think you then put a dummy byte into the data register, to force 8 clock bits that drives the slave for sending its data.

5) If it is just one byte, I think that the master has to ACK 

6) Master reads the data from the data register

7) Master sends a STOP

 

Pretty certain about steps 1-3. Less certain about 4-7 but I think they are correct. The process SHOULD be independent of the compiler being used. Function names will be different but the steps are exactly the same because that is set by the hardware inside. The Mega32 manual should help.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Surely you have all the functions already provided by CV library.

 

void twi_master_init(unsigned int bit_rate)

 

            enables and initializes the TWI hardware for operating in master mode.

 

Parameters:

 

            bit_rate specifies the SCL clock frequency in kHz.

 

bool twi_master_trans(

            unsigned char slave_addr,

            unsigned char *tx_data,

            unsigned char tx_count,

            unsigned char *rx_data,

            unsigned char rx_count)

 

            performs a TWI transaction using the master module.

 

If you want to read from the PCF8574

unsigned char read_value;
bool ret = twi_master_trans(0x20, NULL, 0, &read_value, 1);

From memory,  the PCF8574 has an IRQ pin.   So you only need to read the device when the IRQ pin says there has been a change.

 

CV obviously uses the TWI interrupt.   So you can't mix home-grown TWI service routines with CV library calls.

 

If you really want to write your own TWI interrupt code CV can compile it just fine.   For example,   it is simple to port Atmel TWI Application notes like AVR315.   And even simpler to port Xmega App Notes like AVR1308 to CV.

 

Actually the PCF8574 might be easier to use via polled I2C rather than interrupts.    In which case you can use CV "i2c.h" library functions.

 

David.

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

Dear David Thank you for your help ,but belive me I am not that cleaver to put these in to action. I copied your code in the there but produced many errors.

Is it possible that give me a few line of codes which fits what I already have? with the codes I already have ,writing to pcf8574 is ok and it dose the job,the only things is reading from it.

I past my codes and yours again to see how it can be fixed.

 



#include <mega32a.h> 
#include <delay.h>
#include "TWI_Master.h"
//#include <twi_master.h>
#define SEND_DATA             0x01
#define REQUEST_DATA          0x02
#define READ_DATA_FROM_BUFFER 0x03
#define START 		       0x08 
#define Repeated_START 	 0x10
// Master Transmitter
#define MT_SLA_ACK       0x18
#define MT_SLA_NACK      0x20
#define MT_DATA_ACK      0x28
#define MT_DATA_NACK     0x30
#define MT_ARB_LOST      0x38
// Master Receiver
#define MR_ARB_LOST      0x38
#define MR_SLA_ACK       0x40
#define MR_SLA_NACK      0x48
#define MR_DATA_ACK      0x50
#define MR_DATA_NACK     0x58

//TWCR    _SFR_IO8(0x36)
//#define TWIE    0
//#define TWEN    2
//#define TWWC    3
//#define TWSTO   4
//#define TWSTA   5
//#define TWEA    6
//#define TWINT   7

static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer
static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.
static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.


interrupt [TWI] void TWI_ISR(void)  
{
  static unsigned char TWI_bufPtr ;
  
  switch (TWSR)
  {
    case TWI_START:             // START has been transmitted  
    case TWI_REP_START:         // Repeated START has been transmitted
      TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location
    case TWI_MTX_ADR_ACK:       // SLA+W has been tramsmitted and ACK received
    case TWI_MTX_DATA_ACK:      // Data byte has been tramsmitted and ACK received
      if (TWI_bufPtr < TWI_msgSize)
      {
        TWDR = TWI_buf[TWI_bufPtr++];
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
               (0<<TWWC);                                 //  
      }else                    // Send STOP after last byte
      {
        TWI_statusReg_lastTransOK = TRUE;                 // Set status bits to completed successfully. 
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
               (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
               (0<<TWWC);                                 //
      }
      break;
    case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK tramsmitted
      TWI_buf[TWI_bufPtr++] = TWDR;
    case TWI_MRX_ADR_ACK:       // SLA+R has been tramsmitted and ACK received
      if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
               (0<<TWWC);                                 //  
      }else                    // Send NACK after next reception
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
               (0<<TWWC);                                 // 
      }    
      break; 
    case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK tramsmitted
      TWI_buf[TWI_bufPtr] = TWDR;
      TWI_statusReg_lastTransOK = TRUE;                 // Set status bits to completed successfully. 
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
             (0<<TWWC);                                 //
      break;      
    case TWI_ARB_LOST:          // Arbitration lost
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag
             (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
             (0<<TWWC);                                 //
      break;
    case TWI_MTX_ADR_NACK:      // SLA+W has been tramsmitted and NACK received
    case TWI_MRX_ADR_NACK:      // SLA+R has been tramsmitted and NACK received    
    case TWI_MTX_DATA_NACK:     // Data byte has been tramsmitted and NACK received
//    case TWI_NO_STATE              // No relevant state information available; TWINT = “0”
    case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
    default:     
      TWI_state = TWSR;                                 // Store TWSR and automatically sets clears noErrors bit.
                                                        // Reset TWI Interface
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
             (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt
             (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
             (0<<TWWC);                                 //
  }
}
 int i=0;
 //  unsigned char messageBuf[4],firsttime =1;
  // unsigned char TWI_targetSlaveAddress,  TWI_operation=0,pressedButton =0, myCounter=0;
   void twi_start(void){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);    	  	
	while(!(TWCR & (1<<TWINT))); 
   }
void twi_write(unsigned char data){
		TWDR = data;                       	
		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);		 
		while (!(TWCR & (1<<TWINT)));		                               
    }

/*unsigned char twi_read  (unsigned char get_data){
	//unsigned  char   get_data; 
	if((TWSR & 0xF8) == MR_SLA_ACK) {     	
    	TWCR = (1<<TWINT)| (1<<TWEN)| (1<<TWEA);    	
    while (!(TWCR & (1<<TWINT)));       
	 get_data=TWDR;	
	 TWCR = (1<<TWINT)|(1<<TWEN);   
	while (!(TWCR & (1<<TWINT)));	  
	return get_data;                         			      
  	}	                    
}*/

//This is David codes
void twi_master_init(unsigned int bit_rate)

  //  enables and initializes the TWI hardware for operating in master mode.
//Parameters:
//   bit_rate specifies the SCL clock frequency in kHz.

bool twi_master_trans(

            unsigned char slave_addr,

            unsigned char *tx_data,

            unsigned char tx_count,

            unsigned char *rx_data,

            unsigned char rx_count)
unsigned char read_value;
bool ret = twi_master_trans(0x20, NULL, 0, &read_value, 1);


void twi_stop(void){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); 	  	   	
}


  void MT_TWI(unsigned char data,unsigned char address_device)   //Master transmits the data to the address of the Slave 
 {                                            
  twi_start();
  twi_write((address_device<<1)&0xFE);
  twi_write(data);                             
  twi_stop();
 }


unsigned  char  val;
unsigned char Senddata,Slaveaddress=0x20;
void main( void )
{
 
  DDRA  = 0xFF;
  DDRC  = 0x00;
  DDRD=0xff;
 for(i=0;i<=3;i++) //Startup Led
    {
        PORTD.7=~PORTD.7;
        delay_ms(1000);
    }
  while(1)
  {
      Senddata=0xf3;
      MT_TWI(Senddata,Slaveaddress);
      
      PORTD=Senddata;
      delay_ms(2000);
      
     Slaveaddress=0x20;
     Senddata=0xf2;
     MT_TWI(Senddata,Slaveaddress);
     PORTD=Senddata;
     delay_ms(2000);
     
   }
   
  }

 

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

azizollah wrote:
I am not that clever to put these in to action

It's not about being clever or not - it's about learning & developing the appropriate skills.

 

As with learning any new skill, it is important to start with the basics, lay strong foundations, and build step by step - not leap straight into something over-complicated where you're out of your depth.

 

Getting to grips with I2C does require that you have some good solid foundations in place - so maybe you need to take a step back, and review some basics?

 

See Tip #6 in my signature (below) for some beginner's getting started ideas ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have a full licence for CodeVision?  

 

The TWI library functions might be restricted on the free Evaluation version.

 

The bit-bash "i2c.h" functions should always be available.

 

If you say what version you are using,  I can write the appropriate example code for you.

 

David.

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

Hi David,

CV Version is 3.12 Advanced  Copyright 1998:2014

I dn;t know about licence but this is what I have.

Let me tell you that I tired the i2c type of statements but that also could not buid the program.

 

Anyhow its very kind of you to help me.

 

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

Here is an example.  

/*
 * PCF8574_read.c
 *
 * Created: 31-Mar-20 17:17:11
 * Author: David Prentice
 */

#include <io.h>
#include <stdio.h>      //for NULL
#include <TWI.h>
#include <delay.h>

#define PCF8574 0x20    //7-bit Slave address

void main(void)
{
    bool ret;
    unsigned char read_value, send_data;
    twi_master_init(100);  //100kHz bus
    DDRD = 0xFF;
    while (1) {
        send_data = 0xF3;  //make bits 0,1,4,5,6,7 input
        ret = twi_master_trans(PCF8574, &send_data, 1, NULL, 0);
        PORTD = send_data;
        delay_ms(2000);
        send_data = 0xF2;  //make bits 1,4,5,6,7 input
        ret = twi_master_trans(PCF8574, &send_data, 1, &read_value, 1);
        PORTD = read_value; //read  1,4,5,6,7 input.   0,2,3 are output LOW
        delay_ms(2000);
    }
}

It would be wise to test the value of ret variable.   And light an LED if false.

 

Remember to use pullups on SDA, SCL pins (PC1, PC0 on mega32)

 

David.

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

Thank you David,

 

I wrote the program and corrected all the errors , but when compiling it says "Packed library error: D:\AVR\cvavr2\lib\twi.lib(43): #error directive:  I/O Port used by the TWI is not defined"

So what do you think is the problem.?

I send two version of your code for you to see:

 

/*
 * PCF8574_read.c
 *
 * Created: 31-Mar-20 17:17:11
 * Author: David Prentice
 */
#include <mega32a.h>
#include <io.h>
#include <stdio.h>      //for NULL
//#include <TWI.h>
#include <twi.h>
#include <delay.h>

#define PCF8574 0x20    //7-bit Slave address
int i=0;
 bool ret;
 unsigned char read_value, send_data; 
void main(void)
{
    for(i=0;i<=3;i++) //Startup Led
    {
        PORTD.7=~PORTD.7;
        delay_ms(1000);
   
    
    twi_master_init(100);  //100kHz bus
    DDRD = 0xFF;
    while (1) {
        send_data = 0xF3;  //make bits 0,1,4,5,6,7 input
        ret = twi_master_trans(PCF8574, &send_data, 1, NULL, 0);
        PORTD = send_data;
        delay_ms(2000);
        send_data = 0xF2;  //make bits 1,4,5,6,7 input
        ret = twi_master_trans(PCF8574, &send_data, 1, &read_value, 1);
        PORTD = read_value; //read  1,4,5,6,7 input.   0,2,3 are output LOW
        delay_ms(2000);
    }
}
}

And this is another with your code added,:

 

#include <mega32a.h> 
#include <delay.h>
#include "TWI_Master.h"
#include <twi.h>
//#include <mega32a.h>
#include <io.h>
#include <stdio.h>      //for NULL
//#include <TWI.h>
//#include <delay.h>

#define PCF8574 0x20    //7-bit Slave address
//#include <twi_master.h>
#define SEND_DATA             0x01
#define REQUEST_DATA          0x02
#define READ_DATA_FROM_BUFFER 0x03
#define START 		       0x08 
#define Repeated_START 	 0x10
// Master Transmitter
#define MT_SLA_ACK       0x18
#define MT_SLA_NACK      0x20
#define MT_DATA_ACK      0x28
#define MT_DATA_NACK     0x30
#define MT_ARB_LOST      0x38
// Master Receiver
#define MR_ARB_LOST      0x38
#define MR_SLA_ACK       0x40
#define MR_SLA_NACK      0x48
#define MR_DATA_ACK      0x50
#define MR_DATA_NACK     0x58

#define TWI_GEN_CALL         0x20  // The General Call address is 0
// Sample TWI transmission commands
#define TWI_CMD_MASTER_WRITE 0x10
#define TWI_CMD_MASTER_READ  0x20

//TWCR    _SFR_IO8(0x36)
#define TWIE    0
#define TWEN    2
#define TWWC    3
#define TWSTO   4
#define TWSTA   5
#define TWEA    6
#define TWINT   7

static unsigned char TWI_buf[ TWI_BUFFER_SIZE ];    // Transceiver buffer
static unsigned char TWI_msgSize;                   // Number of bytes to be transmitted.
static unsigned char TWI_state = TWI_NO_STATE;      // State byte. Default set to TWI_NO_STATE.
static unsigned char TWI_statusReg_all;

interrupt [TWI] void TWI_ISR(void)  
{
  static unsigned char TWI_bufPtr ;
  
  switch (TWSR)
  {
    case TWI_START:             // START has been transmitted  
    case TWI_REP_START:         // Repeated START has been transmitted
      TWI_bufPtr = 0;                                     // Set buffer pointer to the TWI Address location
    case TWI_MTX_ADR_ACK:       // SLA+W has been tramsmitted and ACK received
    case TWI_MTX_DATA_ACK:      // Data byte has been tramsmitted and ACK received
      if (TWI_bufPtr < TWI_msgSize)
      {
        TWDR = TWI_buf[TWI_bufPtr++];
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to send byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
               (0<<TWWC);                                 //  
      }else                    // Send STOP after last byte
      {
        TWI_statusReg_lastTransOK = TRUE;                 // Set status bits to completed successfully. 
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
               (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
               (0<<TWWC);                                 //
      }
      break;
    case TWI_MRX_DATA_ACK:      // Data byte has been received and ACK tramsmitted
      TWI_buf[TWI_bufPtr++] = TWDR;
    case TWI_MRX_ADR_ACK:       // SLA+R has been tramsmitted and ACK received
      if (TWI_bufPtr < (TWI_msgSize-1) )                  // Detect the last byte to NACK it.
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
               (0<<TWWC);                                 //  
      }else                    // Send NACK after next reception
      {
        TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
               (0<<TWWC);                                 // 
      }    
      break; 
    case TWI_MRX_DATA_NACK:     // Data byte has been received and NACK tramsmitted
      TWI_buf[TWI_bufPtr] = TWDR;
      TWI_statusReg_lastTransOK = TRUE;                 // Set status bits to completed successfully. 
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                      // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|           // Initiate a STOP condition.
             (0<<TWWC);                                 //
      break;      
    case TWI_ARB_LOST:          // Arbitration lost
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag
             (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
             (0<<TWWC);                                 //
      break;
    case TWI_MTX_ADR_NACK:      // SLA+W has been tramsmitted and NACK received
    case TWI_MRX_ADR_NACK:      // SLA+R has been tramsmitted and NACK received    
    case TWI_MTX_DATA_NACK:     // Data byte has been tramsmitted and NACK received
//    case TWI_NO_STATE              // No relevant state information available; TWINT = “0”
    case TWI_BUS_ERROR:         // Bus error due to an illegal START or STOP condition
    default:     
      TWI_state = TWSR;                                 // Store TWSR and automatically sets clears noErrors bit.
                                                        // Reset TWI Interface
      TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins
             (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt
             (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests
             (0<<TWWC);                                 //
  }
}
void TWI_Master_Initialise(void)
{
  TWBR = TWI_TWBR;                                  // Set bit rate register (Baudrate). Defined in header file.
// TWSR = TWI_TWPS;                                  // Not used. Driver presumes prescaler to be 00.
  TWDR = 0xFF;                                      // Default content = SDA released.
  TWCR = (1<<TWEN)|                                 // Enable TWI-interface and release TWI pins.
         (0<<TWIE)|(0<<TWINT)|                      // Disable Interupt.
         (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // No Signal requests.
         (0<<TWWC);                                 //
}    
unsigned char TWI_Transceiver_Busy( void )
{
  return ( TWCR & (1<<TWIE) );                  // IF TWI Interrupt is enabled then the Transceiver is busy
}

unsigned char TWI_Get_State_Info( void )
{
  while ( TWI_Transceiver_Busy() );             // Wait until TWI has completed the transmission.
  return ( TWI_state );                         // Return error state.
}

void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize )
{
  unsigned char temp;

  while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.

  TWI_msgSize = msgSize;                        // Number of data to transmit.
  TWI_buf[0]  = msg[0];                         // Store slave address with R/W setting.
  if (!( msg[0] & (TRUE<<TWI_READ_BIT) ))       // If it is a write operation, then also copy data.
  {
    for ( temp = 1; temp < msgSize; temp++ )
      TWI_buf[ temp ] = msg[ temp ];
  }
  TWI_statusReg_all = 0;      
  TWI_state         = TWI_NO_STATE ;
  TWCR = (1<<TWEN)|                             // TWI Interface enabled.
         (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
         (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
         (0<<TWWC);                             //
}
void TWI_Start_Transceiver( void )
{
  while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.
  TWI_statusReg_all = 0;      
  TWI_state         = TWI_NO_STATE ;
  TWCR = (1<<TWEN)|                             // TWI Interface enabled.
         (1<<TWIE)|(1<<TWINT)|                  // Enable TWI Interupt and clear the flag.
         (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|       // Initiate a START condition.
         (0<<TWWC);                             //
}

unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )
{
  unsigned char i;

  while ( TWI_Transceiver_Busy() );             // Wait until TWI is ready for next transmission.

  if( TWI_statusReg_lastTransOK )               // Last transmission competed successfully.              
  {                                             
    for ( i=0; i<msgSize; i++ )                 // Copy data from Transceiver buffer.
    {
      msg[ i ] = TWI_buf[ i ];
    }
  }
  return( TWI_statusReg_lastTransOK );                                   
}

 int i=0;
 
   void twi_start(void){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);    	  	
	while(!(TWCR & (1<<TWINT))); 
   }
void twi_write(unsigned char data){
		TWDR = data;                       	
		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);		 
		while (!(TWCR & (1<<TWINT)));		                               
    }

unsigned char twi_read  (unsigned char get_data){
	//unsigned  char   get_data; 
	if((TWSR & 0xF8) == MR_SLA_ACK) {     	
    	TWCR = (1<<TWINT)| (1<<TWEN)| (1<<TWEA);    	
    while (!(TWCR & (1<<TWINT)));       
	 get_data=TWDR;	
	 TWCR = (1<<TWINT)|(1<<TWEN);   
	while (!(TWCR & (1<<TWINT)));	  
	return get_data;                         			      
  	}	                    
}

//This is David codes
//void twi_master_init(unsigned int bit_rate)
//  enables and initializes the TWI hardware for operating in master mode.
//Parameters:
//   bit_rate specifies the SCL clock frequency in kHz.
/*bool twi_master_trans(

            unsigned char slave_addr,

            unsigned char *tx_data,

            unsigned char tx_count,

            unsigned char *rx_data,

            unsigned char rx_count)
unsigned char read_value;
bool ret = twi_master_trans(0x20, NULL, 0, &read_value, 1);

*/
 void twi_stop(void){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); 	  	   	
}


  void MT_TWI(unsigned char data,unsigned char address_device)   //Master transmits the data to the address of the Slave 
 {                                            
  twi_start();
  twi_write((address_device<<1)&0xFE);
  twi_write(data);                             
  twi_stop();
 }

unsigned  char   get_data; 
unsigned  char  val;
unsigned char Senddata,Slaveaddress=0x20;
unsigned char messageBuf[4],firsttime =1;
unsigned char TWI_targetSlaveAddress,  TWI_operation=0,
                pressedButton =0, myCounter=0;
unsigned char TWI_Act_On_Failure_In_Last_Transmission ( unsigned char TWIerrorMsg )
{
                    // A failure has occurred, use TWIerrorMsg to determine the nature of the failure
                    // and take appropriate actions.
                    // Se header file for a list of possible failures messages.
                    
                    // Here is a simple sample, where if received a NACK on the slave address,
                    // then a retransmission will be initiated.
if ( (TWIerrorMsg == TWI_MTX_ADR_NACK) | (TWIerrorMsg == TWI_MRX_ADR_NACK) )
    TWI_Start_Transceiver();
    
  return TWIerrorMsg; 
}                 
bool ret;
 unsigned char read_value, send_data;                 
void main( void )
{
 TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);

// Bit-Banged I2C Bus initialization
// I2C Port: PORTC
// I2C SDA bit: 1
// I2C SCL bit: 0
// Bit Rate: 100 kHz
// Note: I2C settings are specified in the
// Project|Configure|C Compiler|Libraries|I2C menu.
  DDRA  = 0xFF;
  DDRC  = 0x00;
  DDRD=0xff;
   TWI_Master_Initialise();
 #asm ("sei") // global interrupt enable
  firsttime =1;
  twi_master_init(100);  //100kHz bus
 for(i=0;i<=3;i++) //Startup Led
    {
        PORTD.7=~PORTD.7;
        delay_ms(1000);
    }
    
    DDRD = 0xFF;
    while (1) {
        send_data = 0xF3;  //make bits 0,1,4,5,6,7 input
        ret = twi_master_trans(PCF8574, &send_data, 1, NULL, 0);
        PORTD = send_data;
        delay_ms(2000);
        send_data = 0xF2;  //make bits 1,4,5,6,7 input
        ret = twi_master_trans(PCF8574, &send_data, 1, &read_value, 1);
        PORTD = read_value; //read  1,4,5,6,7 input.   0,2,3 are output LOW
        delay_ms(2000);
    } 
 }
   /*  for(;;)
  {  
    if (firsttime == 1)
      {
      TWI_Master_Initialise();
      messageBuf[1] = 0xfF;
      firsttime =2; 
      }
     if (firsttime == 2)
      {
      TWI_Master_Initialise();
      messageBuf[1] = 0xfE;
      firsttime =1; 
      }  
      
    delay_ms(100); // Change this delay to get a different speed for the led flasher. 
     
     // if (pressedButton)       // Check if any button is pressed
    //{
      //do{temp = 1}      // Wait until key released    
      
      //while (1);
      //pressedButton =0 ; 
      
      switch ( pressedButton ) 
      {
        // Modification to Atmel test code to work on a Mega16 without a STK500 kit. 
        // Send a Address Call, sending a command and data to the Slave    
          case 0:      
         // messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
                                                        //  OxFE turns on led , OxFF turns off led 
          messageBuf[1] = 0xfF;                        // The second byte is used for the data. Turn on 0 led
          messageBuf[2] = 0xFF;                        // The third byte is used for the data. 8-16 all high 
          TWI_Start_Transceiver_With_Data( messageBuf, 3 ); 
           pressedButton = 2;
          break;
       
       
       
        case 1:      
          messageBuf[0] = TWI_GEN_CALL;     // The first byte must always consit of General Call code or the TWI slave address.
          messageBuf[1] = 0x10;             // The command or data to be included in the general call.
          TWI_Start_Transceiver_With_Data( messageBuf, 2 );
          break;

        // Send a Address Call, sending a command and data to the Slave          
        case 2:      
         // messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
                                                        //  OxFE turns on led , OxFF turns off led 
          messageBuf[1] = 0xfe;                        // The second byte is used for the data. Turn on 0 led
          messageBuf[2] = 0xFF;                        // The third byte is used for the data. 8-16 all high 
          TWI_Start_Transceiver_With_Data( messageBuf, 3 );
           pressedButton = 0;
          break;

        // Send a Address Call, sending a request, followed by a receive          
        case 3:      
          // Send the request-for-data command to the Slave
         // messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (FALSE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
          messageBuf[1] = TWI_CMD_MASTER_READ;             // The first byte is used for commands.
          TWI_Start_Transceiver_With_Data( messageBuf, 2 );

          TWI_operation = REQUEST_DATA;         // To release resources to other operations while waiting for the TWI to complete,
                                                // we set a operation mode and continue this command sequence in a "followup" 
                                                // section further down in the code.
                    
        // Get status from Transceiver and put it on PORTB
        case 4:
          PORTB = TWI_Get_State_Info();
          break;

        // Increment myCounter and put it on PORTB          
        case 5:      
          PORTB = ++myCounter;        
          break;
          
        // Reset myCounter and put it on PORTB
        case 6:      
          PORTB = myCounter = 0;        
          break;  
     // }
    }    

    if ( ! TWI_Transceiver_Busy() )
    {
    // Check if the last operation was successful
      if ( TWI_statusReg_lastTransOK )
      {
        if ( TWI_operation ) // Section for follow-up operations.
        {
        // Determine what action to take now
          if (TWI_operation == REQUEST_DATA)
          { // Request/collect the data from the Slave
           // messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_READ_BIT); // The first byte must always consit of General Call code or the TWI slave address.
            TWI_Start_Transceiver_With_Data( messageBuf, 2 );       
            TWI_operation = READ_DATA_FROM_BUFFER; // Set next operation        
          }
          else 
          if (TWI_operation == READ_DATA_FROM_BUFFER)
          { // Get the received data from the transceiver buffer
            TWI_Get_Data_From_Transceiver( messageBuf, 2 );
            PORTB = messageBuf[1];        // Store data on PORTB.
            TWI_operation = FALSE;        // Set next operation        
          }
        }
      }
      else // Got an error during the last transmission
      {
        // Use TWI status information to detemine cause of failure and take appropriate actions. 
        TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info( ) );
      }
    }

    // Do something else while waiting for TWI operation to complete and/or a switch to be pressed
    //__no_operation(); // Put own code here.

  }
    
    
    
/*  while(1)
  {
      Senddata=0xf3;
      MT_TWI(Senddata,Slaveaddress);
      
      PORTD=Senddata;
      delay_ms(2000);
     // TWI_Start_Transceiver( );
     PORTD=  TWI_Get_Data_From_Transceiver("2", 1 );
     // twi_read(get_data);
     //get_data;
      delay_ms(2000);
     Slaveaddress=0x20;
     Senddata=0xf2;
     MT_TWI(Senddata,Slaveaddress);
     PORTD=Senddata;
     delay_ms(2000);
     
   }*/
   
 // }*/

Both produce the same error  i.e"

D:\AVR\cvavr2\lib\twi.lib(43): #error directive:  I/O Port used by the TWI is not defined"

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

You should only have one target header file.  Either mega32a.h or io.h

 

I built and ran on a mega328p with PCF8574.   I can dig out a mega32 but it is a PCF8574A on that board.

 

The target chip must agree with the chip in the Project Configuration.

io.h uses the chip from Project Config.

 

Please just try the simple code that I posted.   Your v3.12 licence will work with TWI.h and any CodeWizard code too.

 

If you have several Codevision projects I would upgrade your licence.   The current v3.39 works seamlessly with AS7.0

 

David.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear David,

Thank you very much for your help and guidence. I up dated my CV to 3.38 and it works fine now.

My I pray God to save you and your family safe, and keep you away from all evilness.

Love you.

Aziz