I2c Converter

PCF8574 is 8-bit I2C/Parallel converter.
It is used in Arduino CPUs extend pins.
Expecially with LCD.
There is also a Microchip version of the program.

PCF8574.jpg
www.mjkdz.com.JPG

'= ===================
' here is Arduino version
'===================
How to find I2C address
from http://todbot.com/blog/2009/11/29/i2cscanner-pde-arduino-as-i2c-bus-scanner/

void scanI2CBus(byte from_addr, byte to_addr) {
byte data = 0; // not used, just a ptr to feed to twi_writeTo()
for( byte addr = from_addr; addr < = to_addr; addr++ ) {
byte rc = twi_writeTo(addr, &data, 0, 1, 0);
if( rc == 0 ) {
Serial.printl("Device found at address ");
Serial.println(addr,DEC);
}

}
}

Here is Microchip PIC version

put 4k7 resitors I2C from i2c pins to +3.3V or 5V
18.1.2023 Pekka OH3GDO
#include <16F886.h>
#fuses INTRC_IO, NOMCLR, NOLVP
#fuses NODEBUG, NOPROTECT, NOWDT//, WDT512
#USE DELAY(INTERNAL=8MHz)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,errors)
#USE I2C(I2C1, MASTER, FAST=100000, FORCE_HW) //clock = C.3 CLand data oisC.4 DTA, Remember up resistors 4k7 to power supply

#define LCD_SDA PIN_C4
#define LCD_SCL PIN_C3

#use i2c(master, sda= LCD_SDA, scl= LCD_SCL,FORCE_HW)
/*===============================================
look for i2c-address from OH3GDO
===============================================*/

void scanI2CBus(byte from_addr, byte to_addr) {
unsigned int8 found;
unsigned int8 addr;
unsigned int8 data = 0; // not used, just a dummy data

for( addr = from_addr; addr < to_addr; addr++ )
{

i2C_start();
i2C_write( addr); // search address
i2C_write( 0); // command mode
found=i2C_write( 0); // data dummy
if( found== 0 ) {
printf("\r I2C Device found at address 0x%x ",addr);

}
i2C_stop();

}
}
void main ()
{
while(1)
{
scanI2CBus(0, 0xFF);
delay_ms(4000);
}
}
I found sensor BMP280

I2C Device found at address 0xec

It was right

pirilevyKUVA.jpg

Here is my radio circuit
==
The responce for SSD1306 0.9"LCD (3.3V) or LCD MC21605WD-BNMLW.V2 (5V). They both gave 0x78

I2C Device found at address 0x78

Here is LCD I2C address for MC1605A6WD-BNMLW-V2

I2C.jpg

Here is Youtube picture

i2CLCD.jpg
Vuonna 2022 ostin erään LCD1602 laitteen.
Siinä tuli mukana I2C laite.

Kokeilin sitä tällä ohjelmalla ja se antoi:
I2C Device found at address 0x4e

No siinä oli kuitenkin sama mikroppiiri PCF8574T
Siinä oli liittimet A0,A1 ja A2 tai oikeastaan avoimet juotokset auki.
Tosin osoitejohdit olivat piilossa.

0x78 on binäärisenä 01111000 ja
0x4E on binäärisenä 01000111
Siis ei lainkaan yhteistä, mutta sama mikropiiri, miksi?
Kun katsoin datalehteä PCF8574AT, niin siellä oli kaksi osoitetta toinen PCF8574 0x40- 0x4e ja toinen PCF8574A 0x7-0x7e.
Siis testaa laittesi!
Älä luota pelkään tunnukseen vaan mittaa laitteesi.

Sitten luin DS1307 osoitetta.
Sen pitäisi olla 0xD0 kirjoitettaessa ja 0xD1 luettaessa.
En kuintekaan saanut muuta kuin ei löydy osoitetta,

Mittasin kaikki piiriin liittyvät sähköt yleismittarilla ja oskilloskoopilla.
Piirin oskillaattori ei toiminut, vaikka alustin sen omasta mielestäni oikein.

Mitasin sen prosessorin piirin I2C testilaaiteella ja ulkoisella PCF8570 piirillä, joka antoi ihan oikean osoitteen, mutta ei DS1307 ei antanut mitään.
Vaihdoin uuden pintaliitospiirin, käytin toista kidettä, mutta DS1307 ei antanut mitään elonmerkkiä.
Nuo piirit olivat ihan uusia.

Mikä vika?

