NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » SPI problem
May 25, 2012 by denis1981 |
Guys, I have a little problem. I diligently searched the previous topics and could not find the solution to my problem. I’m trying to learn SPI protocol and so trying to complete a very simple project. Two micro-controllers (both ATmega168), one as a slave, second as a master. Master receives an input from the user (push of a button), transmits the data (logical 1) through SPI protocol to the slave and slave turns on an LED. The problem: I did a lot of trouble shooting and it appears that the problem is at the line 62 of the master controller. It seems like this while loops runs forever waiting for the SPIF flag that never signals the end of the transmission. So master code never passes line number 62. Circuitry and codes for master and slave are attached. Clearly I’m just doing something plain stupid as I triple checked all the settings and all looks like per data sheet . I’m stuck on it for nearly a week. Please advise. Denis. http://i.imgur.com/eiXU5.jpg Slave: define F_CPU 14745600include <stdio.h>include <math.h>include <avr/io.h>include <avr/interrupt.h>include <avr/pgmspace.h>include <inttypes.h>include "../libnerdkits/delay.h"include "../libnerdkits/lcd.h"include "../libnerdkits/uart.h"int main() { DDRC|=(1<<PC5);
DDRC|=(1<<PC4);
DDRC|=(1<<PC3);
DDRC|=(1<<PC2);
DDRB|=(1<<PB4);
DDRB &= ~(1<<PB5); PORTC|=(1<<PC4); while(1) { PORTC|=(1<<PC3); while(!(SPSR & (1<<SPIF))); B=SPDR; if (B==1){ PORTC|=(1<<PC5); } else { PORTC &= ~(1<<PC5); } PORTC|=(1<<PC2); } return 0; } Master: define F_CPU 14745600include <stdio.h>include <math.h>include <avr/io.h>include <avr/interrupt.h>include <avr/pgmspace.h>include <inttypes.h>include "../libnerdkits/delay.h"include "../libnerdkits/lcd.h"include "../libnerdkits/uart.h"uint16_t SPI(uint16_t dataout) { uint16_t datain; SPDR=dataout; while(!(SPSR & (1<<SPIF))); datain=SPDR; PORTB|=(1<<PB2); delay_us(1); PORTB&= ~(1<<PB2); return datain; } uint16_t A=0; int main() { DDRC &= ~(1<<PC5);
DDRB &= ~(1<<PB4);
DDRB |= (1<<PB3);
DDRB |= (1<<PB5); SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA); lcd_init(); FILE lcd_stream=FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE); lcd_home(); while(1) { if (PINC&(1<<PC5)){ A=1; } else { A=0; } SPI(A); } return 0; } |
---|---|
May 26, 2012 by Ralphxyz |
denis1981, I used the "Indent Selection as Code Block" button at the bottom of the page to make this readable.
Ralph |
May 26, 2012 by denis1981 |
Thank you. I tried to do it when posted originally but it wouldn't work for me then... Any idea why it doesn't work? |
May 27, 2012 by Ralphxyz |
Oh, "it" works. There have been a number of post about posting code. Originally "we" had to put four spaces before a line to indent it as code. In fact you can still put in four spaces which is what the "Indent Selection as Code Block" button does. Since we do not have a practice forum where new users can experiment before posting. But we do have the "Preview" so you have to see what you are posting before actually posting so you always can go back and try something else. Of course there are certain assumptions made about posters. Like doing a "Selection" it is assumed everybody knows how to do a Selection but for some a "Highlight" might make more sense. So you copy your code to the "Body" window (where you are composing your post). And then you "Select" it by left clicking and holding your mouse button at the start of your code and dragging your mouse to the end of your code. There now your code is "Highlighted" in blue as in being "Selected". Then you just click the "Indent Selection as Code Block". When you "Preview" you will see you correctly formatted code block. Now hopefully someone will help you with your SPI problem. Have you compared your code to the Servo Squirter code? Also are you doing anything about "button debounce"? I do not know if that would effect your setup but it does mess up things. I just quickly looked at your code but did not notice any debounce. Ralph |
May 27, 2012 by sask55 |
Hi denis1981 slave code You do not have to set the CPOL or the CPHA bits in the SPCR register. You will have to set the SPE and the SPIE bits.
Enable global interrupts.
Set up the SPI interrupt code that will run when the SPIF interrupt flag in the SPSR register is set after the SPI transfer is complete.
Master code
You do not have to set the CPOL or the CPHA bits You should select a SPI clock speed by setting one or both of the SPR1 and SPR0 bits. Table 18-5 in the data sheet. Without setting ether of these bits the SPI will default to f osc/4 which is alright. For example to set the SPI speed to 1/64 of the oscillator speed
Inside the while loop send a 0 out on the SPI if pin 5 on the C port is high or else send a 1 out on the SPI if (ie button is pushed and pin is shorted to ground)
I hope this helps a bit. |
May 27, 2012 by sask55 |
I think a example of the least amount of code required to do what you described may be more clear.
If I have not made any syntax errors this code should do what you have described. |
May 27, 2012 by sask55 |
Noticed an error line 27 uint16_t B; must be moved to the top of the SPI interupt. |
Please log in to post a reply.
Did you know that the printf format string "%.3f" will show three digits after the decimal point? Learn more...
|