Arduino to wifly module using SC16IS750 breakout board

Hey guys,

I have a wifly module (RN-XV WiFly Module - RP-SMA Connector - WRL-11047 - SparkFun Electronics) and have used it successfully using an xbee explorer, but I'd like to use my Arduino UNO to communicate with it. I bought a SPI to UART IC (SparkFun I2C/SPI-to-UART Breakout - SC16IS750 - BOB-09981 - SparkFun Electronics) so I could take advantage of the WiFly libraries that exist out there, but had trouble getting it to work properly. I was wondering if anybody had a reference for the connections needed to get everything working for the Arduino WiFly Driver - Browse Files at SourceForge.net "WiFly Test" sketch?

I had Uno's 10-13 pins connected to CS, MOSI, MISO, SCLK on the SC16IS750 breakout board, and RX/TX going from the breakout board to the wifly module's TX/RX, with both the breakout board and the wifly's GND and VIN connected properly. I have a feeling I have it wired completely wrong but haven't been able to find a good reference, so any help is appreciated.

Thanks in advance.

What is your goal with using the SPI to UART solution? Is that so you can use higher baud rates than using the Arduino's hardware UART or a soft-serial over a couple of digital pins to the WiFly?

To be able to use the soft serial connection.

Here is the entire project code I am currently using that utilizes the SC16IS750, from sparkfun.com, then I'm attaching images of my current setup using my breadboard. I'm looking for an answer to the question of "what connections am I making wrong, or failing to make?"

#include <Arduino.h>
#include <pins_arduino.h>

// SC16IS750 Register Definitions
#define THR        0x00 << 3
#define RHR        0x00 << 3
#define IER        0x01 << 3
#define FCR        0x02 << 3
#define IIR        0x02 << 3
#define LCR        0x03 << 3
#define MCR        0x04 << 3
#define LSR        0x05 << 3
#define MSR        0x06 << 3
#define SPR        0x07 << 3
#define TXFIFO     0x08 << 3
#define RXFIFO     0x09 << 3
#define DLAB       0x80 << 3
#define IODIR      0x0A << 3
#define IOSTATE    0x0B << 3
#define IOINTMSK   0x0C << 3
#define IOCTRL     0x0E << 3
#define EFCR       0x0F << 3

#define DLL        0x00 << 3
#define DLM        0x01 << 3
#define EFR        0x02 << 3
#define XON1       0x04 << 3  
#define XON2       0x05 << 3
#define XOFF1      0x06 << 3
#define XOFF2      0x07 << 3

// SPI pin definitions

#define CS         10
#define MOSI       11
#define MISO       12
#define SCK        13


#define ASSOCIATE_TIMEOUT 5000

// Global variables
char incoming_data; 
char TX_Fifo_Address = THR; 

int i = 0;
int j = 0;
int k = 0;
char clr = 0;
char polling = 0;

// SC16IS750 communication parameters
struct SPI_UART_cfg
{
  char DivL,DivM,DataFormat,Flow;
};

struct SPI_UART_cfg SPI_Uart_config = {
  0x50,0x00,0x03,0x10};

// Wifi parameters
char auth_level[] = "3";
char auth_phrase[] = "ducklings1";
char port_listen[] = "80";
char ssid[] = "Brownbear";

void setup()
{
  // SPI pin initialization
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK,OUTPUT);
  pinMode(CS,OUTPUT);
  digitalWrite(CS,HIGH); //disable device 

  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10); 

  Serial.begin(9600);
  Serial.println("\n\r\n\rWiFly Shield Terminal Routine");
  
  if(SPI_Uart_Init()){ // Test SC16IS750 communication
    Serial.println("Bridge initialized successfully!"); 
  }
  else{ 
    Serial.println("Could not initialize bridge, locking up.\n\r"); 
    while(1); 
  }
 

  autoconnect();
}

