Shop OBEX P1 Docs P2 Docs Learn Events
Proper way to set I/O pins? — Parallax Forums

Proper way to set I/O pins?

Jack BuffingtonJack Buffington Posts: 115
edited 2013-01-11 06:42 in Propeller 1
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.
// 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;
   }

SPI.png
741 x 356 - 40K

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-01-09 23:52
    Self-inflicted damage I'm afraid. CLK is #defined as 1<<1 which makes the clock line look like:
    OUTA &= ~1<<1;
    
    to the compiler which is not really what you want. So instead declare CLK as (1<<1) (no semicolon but with brackets) with the result that your clock line now reads:
    OUTA &= ~(1<<1);
    
    To inspect your binary use propeller-elf-objdump [-S] <binary>.
  • jazzedjazzed Posts: 11,803
    edited 2013-01-10 08:55
    Thanks @kuroneko

    #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.
  • Jack BuffingtonJack Buffington Posts: 115
    edited 2013-01-10 10:45
    Thanks guys! That makes sense now.
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2013-01-11 06:42
    Some rules you should set yourself when defining macros, from a coding standard document of one of the companies I worked for:

    - 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
Sign In or Register to comment.