Tein ulkopuolisen oskillaattorin 32kHz

osc.jpg

ja laitoin sen DS1307:n nastaan 1 ( 2 ei käy)
Mutta, sama tulos ei löydy osoitetta,

#include <16F18857.h>
#FUSES NOWDT // Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO Internal External Switch Over mode enabled
#FUSES NOBROWNOUT //No reset when brownout detected
#FUSES NOPUT //No power Up Timer
#FUSES NOCPD //No EE protection
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOFCMEN //Fail-safe clock monitor enabled
#FUSES NOIESO //Internal External switch over mode disabled
#FUSES NOMCLR //Master Clear pin not enabled

#device ADC=10 *=16 // valitaan tarkin ADc-muunnin
#use delay(internal=32MHz,restart_wdt) // oi 32Mhz

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8 ,errors )
#use delay(clock=32000000,RESTART_WDT)

void main ()
{
delay_ms(100);
output_high( PIN_B0);
printf("\r Probyte 32khZosc");

While(1)
{
output_high(PIN_B0);
delay_us(30/2);
output_low(PIN_B0);
delay_us(30/2);
}
}
===
Nyt 20.1.2023 DS1307 toimii!
Siinä meni kolme päivää.
Mittasin oskillaattoria eri kiteillä, DS1307 ei toiminut.
Vaihdoin DS1307 ei auttanut.

Yritin käyttää I2C testilaitetta, mutta ei auttanut, koska laite ei ollut saanyt käynnistys komentoa ja oskillaattorin käyntikomentoa.

Tässä on pieni sarjaliikenneportin tiedosto
TIME: 15:04:14
DATE: 20.01.2023
index 15 ready=0 rec 0 timex=2301205150200
TIME: 15:04:15
DATE: 20.01.2023

Tuossa timex = sarjaliikenteeltä tullut asetustiedot.
Siinä on vielä '#' merkki, joka sanoo, että nyt alkaa ajan asetustiedosto tulla.
Nyt voin jatkaa tuota piirilevyn toimintaa eteenpäin.
Siis mikään ei toimi, jos ei ole tullut I2C oikeaa komentoa!
==
Laite lakkasi taas toimimasta!
Etsin vikaa ohjelmasta, mutta kun laitoin pariston paikoilleen, niin se alkoi toimia!.
Sitten aloin kokeilla 24LC512 eeprom muistia.
Sen koko on 512kbittiä eli 64ktavua
Se on I2C muisti ja se on samassa I2C väylässä kuin tuo kello.
Sekään ei toiminut alkuksi

PUHE.jpg

Minula ei ollut vielä oikeata SMD-kokoista muistia, mutta laitoin DIP8 24LC512 muistipiirin samaan väylään ulkoiseen testilevyyn.
Ei toiminut, kokeilin varmaan 20:llä eri ohjelmala,
Testasin I2C väylää oskilloskoopilla.
Aina kun laitoin kirjoitustilan päälle, ohjelma jäi siihen.
Olin alustanut I2C väylän, mutta sekään ei auttanut.

Tässä on kuva kun yritin kirjoittaa 1 osoitteeseen 1.
Ei onnistunut

kirjoitus.jpg

Sitten tässä on kun kijoitus teki viimeistä kirjoustaan ikuisesti

lopetus.jpg

Noin neljän päivän kuluttua yhtäkkiä laite alkoi toimimaan normaalisti.

Tässä on koko ohjelma, jossa valitaan ensin kirjoitus tai lukufunktio, sitten osoite (0x0000— 0xffff), sittee 1-31 merkkiä, jotka kirjoitetaan EEPROMille

 #include <18F2620.h>
#device ADC=10
#FUSES  WDT                    //No Watch Dog Timer
#fuses INTRC_IO,NOWDT,NOPROTECT,noMCLR,NOLVP
#FUSES WDT32768                  //Watch Dog Timer uses 1:128 Postscale 32Mhz/4/128=62500Hz
#use delay(internal=32MHz)
#use rs232(Baud=9600, UART1, ERRORS,restart_wdt)     //aseta BAUD rate  RS232:lle

#define EEPROM_SDA PIN_C4       //määrittele  I2C nastat  EEPROM:lle
#define EEPROM_SCL PIN_C3          //lisää 2K vastukset I2C nastoista +5V 

#include <24LC512.c>     //Lataa  EEPROM driver
#include <string.h>      //String käsittely
#include <stdlib.h>      //standard IO funktiot 
#include <input.c>       // ja input.c

