Since the ADXL345 has got an I2C-interface (I am not a friend of SPI), why don't you use this? With the basic APIs of I2C-master (start, restart read etc) you can setup your connection byte-by-byte easily.
In your routine task() you initialize your device and get data, better is to separate initialization and reading off data.
You do not tell us where your program runs into troubles. Debugging the code will reveill that.
Best is to upload a complete project archive here (use Creator -> File -> Create Workspace Bundle (minimal) and upload the resulting .zip here), so we can check not only the code but all the settings.
A complete project helps to see where your hardware might be configured wrong.
Things to look for:
- SPI clock too fast (then the slave select output might go high inbetween the bytes)
- each write to the SPI also does a read - and this will fill up the buffer, so you might read wrong values afterwards. So clear the read buffer after each write
- wrong SPI mode (must be 1/1)
- when reading the registers, *1 must be shifted, as its the higher byte, and *0 is the lower byte
You should attach a logic analyzer and see whats going over the wire, and see whether it is what you expect. Then you can look at the software...
I think the code is very well written, here is some suggestions1. I think you should read all the data first into an array and then process the whole array; in that case you can check that value immediate after the reading.2. I would avoid use any names with leading underscore such as _POWER_CTL, as that normal are used for system usage3. Try not to mix // and /* */ together such as/*LCD_Position(0,9); //Initialize string position 9LCD_PrintString(point); //Prints . at 0,9, may not need?LCD_Position(0,12); //Initialize string position 12LCD_PrintString(G); //Prints G at 0,12*/I prefer to use#if 0LCD_Position(0,9); //Initialize string position 9LCD_PrintString(point); //Prints . at 0,9, may not need?LCD_Position(0,12); //Initialize string position 12LCD_PrintString(G); //Prints G at 0,12#endifOr#ifndef NO_PRINTLCD_Position(0,9); //Initialize string position 9LCD_PrintString(point); //Prints . at 0,9, may not need?LCD_Position(0,12); //Initialize string position 12LCD_PrintString(G); //Prints G at 0,12#endifAnd define that at the beginning of the file like this.#define NO_PRINTYou then can check your setting in one place and no need to check the code4. I think PSoC5 does not have bit variables. That is why sbit would not work5. I normally control the CS of SPI directly and not using the output from the SPI component. You can change it back to use the output of the component. But directly controlling it save a lot of headache during debugging.6. It would also help if you use more defines such as#define CARRAGE_RETURN (13)#define X_READING (0)#define Y_READING (0)UART1_Write(CARRAGE_RETURN );readings[X_READING] = ADXL345_Read(SENSOR_DATAX0) << 8;readings[Y_READING] = ADXL345_Read(SENSOR_DATAY0) << 8;7. As mentioned, it would be easier if you post the complete project.8. I would debug one portion of code a time, IE made sure the UART part works first by write something the the array direcly and send it out to the UART. Once it can display correctly then start doing
My bad!!8. I would debug one portion of code a time, IE made sure the UART part works first by write something the the array direcly and send it out to the UART. Once it can display correctly then start doing the reading of the sensor.
Thanks for the suggestions everyone. Hopefully this zip file will contain everything you need to look at, I've never used that feature before. As for the problem that I'm running into, I can display the title of the axis(X and Y) on the LCD but it won't display the data if should be getting from the accelerometer. I think the 2 problems are getting the accelerometer data and converting that data into a string to print on the LCD. One of my profs thought maybe that the LCD could only hold so much data so it wouldn't print something that was really long, but I don't think that is the case as I've shortened it to the first 6 values. I didn't know about the sbit stuff so thank you for that. I couldn't figure out why that wasn't working. I currently don't use UART anywhere (it's in there, just commented out), is it something I should be using? As for using SPI over I2C, I've been working on the project with many different accelerometers and boards over the past year and this just seems like the one that has been making the most progress. If I can't make it work with SPI, I'll switch over to I2C. I'm really not too picky on which I'll end up using, at this point I'd use whatever made it work. Sorry to keep you guys waiting for a few days, I was out of town and couldn't work on this then.
Acc.cywrk.Archive01.zip 539.7 K
The easy way to convert data to formatted data is sprintf(), basically printf() that
outputs to a character buffer for printing on LCD.
Attached the format specifications useful for sprintf(). If you are using character
LCD there is an API f() call in datasheet for printing a character buffer/array to the
LCD, as well as f()'s for moving the cursor to the position where you want the
formatted data to be written on LCD.
printf7.pdf 81.5 K
1. You have a while loop in your task() function. it will never come out so it won't run the Updatedisplay function().
2. You should be able to step and break within creator to debug your project.
3. For some simply test. I would suggest to added a 1second delay inside the main loop and also increment and x and y counter every loop and shown it on the LCD. So you can see the change of the counters updated on the LCD.
4. One step a time is actually quicker to the finish line.
I've changed a few things around and got actual numbers to be outputted on the LCD, but they only update when the accelerometer is unplugged. These numbers that change are from noise in the air we believe. Once the ADXL is plugged back in, the numbers stop changing. If the ADXL is plugged in when the PSoC board is programmed, it displays a single 0 on each line. We expected this but when I would change the default readings at the start of the code, the 0's would still be displayed. I've cleaned up some stuff that I don't think I'll need and am no longer using a printf() as LCD_PrintNumber() seems to be giving us data. I also fixed the while loop in task() and spilt task() into ADXLReady() and GetData(). Any ideas how I can get data from the ADXL? I know the registers are correct and I've tried different ADXL's and PSoC boards so it's not a hardware issue.
Acc.cywrk.Archive03.zip 573.6 K
First thing to note is that the SPI master is configured wrong. Its set to CPOL=0/CPHA=0, but the data sheet says it needs to be 1/1.
Can you attach a scope or logic analyzer to the SPI bus and check what goes over the wire, and whether the ADXL345 actually responds to the commands? Only if you can make sure that it answers it makes sense to look for other problems.
Also, your read logic is wrong. You only send the address byte to the ADXL345, but you never receive any data. For that, you need to send a second (dummy) byte, during which the ADXL345 will send your data back (see data sheet, page 16). Don't forget to skip the first byte you get from the read buffer, and you also need to wait for the transmission to finish (readRxStatus / readTXStatus).
I suggest you start reading the SPI master component data sheet, at least the API and the functional descriptions, and the ADXL345 data sheet, the part about SPI. Look at especially at the timing diagrams in both data sheets.
Btw: you still mix high and low bytes (DATAX0 is low, DATAX1 is high).
1. ADXL345 use the CS pin to switch between I2C and SPI mode, did you follow suggestion from the data sheet "Preventing bus traffic errors"?
2. SPI uses the CS pin to restart. It was mentioned by others that the line switches to high if the TX buffer is not filled up fast enough.
I would suggest to control the CS line via a control register. Or use I2C mode as other suggested.
3. Try to read the ID register( which is a constant) first to make sure the SPI and the related circuit is working correctly.
4. There are different setting for all the registers, make sure the default reset value is what your wants.
if not you need to set it up for your application.
5. I would suggest to read the values (6 bytes in one go).
The SPI clock is set to 150kHz, so I suppose that the PSoC is fast enough to fill the transmit buffer. The real problem is that only a single byte is send, so the ADXL345 never gets a chance to send its data back.
Thanks for all the suggestions so far, this is my first time working with SPI or I2C so a lot of this is new to me. I tried going the I2C route until I figured out how to get actual numbers displayed (I was getting greek letters, numbers, and random symbols at first) so I continued with the SPI. I won't be able to get into the lab until Tuesday so hopefully I can figure the signal stuff out after that because if I can't it'll be another week because the university will be shut down for the holiday. I've taken a look at the various data sheets involved, but having never used it before it's difficult to know what's used for what and its purpose. Thank you guys for your patience, you're an awesome group of people!
how did u do with the sbit?
Hi friends.could u runing adxl345 with spi or i2c?because i cant solved this problem!!!
If you solved this problem please give me your project to understanding how i can to do?