Hello. im trying to drive mma7455l accelerometer with a csm12c32 dev. board( has mc9s12c32 micrprocessor on it). i couldnt manage to use spi module somehow. and now im trying to use gpio pins to communicate with accelerometer. i have another problem now. i cannot write a r/w register of accelerometer but i can read register values. here is my source code to communicate through gpio pins:
#include <hidef.h> /* common defines and macros */#include <mc9s12c32.h> /* derivative information */#pragma LINK_INFO DERIVATIVE "mc9s12c32"#define CS_HIGH ( PTT = PTT | 0x01) //|0000|0001| #define CS_LOW ( PTT = PTT & 0xFE) //|1111|1110|#define SCL_HIGH ( PTT = PTT | 0x02) //|0000|0010|#define SCL_LOW ( PTT = PTT & 0xFD) //|1111|1101|#define SDO_HIGH ( PTT = PTT | 0x04) //|0000|0100|#define SDO_LOW ( PTT = PTT & 0xFB) //|1111|1011|unsigned char val=0;void main(void);void initSPI(void);void Delay10TCY();void Delay10KTCYx(int i);unsigned char ReadSPI(unsigned char address);void WriteSPI(unsigned char address, unsigned char data);unsigned char SPI_RByte(void);void SPI_WByte(unsigned char data); void main(void) { EnableInterrupts; DDRA = 0x01; DDRB = 0x10; PORTA = 0x01; PORTB = 0x10; initSPI(); for(;;){ val=0; // reset value PORTA = 0x01; // turn LED OFF //Set up MMA7455L operation mode by writing to hex addr 16, hex value 05 (2g, 4 wires) WriteSPI(0x16,0x05); Delay10KTCYx(100); val = ReadSPI(0x16);// read value back from register and if expected value turn ON the LED if(val==0x05){ PORTA = 0x00; }// turn LED ON /* else{ PORTA = 0x01; }// turn LED OFF */ Delay10KTCYx(100); if(PORTB == 0x00) PORTB = 0x10; else PORTB = 0x00; }}void initSPI(void){ DDRT = 0x07; //|0000|0111| CS_HIGH; SDO_LOW; SCL_LOW;}void Delay10TCY(){ int x; for(x=0;x<255;x++){}}void Delay10KTCYx(int i){ int x; for(x=0;x<i;x++){ Delay10TCY(); } }void SPI_WByte(unsigned char data){ char x; for(x=0;x<8;x++){ //Loop 8 bits SCL_LOW; //Clock Low Delay10TCY(); SDO_LOW; if((data & 0x80) > 0)//Clear entire byte except bit 7 and check if byte is greater than 0 SDO_HIGH; //Set the Data Out to HIGH Delay10TCY(); //Delay 5uS SCL_HIGH; //Clock High Delay10TCY(); //Delay 5uS data <<= 1; //Shift data bit out to the right } Delay10TCY(); //Delay 5uS}unsigned char SPI_RByte(void){ char x,data; for(x=0;x<8;x++){ //Loop 8 bits SCL_LOW; //Clock Low Delay10TCY(); //5uS delay data <<= 1; //Shift 1 bit to the left data &= 0xFE; //Clear BIT 0 from byte without touching the rest if( (PTT & 0x08) > 0) //if the Serial Data In is HIGH do below if not then leave it 0 data |= 1; //OR in a 1 into out byte SCL_HIGH; //Clock High Delay10TCY(); //5uS delay } Delay10TCY(); //Delay 5uS return data; //return our data}void WriteSPI(unsigned char address, unsigned char data){ SCL_HIGH; //Clock High CS_LOW; //Chip Select Low address = ( ( ( address << 1 ) & 0x7F ) | 0x80 ); SPI_WByte(address); //Write our address SPI_WByte(data); //Write our data CS_HIGH; //Chip Select High}unsigned char ReadSPI(unsigned char address){ unsigned char tmp; SCL_HIGH; //Clock High CS_LOW; //Chip Select Low address=( ( address << 1 ) & 0x7f );//Send read command together with reg address SPI_WByte(address); //Write our address to read from tmp = SPI_RByte(); //Get the byte from the device CS_HIGH; //Chip Select High return tmp; //Return tmp}
is there any thing wrong with src? i need a help very badly.
ps: if anyone has a tested & working source code using spi module to share, that would be great too.
Have a good day
Hi,
In this line:
if( (PTT & 0x08) > 0) //if the Serial Data
use PTIT - the input port register. PTT read returns the status
of this register as output.
Regards,
ipa
thanks for reply. but i couldnt see if this makes a difference. forgive me if i become blind by looking at the same code for over one week.
anyways i replaced PTT with PTIT and nothing changed. register read operation already works fine.
Ersancan,
I looked into MMA7455 datasheet and it seems your code doesn't agree with SPI timing diagrams. At least clock polarity is reversed. Clock should idle low, while in your code I see it idling high. You initiate write transfer setting clock high, then setting CS low. But CS bit is not only SPI slave select, it also switches MMA chip from/to IIC and SPI modes. I think you should make clock idling low, so that when you set CS low, clock is also low. Then you also will need to modify SPI_Write and SPI_Read routines. in SPI_Write you should first set up MMA SDI line, then pulse clock high then low. Read seems to be the similar: sample MMA SDO pin, then pulse clock high then low. Or maybe set clock high, sample SDO, then set clock low.
Hi,
Look for AN3468 and the correspoding software package - there is already
a software example.
Regards,
ipa