- Sat Nov 11, 2006 12:56 am
#21705
Hey All, there has been some discussion about how to get a DOSonCHIP module to function with the SPI bus, since the documentation for the product is best described as 'woefully inadequate'. I recently picked one of these up and sat down with it for an evening, and through a combination of intuition and *luck* was able to get it to communicate over the SPI bus.
Below is pseudocode and code. The code serves the function of piping spi<-->uart, and handshaking with the card to figure out when it wants the master to clock data out, so one can work in terminal just to speed debugging.
Pseudocode:
1) you'll need the following pins
SPI_MOSI, SPI_MISO, SPI_CLK, SPI_CS#, BUSY, DIR, RESET
from your microcontroller's point of view, CS, and Reset are outputs, Busy and Dir are inputs.
A) reset the module:
At power up, set Reset to 0,
set CS# to 1
delay for 10uS or longer
set Reset to 1. -- reset is active low, so 1 is 'run', 0 is 'reset'
B) connect to the module:
set up your spi module such that:
clock resting state is HIGH
data clocked out(of microcontroller) on rising edge
data clocked in(to microcontroller) on falling edge
8 bit transmission
unframed
C) you can tell the DOSonCHIP has info to send when:
Direction =0 and Busy = 0
if this is the case, clock an FF into the module to extract a data byte
if Direction and busy don't change state, keep sending FF's until they do
(might work with other characters, haven't tried)
D) Sending requires the following:
Set CS to 0 -- selects the module
delay (I'm using a microsecond or two, might work with tighter timing)
Send data to your SPI output
When data finishes clocking out of the SPI, delay again(microsecond or so)
Set CS to 1 -- informs the module the byte has finished transmitting
Code:
/begin SDaccess.c
//*****************************************************************
//*FILENAME: SDaccess.c
//AUTHOR: Aiden Morrison
//DESCRIPTION: Access and control of an SD media card via a wearable inc
//DOSonCHIP device.
//*****************************************************************
//TARGET DEVICE: DSPIC30F4011
//*****************************************************************
#include "C:\Program Files\Microchip\MPLAB C30\support\h\p30F4011.h"
#include "C:\Program Files\Microchip\MPLAB C30\support\h\spi.h"
#include "C:\Program Files\Microchip\MPLAB C30\support\h\uart.h"
// the above include path may be different for each user. If a compile
// time error appears then check the path for the file above and edit
// the include statement above.
//Define Pins's
#define L0 LATBbits.LATB0 //Indicator LED
//SD Card handling pins
#define SDCS LATFbits.LATF0 //SD card Chip Select signal
#define SDBusy PORTEbits.RE5 //SD card Busy signal
#define SDDir PORTEbits.RE3 //SD card Data Direction Signal
#define SDCD PORTEbits.RE2 //SD card presence detect
#define SDRst LATEbits.LATE0 //DOSonChip Reset signal
//#define FOSC 16000000
//#define BAUDRATE 115200
//---------------------------------------------------------------------
// Definitions for subroutines
void SetupPorts(void);
void Init_UART1(void);
void Init_UART2(void);
void Init_SPI1(void);
//SDcard handling functions
void SendSD(unsigned int databyte);
//Global Variables
unsigned char charbuf;
//---------------------------------------------------------------------
int main(void)
{
SetupPorts(); // Initialize I/O
Init_UART1();
Init_UART2();
Init_SPI1();
while(1)
{
SDRst=0; //Reset SDcard
SDCS=1; //De-select SDcard
L0=1;
WriteUART1('B'); //UART1 'Alive' check character
delay();
L0=0;
SDRst = 1; //Active low reset, release card from reset
while(1)
{
L0=SDBusy;
// This code checks to see if the SDCard has something to say
//if it does, it clocks it out by sending FF's... don't know if
//other characters work just as well or not.
if (SDDir ==0 && SDBusy ==0){
microdelay();
if (SDDir==0 && SDBusy ==0){
SendSD(0xFF);
}
}
}
}
} // end main
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void SetupPorts(void)
{
//B0 LED output - set pin as digital
ADPCFG= 0x0001; //Turn RB0 to digital pin for L0
TRISB = 0xFFFE; //alter tristate to output
TRISE = 0xFFFE; //Everything on Port E is an input but RE0, which is Card Reset
TRISF = 0xFFFE; //" " F " " RF0, " " Chip Select SD card
SDRst = 0;
SDCS = 0;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void Init_UART1(void)
{
unsigned int baudvalue, U1MODEvalue, U1STAvalue;
CloseUART1();
ConfigIntUART1(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS);
U1MODEvalue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK &
UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
U1STAvalue = UART_TX_PIN_NORMAL & UART_TX_ENABLE &
UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
baudvalue =8;
//4MHz crystal with 16xpll
//8;//115200
//16; //57600
//25; //38400
//34; //28800
//68; //14400
//((FOSC/(16*BAUDRATE)) - 1); //this expression doesn't work, i'm probably doing something wrong
OpenUART1(U1MODEvalue, U1STAvalue, baudvalue);
}
void Init_UART2(void)
{
unsigned int baudvalue, U1MODEvalue, U1STAvalue;
CloseUART2();
ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS);
U1MODEvalue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK &
UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
U1STAvalue = UART_TX_PIN_NORMAL & UART_TX_ENABLE &
UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
baudvalue =8; //((FOSC/(16*BAUDRATE)) - 1); //this expression doesn't work, i'm probably doing something wrong
OpenUART2(U1MODEvalue, U1STAvalue, baudvalue);
}
void Init_SPI1(void)
{
unsigned int SPICONValue, SPISTATValue;
CloseSPI1();
SPICONValue = FRAME_ENABLE_OFF &
FRAME_SYNC_OUTPUT &
ENABLE_SDO_PIN &
SPI_MODE16_OFF &
SPI_SMP_ON &
SPI_CKE_ON &
SLAVE_ENABLE_OFF &
CLK_POL_ACTIVE_HIGH &
MASTER_ENABLE_ON &
SEC_PRESCAL_4_1 &
PRI_PRESCAL_16_1;
SPISTATValue = SPI_ENABLE &
SPI_IDLE_STOP &
SPI_RX_OVFLOW_CLR;
OpenSPI1(SPICONValue,SPISTATValue);
EnableIntSPI1;
SetPriorityIntSPI1(2);
}
void SendSD(unsigned int databyte)
{
SDCS=0;
nanodelay();
nanodelay();
nanodelay();
nanodelay();
WriteSPI1(charbuf);
//SDCS=0;can't do this here, must do it in ISR after byte finishes sending
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void _ISR _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0;
//while(U1STAbits.URXDA ==1){
charbuf =ReadUART1();
//
SendSD(charbuf);
}
void _ISR _U2RXInterrupt(void)
{
IFS1bits.U2RXIF = 0;
charbuf = ReadUART2();
//WriteUART1(charbuf);
}
void _ISR _SPI1Interrupt(void)
{
IFS0bits.SPI1IF =0;
nanodelay();
nanodelay();
SDCS=1; //Tell SD card that previous byte has finished sending
charbuf = ReadSPI1();
WriteUART1(charbuf);
}
/end sdaccess.c
/begin delays.h
//Delay Routines
void delay(void);
void tinydelay (void);
void microdelay (void);
void nanodelay(void);
void picodelay64(void);
/end delays.h
/begin delays.c
//---------------------------------------------------------------------
void tinydelay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=500 ; outer++)
{
for (inner=1; inner <=100 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void microdelay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=100 ; outer++)
{
for (inner=1; inner <=100 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void nanodelay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=10 ; outer++)
{
for (inner=1; inner <=10 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void picodelay64(void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=2 ; outer++)
{
for (inner=1; inner <=2 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void delay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=5500 ; outer++)
{
for (inner=1; inner <=500 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
/end delays.c
Below is pseudocode and code. The code serves the function of piping spi<-->uart, and handshaking with the card to figure out when it wants the master to clock data out, so one can work in terminal just to speed debugging.
Pseudocode:
1) you'll need the following pins
SPI_MOSI, SPI_MISO, SPI_CLK, SPI_CS#, BUSY, DIR, RESET
from your microcontroller's point of view, CS, and Reset are outputs, Busy and Dir are inputs.
A) reset the module:
At power up, set Reset to 0,
set CS# to 1
delay for 10uS or longer
set Reset to 1. -- reset is active low, so 1 is 'run', 0 is 'reset'
B) connect to the module:
set up your spi module such that:
clock resting state is HIGH
data clocked out(of microcontroller) on rising edge
data clocked in(to microcontroller) on falling edge
8 bit transmission
unframed
C) you can tell the DOSonCHIP has info to send when:
Direction =0 and Busy = 0
if this is the case, clock an FF into the module to extract a data byte
if Direction and busy don't change state, keep sending FF's until they do
(might work with other characters, haven't tried)
D) Sending requires the following:
Set CS to 0 -- selects the module
delay (I'm using a microsecond or two, might work with tighter timing)
Send data to your SPI output
When data finishes clocking out of the SPI, delay again(microsecond or so)
Set CS to 1 -- informs the module the byte has finished transmitting
Code:
/begin SDaccess.c
//*****************************************************************
//*FILENAME: SDaccess.c
//AUTHOR: Aiden Morrison
//DESCRIPTION: Access and control of an SD media card via a wearable inc
//DOSonCHIP device.
//*****************************************************************
//TARGET DEVICE: DSPIC30F4011
//*****************************************************************
#include "C:\Program Files\Microchip\MPLAB C30\support\h\p30F4011.h"
#include "C:\Program Files\Microchip\MPLAB C30\support\h\spi.h"
#include "C:\Program Files\Microchip\MPLAB C30\support\h\uart.h"
// the above include path may be different for each user. If a compile
// time error appears then check the path for the file above and edit
// the include statement above.
//Define Pins's
#define L0 LATBbits.LATB0 //Indicator LED
//SD Card handling pins
#define SDCS LATFbits.LATF0 //SD card Chip Select signal
#define SDBusy PORTEbits.RE5 //SD card Busy signal
#define SDDir PORTEbits.RE3 //SD card Data Direction Signal
#define SDCD PORTEbits.RE2 //SD card presence detect
#define SDRst LATEbits.LATE0 //DOSonChip Reset signal
//#define FOSC 16000000
//#define BAUDRATE 115200
//---------------------------------------------------------------------
// Definitions for subroutines
void SetupPorts(void);
void Init_UART1(void);
void Init_UART2(void);
void Init_SPI1(void);
//SDcard handling functions
void SendSD(unsigned int databyte);
//Global Variables
unsigned char charbuf;
//---------------------------------------------------------------------
int main(void)
{
SetupPorts(); // Initialize I/O
Init_UART1();
Init_UART2();
Init_SPI1();
while(1)
{
SDRst=0; //Reset SDcard
SDCS=1; //De-select SDcard
L0=1;
WriteUART1('B'); //UART1 'Alive' check character
delay();
L0=0;
SDRst = 1; //Active low reset, release card from reset
while(1)
{
L0=SDBusy;
// This code checks to see if the SDCard has something to say
//if it does, it clocks it out by sending FF's... don't know if
//other characters work just as well or not.
if (SDDir ==0 && SDBusy ==0){
microdelay();
if (SDDir==0 && SDBusy ==0){
SendSD(0xFF);
}
}
}
}
} // end main
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void SetupPorts(void)
{
//B0 LED output - set pin as digital
ADPCFG= 0x0001; //Turn RB0 to digital pin for L0
TRISB = 0xFFFE; //alter tristate to output
TRISE = 0xFFFE; //Everything on Port E is an input but RE0, which is Card Reset
TRISF = 0xFFFE; //" " F " " RF0, " " Chip Select SD card
SDRst = 0;
SDCS = 0;
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void Init_UART1(void)
{
unsigned int baudvalue, U1MODEvalue, U1STAvalue;
CloseUART1();
ConfigIntUART1(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS);
U1MODEvalue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK &
UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
U1STAvalue = UART_TX_PIN_NORMAL & UART_TX_ENABLE &
UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
baudvalue =8;
//4MHz crystal with 16xpll
//8;//115200
//16; //57600
//25; //38400
//34; //28800
//68; //14400
//((FOSC/(16*BAUDRATE)) - 1); //this expression doesn't work, i'm probably doing something wrong
OpenUART1(U1MODEvalue, U1STAvalue, baudvalue);
}
void Init_UART2(void)
{
unsigned int baudvalue, U1MODEvalue, U1STAvalue;
CloseUART2();
ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR4 & UART_TX_INT_DIS);
U1MODEvalue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK &
UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
U1STAvalue = UART_TX_PIN_NORMAL & UART_TX_ENABLE &
UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
baudvalue =8; //((FOSC/(16*BAUDRATE)) - 1); //this expression doesn't work, i'm probably doing something wrong
OpenUART2(U1MODEvalue, U1STAvalue, baudvalue);
}
void Init_SPI1(void)
{
unsigned int SPICONValue, SPISTATValue;
CloseSPI1();
SPICONValue = FRAME_ENABLE_OFF &
FRAME_SYNC_OUTPUT &
ENABLE_SDO_PIN &
SPI_MODE16_OFF &
SPI_SMP_ON &
SPI_CKE_ON &
SLAVE_ENABLE_OFF &
CLK_POL_ACTIVE_HIGH &
MASTER_ENABLE_ON &
SEC_PRESCAL_4_1 &
PRI_PRESCAL_16_1;
SPISTATValue = SPI_ENABLE &
SPI_IDLE_STOP &
SPI_RX_OVFLOW_CLR;
OpenSPI1(SPICONValue,SPISTATValue);
EnableIntSPI1;
SetPriorityIntSPI1(2);
}
void SendSD(unsigned int databyte)
{
SDCS=0;
nanodelay();
nanodelay();
nanodelay();
nanodelay();
WriteSPI1(charbuf);
//SDCS=0;can't do this here, must do it in ISR after byte finishes sending
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void _ISR _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0;
//while(U1STAbits.URXDA ==1){
charbuf =ReadUART1();
//
SendSD(charbuf);
}
void _ISR _U2RXInterrupt(void)
{
IFS1bits.U2RXIF = 0;
charbuf = ReadUART2();
//WriteUART1(charbuf);
}
void _ISR _SPI1Interrupt(void)
{
IFS0bits.SPI1IF =0;
nanodelay();
nanodelay();
SDCS=1; //Tell SD card that previous byte has finished sending
charbuf = ReadSPI1();
WriteUART1(charbuf);
}
/end sdaccess.c
/begin delays.h
//Delay Routines
void delay(void);
void tinydelay (void);
void microdelay (void);
void nanodelay(void);
void picodelay64(void);
/end delays.h
/begin delays.c
//---------------------------------------------------------------------
void tinydelay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=500 ; outer++)
{
for (inner=1; inner <=100 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void microdelay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=100 ; outer++)
{
for (inner=1; inner <=100 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void nanodelay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=10 ; outer++)
{
for (inner=1; inner <=10 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void picodelay64(void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=2 ; outer++)
{
for (inner=1; inner <=2 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
//---------------------------------------------------------------------
void delay (void)
{
unsigned int counter;
unsigned int outer;
unsigned int inner;
counter=0;
for (outer=1; outer <=5500 ; outer++)
{
for (inner=1; inner <=500 ; inner++)
{
}
}
if (counter == 0)
{
counter=1;
}
else
{
counter=0;
}
}
/end delays.c
Last edited by Cannibal on Sat Nov 11, 2006 10:44 am, edited 1 time in total.