void loop()
{
  // Exit command mode if we haven't already
  SPI_Uart_println("exit");
  delay(500);
  Flush_RX();

  while(!Have_Client()); // Wait for client
  // Sent HTML
  SPI_Uart_print("<html>");
  SPI_Uart_print("<title>WiFly Server Example</title>");
  SPI_Uart_print("<h1>");
  delay(100);
  SPI_Uart_print("<img src=\"http://static.sparkfun.com/images/framework/logo.gif\">");
  delay(100);
  SPI_Uart_print("</h1>");
  delay(100);
  SPI_Uart_print("<form name=\"input\" action=\"/\" method=\"post\">");
  delay(100);
  SPI_Uart_print("Username:");
  delay(100);
  SPI_Uart_print("<input type=\"text\" name=\"user\" />");  
  delay(100);
  SPI_Uart_print("<input type=\"submit\" value=\"Submit\" />");
  delay(100);
  SPI_Uart_print("</form>"); 
  delay(100);
  SPI_Uart_print("</html>");
  delay(500);
  SPI_Uart_print("$$");
  delay(500);
  SPI_Uart_println("close");
  delay(1000);
  SPI_Uart_println("exit");
  delay(500);
  Flush_RX();

  while(1) // Enter transparent terminal mode
  {
    if(SPI_Uart_ReadByte(LSR) & 0x01)
    { 
      polling = 1;
      i = 0;
      while(polling)
      {
        if((SPI_Uart_ReadByte(LSR) & 0x01))
        {
          incoming_data = SPI_Uart_ReadByte(RHR);
           Serial.print(incoming_data);
        }  
        else
        {
          polling = 0;
        }
      }

    }
    else if(Serial.available())
    {
      incoming_data = Serial.read();
      select();
      spi_transfer(0x00); // Transmit command
      spi_transfer(incoming_data);
      deselect();
    }
  }
}

void select(void)
{
  digitalWrite(CS,LOW);
}

void deselect(void)
{
  digitalWrite(CS,HIGH);
}

char Have_Client(void)
// Wait until we receive data (client request)
{
  if(SPI_Uart_ReadByte(LSR) & 0x01){ 
    Serial.println("Client request."); 
    Flush_RX(); 
    Flush_RX();
    return 1; 
  }   
  else{ 
    return 0; 
  } 
}

char SPI_Uart_Init(void)
// Initialize SC16IS750
{
  char data = 0;

  SPI_Uart_WriteByte(LCR,0x80); // 0x80 to program baudrate
  SPI_Uart_WriteByte(DLL,SPI_Uart_config.DivL); //0x50 = 9600 with Xtal = 12.288MHz
  SPI_Uart_WriteByte(DLM,SPI_Uart_config.DivM); 

  SPI_Uart_WriteByte(LCR, 0xBF); // access EFR register
  SPI_Uart_WriteByte(EFR, SPI_Uart_config.Flow); // enable enhanced registers
  SPI_Uart_WriteByte(LCR, SPI_Uart_config.DataFormat); // 8 data bit, 1 stop bit, no parity
  SPI_Uart_WriteByte(FCR, 0x06); // reset TXFIFO, reset RXFIFO, non FIFO mode
  SPI_Uart_WriteByte(FCR, 0x01); // enable FIFO mode

  // Perform read/write test to check if UART is working
  SPI_Uart_WriteByte(SPR,'H');
  data = SPI_Uart_ReadByte(SPR);

  if(data == 'H'){ 
    return 1; 
  }
  else{ 
    return 0; 
  }

}

void SPI_Uart_WriteByte(char address, char data)
// Write <data> to SC16IS750 register at <address>
{
  long int length;
  char senddata[2];
  senddata[0] = address;
  senddata[1] = data;

  select();
  length = SPI_Write(senddata, 2);
  deselect();
}

long int SPI_Write(char* srcptr, long int length)
// Write string to SC16IS750
{
  for(long int i = 0; i < length; i++)
  {
    spi_transfer(srcptr[i]);
  }
  return length; 
}

void SPI_Uart_WriteArray(char *data, long int NumBytes)
// Write array to SC16IS750 THR
{
  long int length;
  select();
  length = SPI_Write(&TX_Fifo_Address,1);

  while(NumBytes > 16)
  {
    length = SPI_Write(data,16);
    NumBytes -= 16;
    data += 16;
  }
  length = SPI_Write(data,NumBytes);

  deselect();
}

char SPI_Uart_ReadByte(char address)
// Read from SC16IS750 register at <address>
{
  char data;

  address = (address | 0x80);

  select();
  spi_transfer(address);
  data = spi_transfer(0xFF);
  deselect();
  return data;  
}

