Hello,
to put it simply, i have given it my all and failed trying to make an IR sensor work with the IIC module on my board. I have read all the IIC app notes, search this forum back and forth...read HCS08 unleashed and now i simply have to ask for help.
My dilemma:
-I am new to programming so thats a handicap right there
-my code only seems to WORK only when i step line by line while in debug mode
-i have scoped my signals and they appear to be functioning (only in debug mode)
-Once i hit the run button, the code completes one loop then freezes at
while (!(IICS_IICIF)); // <--- stops here during "free run"
When this occurs, my SDA line is held low by the sensor. It stops at the same place even when i disable the watchdog.
The sensor http://www.robotshop.us/solarbotics-i2c-it-ir-rangefinder-1.html
comes with code for PICS and other processors, and it appears to be very easy to work with, but i cant get it to work with what i have (MC9S08SH)
MY CODE:
--------------------------------------------------------------------------------
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#define trimvalue 0xFFAE //debugger calculated trim value
#define LED3 PTCD_PTCD1
#define LED4 PTCD_PTCD0
#define IRaddress 0x20
#define IRreceive 0
#define IRtransmit 1
#define inch 1
#define cm 2
#define raw 3
unsigned int data1,data2,data3,data4; //for data and testing
/*SCI setup*/
void SCI_init(void){
SCIBD = 26; //set baud rate to 19200= 8MHz/(16*(SCIBD))
SCIC2 =0b00001100; //enable receive and transmit
}
/* simple software delay */
void delay (unsigned int long value){
for (;value<=0;value--)__RESET_WATCHDOG();
}
/*MCU setup*/
void MCU_init (void){
ICSTRM = trimvalue; //set to calcuated trim value
PTCDD = 0b00000011; // make PTC0,1 output for leds
SPMSC1_BGBE =1; //enable bandgap buffer.
}
/*IIC setup*/
void IIC_init(void){
IICC1_IICEN = 1; //enable module IIC module
IICF_MULT= 0x01; //divide by 2
IICF_ICR= 0x14; //divide by 80; (50khz)
}
/*master send function call*/
void master_send (void){
IICC1= 0b10110000; //iic enable, no iterrupt,master,transmit,ack on,)
return;
}
/*master receive function call*/
void master_receive (void){
IICC1= 0b10101000;
return;
}
/*iic disable*/
void iic_disable(void){
IICC1_IICEN = 0; //disable iic module
return;
}
void main(void) {
EnableInterrupts; /* enable interrupts */
MCU_init();
SCI_init();
IIC_init();
SCID=0x22; // test to check reset
for(; {
LED3=1;
master_send();
IICD=0x20<<1|0; //write address, put in receive mode
while (!(IICS_IICIF));
IICS_IICIF = 1;
while(IICS_RXAK); // check for RX ack;
//IICC_RSTA=1; //restart send
IICD=2; // ask sensor to send in CM
while (!(IICS_IICIF)); // <--- stops here during "free run"
IICS_IICIF = 1;
while(IICS_RXAK); // check for RX ack;
IICC_RSTA=1; //restart send
IICD=0x20<<1|1; //write address, put in transmit mode
delay(10000);
while (!(IICS_IICIF));
IICS_IICIF = 1;
while(IICS_RXAK); // check for RX ack;
//--------------------------------
IICC_TX=0; //switch to receive mode
data1=IICD; //dummy read!! <--reads sensor value!!
IICC_TXAK = 1; // acknowledge disable; <-- have tried swapping bits and places
IICC_MST = 0; // generate stop signal;
data2 = IICD; // read correct data;
if(SCIS1_TDRE ==1){ //serial for debug
SCID=data2;
}
__RESET_WATCHDOG(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
thanks in advance.
Solved! Go to Solution.
I finally got the sensor to work. Thanks Dave for the suggestions about using delays to troubleshoot. I think what i was missing all along might have been
- resend the start command between write and read
- disable the iic module when i have finished reading the data (otherwise on the next cycle things froze up)
- only setting MST=0 did not help ...hence had to disable the whole iic module.
the final code is shown below. Thanks once more
// this version of code works.
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#define trimvalue 0xFFAE //debugger calculated trim value
#define LED3 PTCD_PTCD1
#define LED4 PTCD_PTCD0
#define IRaddress 0x20
#define IRreceive 0
#define IRtransmit 1
#define inch 1
#define cm 2
#define raw 3
volatile unsigned int data1,data2,data3;
/*SCI setup*/
void SCI_init(void){
SCIBD = 26; //set baud rate to 19200= 8MHz/(16*(SCIBD))
SCIC2 =0b00001100; //enable receive and transmit
}
/* simple software delay */
void delay (unsigned int long value){
for (;value>0;value--)__RESET_WATCHDOG();
}
/*MCU setup*/
void MCU_init (void){
ICSTRM = trimvalue; //set to calcuated trim value
PTCDD = 0b00000011; // make PTC0,1 output for leds
SPMSC1_BGBE =1; //enable bandgap buffer.
}
/*IIC setup*/
void IIC_init(void){
IICC1_IICEN = 1; //disable module IIC module
IICF_MULT= 0x10; //divide by 4 01
IICF_ICR= 0x00; //divide by 40; 07
}
/*master send function call*/
void master_send (void){
IICC1= 0b10111000; //iic enable, no iterrupt,master,transmit,ack on,)
return;
}
/*master receive function call*/
void master_receive (void){
IICC1= 0b10101000;
return;
}
/*iic disable*/
void iic_disable(void){
IICC1_IICEN = 0; //disable iic module
IICD=0;
return; //write zeros to iic data register.
}
void main(void) {
EnableInterrupts; /* enable interrupts */
MCU_init();
SCI_init();
IIC_init();
SCID=0x22; // test to check reset (help debug)
for(; {
delay (10000); //allow time for sensor to initiate!
//-----setup sensor units
LED3=1; // to help debug
master_send(); //configure as master, transmit mode
IICD=(0x20<<1)|0; //send address and write bit
delay (10);
while (!IICS_TCF)__RESET_WATCHDOG(); //wait until transmission finishes
delay (10);
IICD= cm; //tell sensor to send units in CM
delay (10);
while (!IICS_TCF)__RESET_WATCHDOG(); //wait until transmission finishes
delay(10);
if(IICS_RXAK==0){
LED4=~LED4; //to help debug
}
IICC1_RSTA=1 ; //set restart bit
//--------read sensor
master_send();
delay (10);
IICD=(0x20<<1)|1; //send address and receive bit
delay (10);
while(!IICS_TCF)__RESET_WATCHDOG(); //wait for trans to complete
master_receive(); //put in receive mode
data1 = IICD; //dummy read
while(!IICS_TCF)__RESET_WATCHDOG(); //wait for trans to complete
IICC_TXAK=1; //No ACK
data2 = IICD; // REAL DATA
IICC1_MST=0; //release bus
iic_disable(); //disable iic module all together.
//--------serial transmit
if (SCIS1_TDRE==0){ //if not ready to send wait
__RESET_WATCHDOG();
}
SCID=data2;
__RESET_WATCHDOG(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
I will clean things up later on....
As you say your code works when you single step, perhaps you are not meeting a timing requirement when you run at full speed. Try putting delays in between the preceeding few lines. If this works you can hone down the delays to find the problem area.
By the way, your delay routine looks wrong. You have for(;value<=0;value--), this should be
for(;value>=0;value--) assuming you are supplying positive values for value. (You could of course change this to for(;value>0;value--) if you wanted to use unsigned values).
DRich- thanks for pointing out the delay error.
I also suspect i am having a timing/sequence issue. I have tried twicking the IIC baud rate and adding delays but it doesnt work either....(still get stuck at the same point).
what i dont understand is why the sensor appears to be holding the SDA line low after the first loop, and why the processor thinks it getting the first ACK but not the second!! (on the second loop around). I have been working on this for almost a week and am at the point of giving up and using an analog sensor.....
I will post the sample code for PICS and maybe someone will be able to point out something I'm missing.
Ill keep you posted.
I finally got the sensor to work. Thanks Dave for the suggestions about using delays to troubleshoot. I think what i was missing all along might have been
- resend the start command between write and read
- disable the iic module when i have finished reading the data (otherwise on the next cycle things froze up)
- only setting MST=0 did not help ...hence had to disable the whole iic module.
the final code is shown below. Thanks once more
// this version of code works.
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#define trimvalue 0xFFAE //debugger calculated trim value
#define LED3 PTCD_PTCD1
#define LED4 PTCD_PTCD0
#define IRaddress 0x20
#define IRreceive 0
#define IRtransmit 1
#define inch 1
#define cm 2
#define raw 3
volatile unsigned int data1,data2,data3;
/*SCI setup*/
void SCI_init(void){
SCIBD = 26; //set baud rate to 19200= 8MHz/(16*(SCIBD))
SCIC2 =0b00001100; //enable receive and transmit
}
/* simple software delay */
void delay (unsigned int long value){
for (;value>0;value--)__RESET_WATCHDOG();
}
/*MCU setup*/
void MCU_init (void){
ICSTRM = trimvalue; //set to calcuated trim value
PTCDD = 0b00000011; // make PTC0,1 output for leds
SPMSC1_BGBE =1; //enable bandgap buffer.
}
/*IIC setup*/
void IIC_init(void){
IICC1_IICEN = 1; //disable module IIC module
IICF_MULT= 0x10; //divide by 4 01
IICF_ICR= 0x00; //divide by 40; 07
}
/*master send function call*/
void master_send (void){
IICC1= 0b10111000; //iic enable, no iterrupt,master,transmit,ack on,)
return;
}
/*master receive function call*/
void master_receive (void){
IICC1= 0b10101000;
return;
}
/*iic disable*/
void iic_disable(void){
IICC1_IICEN = 0; //disable iic module
IICD=0;
return; //write zeros to iic data register.
}
void main(void) {
EnableInterrupts; /* enable interrupts */
MCU_init();
SCI_init();
IIC_init();
SCID=0x22; // test to check reset (help debug)
for(; {
delay (10000); //allow time for sensor to initiate!
//-----setup sensor units
LED3=1; // to help debug
master_send(); //configure as master, transmit mode
IICD=(0x20<<1)|0; //send address and write bit
delay (10);
while (!IICS_TCF)__RESET_WATCHDOG(); //wait until transmission finishes
delay (10);
IICD= cm; //tell sensor to send units in CM
delay (10);
while (!IICS_TCF)__RESET_WATCHDOG(); //wait until transmission finishes
delay(10);
if(IICS_RXAK==0){
LED4=~LED4; //to help debug
}
IICC1_RSTA=1 ; //set restart bit
//--------read sensor
master_send();
delay (10);
IICD=(0x20<<1)|1; //send address and receive bit
delay (10);
while(!IICS_TCF)__RESET_WATCHDOG(); //wait for trans to complete
master_receive(); //put in receive mode
data1 = IICD; //dummy read
while(!IICS_TCF)__RESET_WATCHDOG(); //wait for trans to complete
IICC_TXAK=1; //No ACK
data2 = IICD; // REAL DATA
IICC1_MST=0; //release bus
iic_disable(); //disable iic module all together.
//--------serial transmit
if (SCIS1_TDRE==0){ //if not ready to send wait
__RESET_WATCHDOG();
}
SCID=data2;
__RESET_WATCHDOG(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
I will clean things up later on....