CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C scanner code not working on PIC18F4550
Goto page 1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
tonkostz



Joined: 07 May 2011
Posts: 56
Location: Bulgaria

View user's profile Send private message

I2C scanner code not working on PIC18F4550
PostPosted: Tue Dec 24, 2024 8:16 am     Reply with quote

I having issues with comunicating with FM transmitter chip QN8007.
Chip by default is controlled by a STC12C5A60S2 mcu but many functions can't be used so my idea is to replace that mcu witn PIC18F4550 and control it myself.

According to the chip datasheet, default address is: 0101011 (0x2B)

I'm using i2c for the first time and i'm not sure how exactly works.
For example i want to communicate to a device register at address 0x01 and write in that register 0x80.

My defines are as follows:
Code:

#include <18F4550.h>
#device adc=10
#fuses HSPLL,PLL5,CPUDIV1,NOWDT,MCLR,NOLVP,USBDIV,VREGEN
#use delay(clock=48000000)
#use i2c(master,Fast=100000,sda=PIN_B0,scl=PIN_B1,SMBUS)  // Configure Device as Master


How should my code be?
Code:

i2c_start();
i2c_write(0x2B) //device address
i2c_write(0x01) //register address
i2c_write(0x80) //register data to be written
i2c_stop();
delay_ms(100);


Would you help with the right commands on the i2c bus?


Last edited by tonkostz on Thu Dec 26, 2024 4:14 am; edited 2 times in total
newguy



Joined: 24 Jun 2004
Posts: 1912

View user's profile Send private message

PostPosted: Tue Dec 24, 2024 10:24 am     Reply with quote

Base address of an I2C chip cannot be odd so I suspect that the address you have is the 7 bit address. Bit shift that left one (x2) for an 8 bit address of 0x56.
dyeatman



Joined: 06 Sep 2003
Posts: 1946
Location: Norman, OK

View user's profile Send private message

PostPosted: Tue Dec 24, 2024 3:49 pm     Reply with quote

Driver info for the chip is located here:
https://github.com/gabriel-tenma-white/qn8007_fm_tx

It looks like you can get all your register defines from here to avoid having to
start from scratch. Porting the code to CCS should be pretty straightforward
but will take some time since there are lot of functions.
_________________
Google and Forum Search are some of your best tools!!!!
tonkostz



Joined: 07 May 2011
Posts: 56
Location: Bulgaria

View user's profile Send private message

PostPosted: Wed Dec 25, 2024 12:15 am     Reply with quote

Thanks!

I wonder how the i2c reads/writes can be represented in this way?:
Code:
QND_WriteReg(CH_STOP, tS);

Maybe i have to define a function QND_WriteReg somewhere and use it multiple time without using i2c_write() each time?

It's very clear that we write in register CH_STOP the tS value.

How will be in CCS?
Code:

i2c_start();
i2c_write(DEVICE_ADDRESS); //should i write the device's address each time?
i2c_write(CH_STOP); //address of register CH_STOP
i2c_write(tS); //can i write the value tS in this way?
i2c_stop();
dyeatman



Joined: 06 Sep 2003
Posts: 1946
Location: Norman, OK

View user's profile Send private message

PostPosted: Wed Dec 25, 2024 6:53 am     Reply with quote

Yes, making your own function is the best approach.

Do a quick search on the term writereg and you will find a number of examples
how to make your own writereg type functions. Here is one:
http://www.ccsinfo.com/forum/viewtopic.php?t=59960&highlight=writereg

Also recommend using the I2C scanner in the Code Library to "find" the device
on the I2C bus and make sure you can communicate with it. If it doesn't "see"
the device you likely have I2C bus issues that also need to be addressed.
_________________
Google and Forum Search are some of your best tools!!!!
temtronic



Joined: 01 Jul 2010
Posts: 9372
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Dec 25, 2024 12:22 pm     Reply with quote

Yes, I 2nd the 'use I2C Scanner program' !!!

Also be sure you use the correct I2C buss pullup resistors.
4k7 for 5 volt PICs
3k3 for 3 volt PICs

are good starting values

Once you've confirmed the hardware IS there, then the rest is 'just' code......
tonkostz



Joined: 07 May 2011
Posts: 56
Location: Bulgaria

View user's profile Send private message

PostPosted: Thu Dec 26, 2024 3:07 am     Reply with quote

I have tried the I2C scanner program and it behaves strange. It shows Start and after that ACK with changing addresses in 2 seconds. After some time it stops on address EE and shows I2C: 112 (112 devices found?). The chip QN8007 is powered from +3.3V and the PIC +5V. There are 3K pull-up resistors to +3.3V. I have tried many things as slowing the mcu clock and using different options in #use_i2c with no result. I can confirm that the QN8007 is working well because i have the original board that controls it with STC mcu. Interesting thing there is that the STC mcu is powered from +4V, with no pull-up resistors for the SDA and SCL pins. Also there are 100ohms series resistor on both lines. The only thing i changed from the original i2c scanner code, is to use a 8x2 LCD display instead of using the serial port. Here is the code:
Code:

#include <18F4550.h>
#device adc=10
#fuses HSPLL,PLL5,CPUDIV1,NOWDT,MCLR,NOLVP,VREGEN,NOPROTECT
#use delay(clock=48000000)

#use i2c(master,slow,sda=PIN_B0,scl=PIN_B1)

#define LCD_E     PIN_D1                                 
#define LCD_RS    PIN_D0 
#define LCD_DB4   PIN_D2                           
#define LCD_DB5   PIN_D3                           
#define LCD_DB6   PIN_D6                       
#define LCD_DB7   PIN_D4 
#include "LCD8x2.c"

// This function writes the slave address to the i2c bus.
// If a slave chip is at that address, it should respond to
// this with an "ACK".   This function returns TRUE if an
// ACK was found.  Otherwise it returns FALSE.
int8 get_ack_status(int8 address)
{
 int8 status;

 i2c_start();
 status = i2c_write(address);  // Status = 0 if got an ACK
 i2c_stop();

 if(status == 0) return(TRUE);
 else return(FALSE);
}

void main()
{
 unsigned int8 i;
 unsigned int8 status;
 unsigned int8 count = 0;
 
 set_tris_b(0b00000011); //set B0 and B1 as inputs 0x03

 delay_ms(500); //needed 0.5s delay for the LCD
 lcd_init();

 lcd_gotoxy(1,1);
 printf(lcd_putc,"Start:  ");
 lcd_gotoxy(1,2);
 printf(lcd_putc,"        ");

 delay_ms(1000);

// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.

 for(i=0x10; i < 0xF0; i+=2)
   {
    status = get_ack_status(i);
    if(status == TRUE)
      {
       lcd_gotoxy(1,1);
       printf(lcd_putc,"ACK:%X    ", i);
       count++;
       delay_ms(2000); //2000
      }
    }

if(count == 0)
{
 lcd_gotoxy(1,1);
 printf(lcd_putc,"Nothing ");
 lcd_gotoxy(1,2);
 printf(lcd_putc,"        ");
}
else
{
 lcd_gotoxy(1,2);
 printf(lcd_putc,"i2c:%u  ",count);
}

while(1);

Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Thu Dec 26, 2024 5:24 am     Reply with quote

You cannot mix a 3.3v I2C device with a 5v PIC, without level translation
hardware.

Now actually there are ways.

The point is that the I2C _hardware_ requires the input signal on the I2C
bus to go up to 4v. Obviously an I2C bus pulled up to 3.3v won't do this.
Hence disaster.
You can work by using inputs on the PIC that support TTL signal levels,
and setting up a software I2C. Obviously means the code is a bit larger,
but this will work fine. If you look in the data sheet 'Pinout I/O DESCRIPTIONS',
and look for pins that say 'TTL'. In your case the hardware pins support this
when used for normal I/O, so if you change your I2C setup to:

#use i2c(master,slow,sda=PIN_B0,scl=PIN_B1, FORCE_SW)

it should work.
You may also be able to get it to work by telling the code to use SMBUS
signal levels instead of I2C. So;

#use i2c(master,slow,sda=PIN_B0,scl=PIN_B1, SMBUS)

This may work, but on some chips gives problems.

Otherwise you need an I2C level translator between the chips.
temtronic



Joined: 01 Jul 2010
Posts: 9372
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Dec 26, 2024 7:15 am     Reply with quote

As Mr. T points out you can't connect 3V peripherals to 5 V PICS, directly.
Other possible options are
1) use the 'L'ow voltage version of the 4550 (PIC18LF4550.. )
2) use another PIC that runs on 3 volts
3) use logic level translation between the 2

I suspect #3 is your best choice as you have an LCD module,which probably requires 5 volts

Probably 99.44% of all peripheral devices are 3 volts,so you may want to consider choosing a PIC like the 18F46K22 that can run on 3 or 5 volts, especially if you plan on many,many projects.

If you choose a 3 volt only PIC, you can run a 5 v LCD module. All it requires is a free timer to generate a square wave, 2 caps and 2 diodes to make a voltage doubler. One of those 'tips 'n tricks' I've used years ago.
tonkostz



Joined: 07 May 2011
Posts: 56
Location: Bulgaria

View user's profile Send private message

PostPosted: Fri Dec 27, 2024 4:05 am     Reply with quote

Update: I have checked with a scope and there are pulses on both pins SDA and SCL during the i2c scanner is running but the program does not find any device. Status never gets "0".
I have made more tests this time with different mcu PIC18F23K20. Now both the mcu and the fm transmitter chip QN8007 are powered from +3.3V. There are 3K3 pull-ups on the SDA and SCL pins.
Result is that the simple I2C scanner program won't find anything but keeps counting from the start address to the end address.
Once again to check if the slave chip is working i insert the original control board with the STC mcu and everything works - there is communication with the chip. Ideas?
In the QN8007 datasheet I2C is not mentioned anywhere. They say "2-wire serial control interface". If this is not I2C communication, what could it be and how to control it?
Here is my code now:
Code:

#include <18F23K20.h>
#device adc=10
#fuses INTRC_IO,NOMCLR,NOWDT,NOBROWNOUT,NOPROTECT
#use delay(clock=2M)

#use i2c(master,sda=PIN_C4,scl=PIN_C3)

#define LCD_DB4   PIN_C2
#define LCD_DB5   PIN_C0
#define LCD_DB6   PIN_C1
#define LCD_DB7   PIN_C7
#define LCD_RS    PIN_A7
#define LCD_E     PIN_A6
#include <LCD8x2.c>

// This function writes the slave address to the i2c bus.
// If a slave chip is at that address, it should respond to
// this with an "ACK".   This function returns TRUE if an
// ACK was found.  Otherwise it returns FALSE.
int8 get_ack_status(int8 address)
{
 int8 status;

 i2c_start();
 status = i2c_write(address);  // Status = 0 if got an ACK
 i2c_stop();

 if(status == 0) return(TRUE);
 else return(FALSE);
}

void main()
{
 unsigned int8 i;
 unsigned int8 status;
 unsigned int8 count = 0;

 delay_ms(500); //needed 0.5s delay for the LCD
 lcd_init();

 lcd_gotoxy(1,1);
 printf(lcd_putc,"Start:  ");
 lcd_gotoxy(1,2);
 printf(lcd_putc,"        ");

 delay_ms(1000);

// Try all slave addresses from 0x10 to 0xEF.
// See if we get a response from any slaves
// that may be on the i2c bus.

 for(i=0x10; i < 0xF0; i+=2)
   {
    status = get_ack_status(i);
    if(status == TRUE)
      {
       lcd_gotoxy(1,1);
       printf(lcd_putc,"ACK:%X    ", i);
       count++;
       delay_ms(2000); //2000
      }
    }

if(count == 0)
{
 lcd_gotoxy(1,1);
 printf(lcd_putc,"Nothing ");
 lcd_gotoxy(1,2);
 printf(lcd_putc,"        ");
}
else
{
 lcd_gotoxy(1,2);
 printf(lcd_putc,"i2c:%u  ",count);
}

while(1);
}

temtronic



Joined: 01 Jul 2010
Posts: 9372
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 27, 2024 7:28 am     Reply with quote

OK, I got curious..downloaded a datasheet for the qn8007

It is NOT 'I2C', it IS 'I2S' !! Chapter 3.1...

Sounds like a variation on the I2C standard that Philips came out with ,decades ago. I 'think' it's used for audio / home use type equipment ?? 'S' for Sound or Stereo or Simple ?? I'm sure others will know.

You'll have to Google and read up about it to see what the differences are.

Also in my quik look, I see a pin used to control how to access it,so again, you'll need to be sure you've got the hardware wired properly.
3volt PIC, 3k3, 3 volt peripheral is great,so that's a great start.

ok, one google ...
What is the difference between I2S and I2C (I2C vs I2S)? I2C is 2 wire protocol and I2S is 3 wire protocol. I2C supports clock stretching and I2S does not have clock stretching. I2C has an extra overhead start and stop bits and I2S does not have any start and stop bits.

so you WILL have to do a lot more reading !!!

I found the QN8007B.pdf, well google did. It EXPLAINS how to setup the THREE wire I2S connections and HOW communications is done. Chapter 6. also has ALL the registers and what they do.....
tonkostz



Joined: 07 May 2011
Posts: 56
Location: Bulgaria

View user's profile Send private message

PostPosted: Fri Dec 27, 2024 9:56 am     Reply with quote

I2S is the Digitial Audio Interface Protocol. Chip can transmit music from USB flash too which communicates on different pins via I2S.


Control is via 2-wire or 3-wire serial control interface and it is properly configured on the board - 2-wire interface is selected and the default 7-bit IC address is 0101011.
All looks like I2C to me - see the timing diagrams. There is a ACK bit too.
I see all the registers but i want to make sure i am able to communicate with the chip and then i will think about the registers.
temtronic



Joined: 01 Jul 2010
Posts: 9372
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 27, 2024 10:22 am     Reply with quote

so , is SEB high or low ? That's really important to confirm.
I've never used I2S but there might be something it needs that I2c doesn't.
Maybe others who have used it can reply soon !!!
tonkostz



Joined: 07 May 2011
Posts: 56
Location: Bulgaria

View user's profile Send private message

PostPosted: Fri Dec 27, 2024 10:36 am     Reply with quote

SEB is connected to ground - it is low. I2S is only for the audio to the chip on different pins. SDA and SCL are for the 2-wire serial control interface.
Ttelmah



Joined: 11 Mar 2010
Posts: 19649

View user's profile Send private message

PostPosted: Fri Dec 27, 2024 12:42 pm     Reply with quote

The interface in 2 wire mode is I2C on the control interface. It should
respond to the scanner program.
One important thing though. This chip is very slow to wake. You need
to wait about 3/4 second after the PIC wakes before making any attempt
to talk to it.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3, 4  Next
Page 1 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group