Hi, This programing is to Start I2c Communication with the basic start up code followed by sending a 8 bit address together with a write bit. Next, it will send a string a serial port to show a string "nack" only if the SDA is not pulled low, which means not acknowledged.
Chip used: Dallas DS89C450 11.0592Mhz Accelerometer: SEN 10955 2.25 Mhz
Problem faced: SDA could not be pulled low. Nack received.
Question: May i know is there any faults in this program?
#include <DS89C4XX.h> //DS89C450 Microcontroller #include <intrins.h> //_nop_() function sbit SDA=P1^0; sbit SCL=P1^1; //--------------------------Transmit---------------------------------- void Uart_Tx2(unsigned char c) { while (TI_0==0); TI_0=0; SBUF0=c; } // ----------------------Transmit string ------------------------------------------------------ void sendstring (char *String) { int i=0; //set counter to 0 while(String[i]) { Uart_Tx2(String[i++]); } } //-------------------------------Delay ----------------------------------------- void I2CBitDly() // wait approximately 4.7uS { // tune to xtal. This works at 11.0592MHz unsigned int time_end = 9; unsigned int index; for (index = 0; index < time_end; index++); return; } //-------------------------------------------Start-------------------------- void I2CSendStart(void) { SDA = 1; I2CBitDly(); SCL = 1; I2CBitDly(); SDA = 0; I2CBitDly(); SCL = 0; I2CBitDly(); } //-------------------------------------------STOP----------------------------- void I2CSendStop(void) { SDA = 0; I2CBitDly(); SCL = 1; I2CBitDly(); SDA = 1; I2CBitDly(); } //-----------------------------------------SEND data--------------------------- void I2CSendByte(unsigned char bt) { register unsigned char i; for (i=0; i<8; i++) { if ((bt<<i)&0x80) SDA = 1; // Send each bit else SDA = 0; SCL = 1; I2CBitDly(); SCL = 0; I2CBitDly(); } SDA = 1; // make P1.0 an input. I2CBitDly(); SCL = 1; // 9th clock high. I2CBitDly(); if (SDA == 1) // { sendstring("nack"); // SDA is not pulled low. nack is sent. } SCL = 0; I2CBitDly(); //SDA = 1; // end transmission SCL = 1; } //---------------MAIN--------------------------------- void main () { SCON1 = 0x52; SCON0 = 0x52; TMOD = 0x20; TCON = 0x69; TH1 = 0xFD; //Buad Rate: 9600 bps I2CSendStart(); I2CSendByte(0x38); while(1) { }; }
Hi! I finally manage to receive an acknowledge, the problem was the wrong slave address used. However, Now, i could not Read from the I2C bus. I keep receiving 0x01 as the final result.
Question: Is my Transmitting to serial port or receiving from I2C function at fault?
#include <DS89C4XX.h> //DS89C450 Microcontroller #include <intrins.h> //_nop_() function #include <stdio.h> //sprintf() function sbit SDA=P1^0; sbit SCL=P1^1; //--------------------------Transmit---------------------------------- void Uart_Tx1(unsigned char c) { while (TI_0==0); TI_0=0; SBUF0=c; } //--------------------------Transmit---------------------------------- void Uart_Tx2(unsigned char c) { while (TI_0==0); TI_0=0; SBUF0=c; } // ----------------------Transmit string ------------------------------------------------------ void sendstring (char *String) { int i=0; //set counter to 0 while(String[i]) { Uart_Tx2(String[i++]); } } //-----------------------------Delay-------------------------------------------- void Delay(int count) { int i,j; for (i=0;i<count;i++){ for (j=0;j<1200;j++); } } //-------------------------------Delay ----------------------------------------- void I2CBitDly() // wait approximately 4.7uS { // tune to xtal. This works at 11.0592MHz unsigned int time_end = 10; unsigned int index; for (index = 0; index < time_end; index++); return; } //-------------------------------------------Start-------------------------- void I2CSendStart(void) { SDA = 1; I2CBitDly(); SCL = 1; I2CBitDly(); SDA = 0; I2CBitDly(); SCL = 0; I2CBitDly(); } //-------------------------------------------STOP----------------------------- void I2CSendStop(void) { SDA = 0; I2CBitDly(); SCL = 1; I2CBitDly(); SDA = 1; I2CBitDly(); } //-----------------------------------------SEND data--------------------------- void I2CSendByte(unsigned char bt) { register unsigned char i; for (i=0; i<8; i++) { if ((bt<<i)&0x80) SDA = 1; // Send each bit else SDA = 0; SCL = 1; I2CBitDly(); SCL = 0; I2CBitDly(); } SDA = 1; // make P1.0 an input. I2CBitDly(); SCL = 1; // 9th clock high. I2CBitDly(); if (SDA == 0) // { //sendstring(" ack "); // SDA is not pulled low. nack is sent. } SCL = 0; I2CBitDly(); SDA = 1; // end transmission SCL = 1; } //----------------READ DATA -------------------------------------------------------------------------------- unsigned char I2CGetByte() { unsigned char retc; unsigned char BitCnt; retc=0; I2CBitDly(); SCL=0; I2CBitDly(); SDA=1; // set as input pin. for(BitCnt=0;BitCnt<8;BitCnt++) { I2CBitDly(); SCL=1; retc=retc<<1; // shift by 1 for each bit. I2CBitDly(); if(SDA==1)retc=retc+1; I2CBitDly(); SCL=0; } I2CBitDly(); return(retc); } //-------------------Standby--------------------------- void standby_mode () { I2CSendStart(); I2CSendByte(0x3A); I2CSendByte(0x0B); //address I2CSendByte(0x00); // standby mode I2CSendStop(); } //-------------------Active mode----------------------- void active_mode () { I2CSendStart(); I2CSendByte(0x3A); I2CSendByte(0x0B); I2CSendByte(0x01); // active mode I2CSendStop(); } //---------------------8g mode ----------------------- void g_mode () { I2CSendStart(); I2CSendByte(0x3A); I2CSendByte(0x0E); I2CSendByte(0x02); // set to 8g. I2CSendStop(); } //-------------------Register Active mode ---------------- void AReg1 () { I2CSendStart(); I2CSendByte(0x3A); I2CSendByte(0x2A); I2CSendByte(0x01); // active mode I2CSendStop(); } //----------------------------------Transmit CHAR---------------------- void Char_Int(unsigned char c) { unsigned char s[4]; int i; c=c&0xff; sprintf(s,"%03d ",(int)c); for (i=0;i<4;i++) Uart_Tx1(s[i]); } //---------------MAIN--------------------------------- void main () { unsigned char value; SCON1 = 0x52; SCON0 = 0x52; TMOD = 0x20; TCON = 0x69; TH1 = 0xFD; //Buad Rate: 9600 bps Delay(200); SDA = 0; //set to output pin SCL = 0; //set to output pin Delay(200); standby_mode (); // set to standby to do config g_mode (); // set to 8g range AReg1 (); // set REG 1 active for reading active_mode (); // set back to active mode while (1) { I2CSendStart(); I2CSendByte(0x3A); I2CSendByte(0x01); I2CSendStart(); I2CSendByte(0x3B); value = I2CGetByte(); Char_Int(value); I2CSendStop(); Delay(1000); } }