Proper way to set I/O pins?
Jack Buffington
Posts: 115
I'm trying to write a simple SPI routine in C but am seeing a glitch on my logic analyzer when I am setting my data line high after it already was high.
I have tried various compiler settings. Right now they are on HUB, C, LMM, and -O0 None. Playing around with the compiler settings don't seem to make a difference. I'm just not seeing what is going on. I am setting my I/O pins the way that I saw in one of the included programs. Is there a way to see what assembly code was created from the C code? That would be helpful to learn how to best work with this compiler.
In any case, here is my code. Below my code is a screenshot of what I am seeing on my logic analyzer. Any help would be appreciated.
I have tried various compiler settings. Right now they are on HUB, C, LMM, and -O0 None. Playing around with the compiler settings don't seem to make a difference. I'm just not seeing what is going on. I am setting my I/O pins the way that I saw in one of the included programs. Is there a way to see what assembly code was created from the C code? That would be helpful to learn how to best work with this compiler.
In any case, here is my code. Below my code is a screenshot of what I am seeing on my logic analyzer. Any help would be appreciated.
// how I define the pins: #define DATA 1<<0; #define CLK 1<<1; // from another place in my code: doSPI(0xAF); waitcnt(CNT + CLKFREQ/500); doSPI(0xAF); void doSPI(int theByte) { unsigned int I; OUTA &= ~CS; for(I = 0x80; I != 0; I >>= 1) { OUTA &= ~CLK; // set the clock low //waitcnt(CNT + CLKFREQ/100000); // If I insert this then the glitch is longer if(theByte & I) { OUTA |= DATA; } else { OUTA &= ~DATA; } waitcnt(CNT + CLKFREQ/10000); OUTA |= CLK; // set the clock high waitcnt(CNT + CLKFREQ/10000); } OUTA |= CS; }
Comments
#define macros cause me pain too. Everyone can forget the rules.
Use parenthesis liberally. Example #define add2(a,b) ((a)+(b))
Using SimpleIDE one can see the ASM output by right-click Project Manager -> File Name -> Show Assembly.
- Each mention of a parameter should be in parentheses:
e.g. #define Square(x) ((x)*(x))
not #define Square(x) (x*x)
- If the macro is interpreted as expression, put the entire macro in parentheses
e.g. #define Square(x) ((x)*(x))
not #define Square(x) (x)*(x)
- Don't put semicolons at the end of a macro unless there's no way to accomplish what you want without them (there usually is)
- If a macro has multiple statements in the expansion (i.e. if it contains semicolons), surround it with do {...} while(0)
e.g. #define Inc(x,y) do { (x)++; (y)++; } while(0)
not #define Inc(x,y) (x)++; (y)++
or #define Inc(x,y) { (x)++; (y)++; }
This ensures that your macro is expanded in the expected way for all situations, and also neatly fixes the problem that semicolons at the end of a macro are a Bad Thing
If you ever get interviewed for a job, and a programming test is part of the interview, chances are that they will test if you use these rules when you write macros.
There are many references on Google about why these are good rules to keep in your head. And I'm happy to see that the Propeller header files follow them :-)
===Jac