char autoconnect(void)
{
  // Exit command mode if we haven't already
  SPI_Uart_println("");  
  SPI_Uart_println("exit");
  delay(500);

  // Enter command mode
  SPI_Uart_print("$$");
  delay(500);

  // Reboot to get device into known state
  Serial.println("Rebooting");
  SPI_Uart_println("reboot");
  delay(3000);

  // Enter command mode
  Serial.println("Entering command mode.");
  SPI_Uart_print("$$");
  delay(500);

  // Set authentication level to <auth_level>
  SPI_Uart_print("set w a ");
  SPI_Uart_println(auth_level); 
  delay(500);
  Serial.print("Set wlan to authorization level ");
  Serial.println(auth_level);

  // Set authentication phrase to <auth_phrase>
  SPI_Uart_print("set w p ");
  SPI_Uart_println(auth_phrase);
  delay(500);
  Serial.print("Set security phrase to ");
  Serial.println(auth_phrase);

  // Set localport to <port_listen>
  SPI_Uart_print("set i l ");
  SPI_Uart_println(port_listen);
  delay(500);
  Serial.print("Set IP localport to ");
  Serial.println(port_listen);

  // Deactivate remote connection automatic message
  SPI_Uart_println("set comm remote 0");
  delay(500);

  // Join wireless network <ssid>
  Serial.print("Joining '");
  Serial.print(ssid);
  Serial.println("'");
  delay(100);
  Flush_RX();
  delay(100);
  SPI_Uart_print("join ");
  SPI_Uart_println(ssid);  
  for(int p = 0; p < 40; p++)
  {
    Serial.print(".");
    delay(ASSOCIATE_TIMEOUT/30);
  }
  Serial.println("");

  Flush_RX();

  // Check for association
  SPI_Uart_println("show c");
  if(Wait_On_Response_Char(13) != '0')
  {
    Serial.print("Failed to associate with '");
    Serial.print(ssid);
    Serial.println("'\n\rRetrying...");
    Flush_RX();
    autoconnect();
  }
  else
  {
    Serial.println("Associated!");
    Flush_RX();
  }
}

void Flush_RX(void)
// Flush characters from SC16IS750
{
  int j = 0;
  while(j < 4000)
  {
    if((SPI_Uart_ReadByte(LSR) & 0x01))
    {
      incoming_data = SPI_Uart_ReadByte(RHR);
    }  
    else
    {
      j++;
    }
  }
}

char Wait_On_Response_Char(char num)
// Wait on char number <num> from a response and return it
{
  i = 1;
  while(1)
  {
    if((SPI_Uart_ReadByte(LSR) & 0x01))
    {
      incoming_data = SPI_Uart_ReadByte(RHR);
      //Serial.print(incoming_data, BYTE);
      if(i == num){ 
        return incoming_data; 
      }
      else{ 
        i++; 
      }
    }  
  }
}

void SPI_Uart_println(char *data)
// Print string <data> to SC16IS750 followed by a carriage return
{
  SPI_Uart_WriteArray(data,strlen(data));
  SPI_Uart_WriteByte(THR, 0x0d);
}

