View previous topic :: View next topic |
Author |
Message |
Doglao
Joined: 26 Mar 2007 Posts: 11
|
MCP3021 don't work! |
Posted: Wed Oct 31, 2007 10:11 am |
|
|
Hi there!
I make a code to comunicate with a i2c mcp3021 device but it don'work!
what's wrong with my code?
Code: | struct DoisBytes
{
int iLsb;
int iMsb;
};
union Junta_dados
{
int16 Total_ad;
struct DoisBytes Msb_Lsb;
}Valor_ad;
int lsb;//varialvel do byte baixo do mcp3021
int msb;//varialvel do byte alto do mcp3021
//*AUTHOR Douglas Ricardo Dos Santos Pereira
//*PURPOSE Le o expander mcp23016 suas entradas
//*DATE_CREATED 01/06/2006
//*CHANGES
int16 Read_ad(){
int16 temp_pressao;
i2c_start();
i2c_write(0b11011001); //coloca endreco do escravo e como escrita
msb = i2c_read(1); //comando de ler o msb
lsb = i2c_read(0); //comando de ler o lsb
i2c_stop();//finaliza leitura
delay_us(50);
Valor_ad.Msb_Lsb.iLsb=lsb;
Valor_ad.Msb_Lsb.iMsb=msb;
Valor_ad.Total_ad = Valor_ad.Total_ad>>2; // ajusto os bits
temp_pressao=Valor_ad.Total_ad;
return temp_pressao;
} |
and the main code
Code: | #include <16F628a.H>
#use delay(clock=4000000)
#fuses XT,NOWDT,PROTECT,PUT,NOBROWNOUT,NOLVP
#use i2c(master, scl=pin_a2 ,sda=pin_a3)
#use fast_io(a)
#use fast_io(b)
int16 Valor_pressao;
void main()
{
set_tris_a(0b00111111);
set_tris_b(0b00000000);
setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_64);//timer0 com clock interno e prescaler dividindo por 64
set_timer0(155);
lcd_init(); // Inicio obrigatorio
lcd_setcursor(0,0); // ajusta cursor invisivel e modo fixo
// TODO: USER CODE!!
while(true){
Valor_pressao=read_ad();
printf(lcd_putc, "%u ", Valor_pressao);
}
} |
this is not a precision code to show a converted value, is a very simple attempt to comunicate with mcp3021.
please what can I do to fix it?
Thanks! _________________ Breaking rocks in the hot sun!
Doglao |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Oct 31, 2007 10:52 am |
|
|
I think you have your bits the wrong way around!
i2c_write(0b11011001);
Should be
i2c_write(0b10011011); |
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Wed Oct 31, 2007 11:39 am |
|
|
Thanks Wayne_!
I'm going to prove with this change, is need firstly to send the device code as lsb. so! this seam like this:
Code: | i2c_write(0b10011011); // first four bits is the device code fallowed by the three address bits
// and finished with a bit that said to device is read or write operation by the master, |
very thanks, I return the results _________________ Breaking rocks in the hot sun!
Doglao |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Wed Oct 31, 2007 1:37 pm |
|
|
I would suggest _not_ using fast_io and not trying to set the tris. Just let the compiler take care of things for the I2C bus.
What is the full part number for the A/D? The address is dependant on the part number. Check out the data sheet thoroughly to see what address to send.
Ronald |
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Wed Oct 31, 2007 1:42 pm |
|
|
Hi! Wayne_
is not running yet! I believe that need a delay time more great than the current for each calling to the read_ad function, but I make the changes and not run to.
my circuit is the same that I use with other i2c device that run perfectly _________________ Breaking rocks in the hot sun!
Doglao
Last edited by Doglao on Wed Oct 31, 2007 2:02 pm; edited 1 time in total |
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Wed Oct 31, 2007 2:00 pm |
|
|
Thanks Ronald!
I'm using the default address 101 because the part don't was ordered from microchip.com with a special address. this was buyed from a supplier informal , but is not a bad idea to probe with other addresses.
I return the results. _________________ Breaking rocks in the hot sun!
Doglao |
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Wed Oct 31, 2007 6:09 pm |
|
|
is not working! I make the changes in the configuration of porta letting the compiler set your configurations and also change all addresses possibles and not working yet.
is my code wrong on theirs commands?
Code: | i2c_start();
i2c_write(0b10011011); //coloca endreco do escravo e como escrita
msb = i2c_read(1); //comando de ler o msb
lsb = i2c_read(0); //comando de ler o lsb
i2c_stop();//finaliza leitura |
thanks! _________________ Breaking rocks in the hot sun!
Doglao |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 31, 2007 6:51 pm |
|
|
Do you have 4.7K pullup resistors on the SDA and SCL signals ?
They are required by the i2c specification. |
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Thu Nov 01, 2007 11:32 am |
|
|
Thanks to reply PCM Programmer!
Yes !! are existing pullups with those resistors that you mentioned in both lines sda and scl. and this circuit work well with other device 12c mcp23016 that I use in other project. I think that my code is not reliable with the datasheet recommendations.
Thanks again! _________________ Breaking rocks in the hot sun!
Doglao |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Thu Nov 01, 2007 12:12 pm |
|
|
Ok. So, post the full part number and the address that you are attempting to write to. |
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Thu Nov 01, 2007 12:53 pm |
|
|
Thanks Ronald!
MCP3021A5T-E/OT
the address that I use is 101 that match with the A5 address options of partnumber. _________________ Breaking rocks in the hot sun!
Doglao |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Nov 01, 2007 1:27 pm |
|
|
Doglao wrote: | is my code wrong on theirs commands?
Code: | i2c_start();
i2c_write(0b10011011); //coloca endreco do escravo e como escrita
msb = i2c_read(1); //comando de ler o msb
lsb = i2c_read(0); //comando de ler o lsb
i2c_stop();//finaliza leitura |
| Have you tried to swap the acknowledge parameter in the two read commands?
I looked at the Microchip Application note AN845 for the similar MCP3221 chip and there they do first an ACK0 and then ACK1. So it becomes:
Code: | i2c_start();
i2c_write(0b10011011); //coloca endreco do escravo e como escrita
msb = i2c_read(0); //ACK 0
lsb = i2c_read(1); // ACK 1
i2c_stop();//finaliza leitura |
|
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Thu Nov 01, 2007 1:51 pm |
|
|
The terminology can be a bit confusing here. The command i2c_read(1), which is the default, tells the Master to send an ACK, negative pulse on the SDA line, to the Slave. An i2c_read(0) sends a NOACK. The proper communication sequence is:
Code: | i2c_start();
i2c_write(address);
msb = i2c_read(1);
lsb = i2c_read(0);
i2c_stop(); |
This would correspond with the I2C standard to send a NOACK on the last read(which tells the slave that the read sequence is over) and it is what the app note states to do.
The most likely problem is that the incorrect address is being sent. That's why I asked for the complete part number of the A/D so I could tell what address should be sent.
Ronald |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 01, 2007 2:46 pm |
|
|
Try a more simple program:
Code: | #include <16F628A.H>
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#use i2c(master, scl=PIN_A2, sda=PIN_A3)
#include <flex_lcd.c>
//-----------------------------------
#define MCP3021_READ_ADDR 0b10011011
int16 read_mcp3021(void)
{
int8 lsb;
int8 msb;
int16 retval;
i2c_start();
i2c_write(MCP3021_READ_ADDR);
msb = i2c_read();
lsb = i2c_read(0);
i2c_stop();
retval = make16(msb, lsb) >> 2;
return(retval);
}
//============================
void main()
{
int16 result;
lcd_init();
while(1)
{
result = read_mcp3021();
printf(lcd_putc, "\f%lx ", result);
delay_ms(500);
}
} |
|
|
|
Doglao
Joined: 26 Mar 2007 Posts: 11
|
|
Posted: Thu Nov 01, 2007 4:06 pm |
|
|
Thanks for all!
it is working now!
I put a 11us delay before read the data, this delay is necessary to make a acquisition time Tacq(1.12usec) plus Conversion Time Tconv(8.96) and this work well, the values changing linearity. the other thing that I know now, is to join msb and lsb with make16() command.
very very very thanks!! _________________ Breaking rocks in the hot sun!
Doglao |
|
|
|