#define BUFFLEN 32     // kuinka monta biitiä kerralla, oikestaan 31 kpl  

unsigned int16 address=0;  // tässä eepromin 24LC512 osoite max 0xffff 
void kirjoita () 
{ 
 unsigned char inString[BUFFLEN];                   //muisti mihin data alaitetaan aluksi, 
printf("\rkirjoita");  

   printf("\rAnna merkkijonosi (mas 31) 24LC512 piirin kirjoitukselle I2C:llä osoitteesta %lx alkaen \r", address);
   InputKbhit(); 
   //gets(inString);
   //gets, on werittäin vaarallinen. Jos annant yhdenkin merkin likaa 
   //kuin mitä oletvarannut, tuloksena on katastrofi.
   // Käytä get_string sensijaan, se sallii maksimipituuden stringille

   get_string(inString, 32); //Max 31 merkkiä
   printf("\rAnnoit %s" ,inString);

   printf("\rKoko  stringissä %s oli %ld" , inString, strlen(inString));

   init_ext_eeprom(); // alusta I2C piiri siten, että nastat ovat avonaisia
   printf("\rNyt kirjoitetaa %s eepromiin .." , inString);
   write_ext_eeprom_bytes(address , inString, strlen(inString)+1);  
}
void lue()
{
 unsigned char inString[BUFFLEN];                   //muisti mihin data alaitetaan aluksi,  
   init_ext_eeprom(); // alusta I2C piiri siten, että nastat ovat avonaisia
printf("\rlue %lXHex ",address); 
   //Tämä luku sisältää null terminatorin.
   read_ext_eeprom_bytes(inString, address, BUFFLEN);
   printf("\rTakasin =%s", inString);
} 
// anna sarjaliikentellää EEPROMIN osoite minne data kirjoitetaa anna viidell kirjaimella esim 65535 ) 0xFFFF
void eepromosite() 
{  

int8 count=0;  
char instr; 
address=0; 
 InputKbhit(); 
 printf("\rAnna eeprom osoite desimaalisen, näytetään myös xxxx Hex:na"); 
while (count<5) 
{ 
instr=getch();
address *=10; 
if( instr>0x2F && instr<0x3A) {
 address  +=(instr-0x30) ;
  count++; 
 printf("\rosoite %lu %lx count %d",address,address, count ); 

}
}  

} 
void valinta ()
{ 
 unsigned int8 i=0;
  printf("\r valitse kirjoita=1, lue=2");  
    while(i!='1' && i!='2') 
    {
   i=getch();  
    }
    printf("\r tuli %c", i);
   if( i=='1') 
   {  
     eepromosite();
     kirjoita(); 
   }
   if(i=='2') {   
     eepromosite(); 
     lue(); 
   } 
       printf("\rloppu"); 
} 
void WriteRead ()
{ 
  //Testausfuktio EEPROM:lle 

   unsigned char inString[BUFFLEN];                   //muisti mihin data alaitetaan aluksi, 

   printf("\rAnna merkkijonosi (mas 31) 24LC512 piirin kirjoitukselle I2C:llä osoitteesta %lx alkaen \r", address);
   InputKbhit(); 
   //gets(inString);
   //gets, on werittäin vaarallinen. Jos annant yhdenkin merkin likaa 
   //kuin mitä oletvarannut, tuloksena on katastrofi.
   // Käytä get_string sensijaan, se sallii maksimipituuden stringille

   get_string(inString, 32); //Max 31 merkkiä
   printf("\rAnnoit %s" ,inString);

   printf("\rKoko  stringissä %s oli %ld" , inString, strlen(inString));

   init_ext_eeprom(); // alusta I2C piiri siten, että nastat ovat avonaisia
   printf("\rNyt kirjoitetaa %s eepromiin .." , inString);
   write_ext_eeprom_bytes(address , inString, strlen(inString)+1);  
   // kirjotus kestaa noin 5ms/ korjoitusoperaatio 
   printf("\rKirjoitus valmis. Luetaan takaisin ");

   //Luku on nopeaa.32byteä on eneintään sallittu  bufferiin
   //Tämä luku sisältää null terminatorin.
   read_ext_eeprom_bytes(inString, address, BUFFLEN);
   printf("\rTakasin =%s", inString);
}
// pääohjelma alkaa 
void main()
{
delay_ms(10);
printf("\rProbyte %s",__date__);

while(1) 
valinta(); 

}

Pekka OH3GDO

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License