void SPI_Uart_print(char *data)
// Print string <data> to SC16IS750 using strlen instead of hard-coded length
{
  SPI_Uart_WriteArray(data,strlen(data));
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait for the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

I'd suggest doing something simple to test the interface first. Like a sketch that simply receives characters from the arduino hardware serial port and sends them straight to the SPI UART interface, and also receives characters from the SPI UART interface and sends them to the hardware serial port. Then you can use the serial monitor and see if you can get the wifly to enter command mode by sending "$$$".

You could also skip the SPI UART altogether and connect two pins from the arduino to the wifly tx and rx pins via a 5V to 3.3v level shifter and use software serial. Or use an XBee shield that supports software serial.

I can't quite work out the VCC connections from those pictures. I think the SPI UART board needs 5V and the Wifly needs 3.3V. Can you describe the all the connections you have between the boards for data and power?

The SPI-UART board is 5v tolerant but works well with 3.3v.

I have the Uno's pins 10-13 connected to CS, MOSI, MISO, SCLK on the SC16IS750 respectively, and RX going from the breakout board to the wifly module's TX, and the TX going from the breakout board to the wifly module's RX. The one thing I think might be weird that I don't understand is I don't have anything connected to Pin 1 of the SC16IS750, labeled I2C-SPI, and I'm not sure what would connect there? Then I have the Arduino's 3.3v and GND connected to the rails of my breadboard, and have the WiFly and SC16IS750 connected to the rails appropriately. Everything has power, but it seems like none of the commands I give the WiFly go through, and I don't see any AOKs come back (or anything for that matter) over RX.

The SPI UART board uses a 3.3V LDO regulator. It's marked X833 so it's probably an SGM2008 which needs an input Voltage of at least 3.6V to operate. 5V would be fine. 3.3V will not work.

From the SPI/I2C UART data sheet...

I2C-bus or SPI interface select. I2C-bus interface is selected if this pin is at logic HIGH. SPI interface is selected if this pin is at logic LOW.

Here's a link to the data sheet

Edit: added datasheet link

I will double check that when I get home and find out if it's not getting power. However, the SC16IS750 gets initialized properly as far as the arduino sketch can tell, based on the following portion of the setup() method

// SPI pin initialization
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK,OUTPUT);
  pinMode(CS,OUTPUT);
  digitalWrite(CS,HIGH); //disable device 

  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10); 

  Serial.begin(9600);
  Serial.println("\n\r\n\rWiFly Shield Terminal Routine");
  
  if(SPI_Uart_Init()){ // Test SC16IS750 communication
    Serial.println("Bridge initialized successfully!"); 
  }
  else{ 
    Serial.println("Could not initialize bridge, locking up.\n\r"); 
    while(1); 
  }

What I really need to do is dive down a little deeper and see what the UART initialization is actually doing under the hood, so I can troubleshoot it better. I wish the WiFly was a little more popular as the Arduino is, so I could find more working references to learn more about what I'm trying to do! Thanks for your help

I have a WiFly module, and I found it easy to use. I didn't bother trying to use a library with it - just the serial interface. I don't think you need the WiFly library unless you plan to change the WiFly config from your sketch.

I posted some details here:

Thanks for the tips. I looked at your sketch and it definitely makes it easier to work with using a soft serial connection. Ideally, I'd like to be able to use the WiFly to the potential it is meant for, which means using a UART signal, but I think I've got quite a bit to learn before I get to that point. Thanks for all the info, I'll let you know if I take it further and do anything exciting with it!

jbuchacher:
I will double check that when I get home and find out if it's not getting power. However, the SC16IS750 gets initialized properly as far as the arduino sketch can tell, based on the following portion of the setup() method

// SPI pin initialization

pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK,OUTPUT);
  pinMode(CS,OUTPUT);
  digitalWrite(CS,HIGH); //disable device

SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
  clr=SPSR;
  clr=SPDR;
  delay(10);

Serial.begin(9600);
  Serial.println("\n\r\n\rWiFly Shield Terminal Routine");
 
  if(SPI_Uart_Init()){ // Test SC16IS750 communication
    Serial.println("Bridge initialized successfully!");
  }
  else{
    Serial.println("Could not initialize bridge, locking up.\n\r");
    while(1);
  }





What I really need to do is dive down a little deeper and see what the UART initialization is actually doing under the hood, so I can troubleshoot it better. I wish the WiFly was a little more popular as the Arduino is, so I could find more working references to learn more about what I'm trying to do! Thanks for your help

Hi there,
I am using your code example for reference to use in my raspberry pi.
would you please tell me what these code lines are for?

 SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
 clr=SPSR;
 clr=SPDR;

Actually I am working on same kind of project and if you can help me that would be great. I am connecting my Raspberry pi with SC16iS750 chip through SPI connection as same you did in your project. And SC16iS750 with RN-131G (Wifi module) through UART.

Now my question is do you have to initialize SC16iS750 chip or it will directly put data from SPI bus to UART? I enable my SPI pins in Raspberry pi and I am getting data on SC16iS750 chip at SPI pins (MOSI and MISO) but when I check pin at TX and RX of SC16iS750 chip, I am getting just 3.3 voltage level no data. So do I have to write commands to initialize pins and registers of SC16iS750 ? IF yes, would you please share your code for reference?

my email is tsavalia@lakeheadu.ca.

I would really appreciate your help.

Hope to hear from you soon.

Thank you.