1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

SD Card and SPI Communications

Discussion in 'Oshonsoft' started by Mity Eltu, Dec 11, 2015.

Tags:
  1. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    OK. I have just spent the better part of the day banging on this project and have found something that is either really irritating and incredibly frustrating or is a serious problem for oshonsoft, or I may just be an idiot and need help.

    This is the story...

    18F4520, 8MHz internal osc. LCD with 4 bit low on portd.
    I needed to be able to sample a thermocouple that will be using SPI to communicate with the PIC and then store the data on an SD card for later analysis on a PC. No problem.

    I was able to get the thermocouple working while displaying the current temp on the LCD within a few minutes. I am using the MAX6675 which incorporates a 12 bit A/D and cold junction compensation - kill 2 birds with one stone, right?

    Next came the SD card. I was able to get the SD card working great a few weeks ago. but then I added the SAME CODE from the working project into this one with the thermocouple. No dice. I checked, rechecked and double rechecked about a hundred times today. The SD card would not even be recognized. I am using a considerable portion of the code found on the oshosoft website for the SD Card Example (http://www.oshonsoft.com/sdcard.php). Like I said, it worked great when it was by itself. Logged data and was able to get the file off the card with a pc. No problem.

    So I decided to do a little side by side comparison of the code. The ONLY difference between the 2 was the SPI setup in the code with the thermocouple. I HAVE to have the SPI working to get data from the thermocouple. Apparently, the sdcardinit command does all this for the sd card. As soon as I removed the lines for SSPCON1 and SSTSTAT, the SD card started working.

    I have not yet had the time (as I have spent the ENTIRE day on this one part) to see if this has made it impossible for the thermocouple to communicate - though I suspect it has.

    This is a serious problem as I need the communications for both in the same project and on the same chip. Has anyone come across this before? Is there a fix? Am I just an idiot and the SPI communications will work just fine wihtout the SSPCON1 and SSPSTAT registers being set?

    What say you all?
     
  2. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,174
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    ONLINE
    hi Mity,
    I wrote some Oshonsoft 18F4520 routines for the SD card some time ago, I had some problems with some Basic commands listed in the manual, that the compiler would not recognise.
    I contacted Vladimir with a Bug report, he replied I should fit more decoupling caps!, how that would solve the compiler problem is anyone's guess.!

    Sometimes the SD card would record and read the Formatted Data and other times it would lock up. [I didn't want to use the Raw data option ]

    If you post your SD coding, full program, I will set up my development board and try the code.

    E
     
  3. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    9,146
    Likes:
    907
    Location:
    Rochdale UK
    ONLINE
    One of the biggest problems with SD cards is that some struggle at 3v3.... When you use two diodes from a 5v rail the SD can get 3v6 ~ 3v8 which gives "Non Branded" SD's a bit more of a boost...

    The best solution is to run little units like this on a 3v7 lithium battery.... Plenty of power.. Just make sure you use 1uf decoupling caps... 0.1uf isn't really big enough as when the card starts writing / reading the power really jumps up!
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA

    I'll try this when I get back to work Monday. I'll post the segments of code that work independently and then try to use them other. Hopefully the SPI will work with the sd card AND the thermocouple in the same circuit.

    Thanks for the advice.
     
  6. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    OK, Attached is the code I am using. It does very little at the moment, but it does recognize the SD card. I have another program that I have used that is similar to this that will write the data into a CSV text file. This is a stripped down version of that one.
    The problem now is that the program locks up at the WHILE SSPSTAT.0 = 0 command. I am guessing that since the SPI has not been set up using the 2 registers, the MSSP module doesn't know what to do with the commands. That means I will have to go back to bit banging all this SD card stuff. THAT's going to be an issue.

    If you can find a problem with the code that is causing this issue, I would really appreciate it. In the mean time I am going to start working on a bit bang version of the SPI code that maybe I can get to work with the sd card. This is a serious flaw with the compiler, IMO, if the SPI commands can't be used with other SPI devices when an SD card is used.

    On a side note, the power supply I am using shuld be capable of powering this and many other devices simultaneously. I am using an 480W ATX power supply that is properly filtered and decoupled. The scope shows no ripple/noise on the power supply rails when the chip is switching multiple led's simultaneously.


    Code (text):
    '18F4520
    'internal 8 MHz clock
    'Full size SD Card Reader
    'porte2 = chip select SD card
    'porte0 = chip select MAX6675
     
     
    'NOTE
    'This program worked as expected
    'AFTER I REMOVED THE SPI SETUP PARAMETERS
     
     
    '12/14/15
    'adding thermocouple solution using MAX6675
    'uses SPI - testing to see if this will work with the
    'existing sd card configuration
    'If this does not work, I will try the sd card using a
    'direct interface as opposed to the card module in
    'curretn use
     
    Define CONFIG1L = 0x00
    Define CONFIG1H = 0x08
    Define CONFIG2L = 0x19
    Define CONFIG2H = 0x00
    Define CONFIG3L = 0x00
    Define CONFIG3H = 0x85
    Define CONFIG4L = 0x80
    Define CONFIG4H = 0x00
    Define CONFIG5L = 0x0f
    Define CONFIG5H = 0xc0
    Define CONFIG6L = 0x0f
    Define CONFIG6H = 0xe0
    Define CONFIG7L = 0x0f
    Define CONFIG7H = 0x40
     
    'LCD Configuration - 4-bit lower
    Define LCD_LINES = 2
    Define LCD_CHARS = 16
    Define LCD_BITS = 4
    Define LCD_DREG = PORTD
    Define LCD_DBIT = 4
    Define LCD_RSREG = PORTD
    Define LCD_RSBIT = 0
    Define LCD_RWREG = PORTD
    Define LCD_RWBIT = 1
    Define LCD_EREG = PORTD
    Define LCD_EBIT = 2
     
    'SPI Configuration
    Define SPI_CS_REG = PORTE
    Define SPI_CS_BIT = 2
    Define SPI_SCK_REG = PORTC
    Define SPI_SCK_BIT = 3
    Define SPI_SDI_REG = PORTC
    Define SPI_SDI_BIT = 4
    Define SPI_SDO_REG = PORTC
    Define SPI_SDO_BIT = 5
    'SPIINIT is NOT used in the program
     
    Define CLOCK_FREQUENCY = 8
     
    'global variables
    Dim flags As Byte
     
    'variables required for MAX6675 sections
    Dim mb1 As Byte
    Dim mb2 As Byte
    Dim max6675 As Word
    Dim temp As Single
    Dim deg As Byte
     
    main:
        OSCCON = 0x72  'internal 8MHz
        Gosub setup
        Lcdinit 0
     
     
        Lcdout "Ready"
        WaitMs 1000
        Lcdcmdout LcdClear
     
        SDCardInit
            WaitMs 2000
            Lcdcmdout LcdLine1Clear
            Lcdcmdout LcdLine1Home
            If sd_status.sd_error = 1 Then Lcdout "Unknown Card"
            If sd_status.sd_mmc = 1 Then Lcdout "MMC Card"
            If sd_status.sd_sd = 1 Then Lcdout "SD Card"
            If sd_status.sd_sdsc = 1 Then Lcdout "SDSC Card"
            If sd_status.sd_sdhc = 1 Then Lcdout "SDHC Card"
     
        Lcdcmdout LcdLine2Clear
    loop:
        If flags.0 = 1 Then
            flags.0 = 0
            While PORTB.0 = 1
            Wend
       
            WaitMs 200
            Toggle PORTE.1
       
            Gosub get_temp
            Gosub convert
       
            Lcdcmdout LcdLine2Clear
            Lcdout #temp
            Lcdout deg, "C  "
       
            temp = temp * 1.8 + 32
            Lcdout #temp, deg, "F"
        Endif
        Goto loop  'infinite loop
    End                                          
     
     
    setup:
        INTCON = 0xd0  'int0 en
        INTCON2 = 0xc0  'pull ups disabled, int0 on rising egde
     
        CCP1CON = 0x00  'cap / comp off
        CCP2CON = 0x00
     
        'SSPCON1 = 0x21  'spi on, fosc/16, clk idle state low
        'SSPSTAT = 0x40  'sample in middle, cke=1 - xfer on clk high to low
     
        ADCON0 = 0x00  'A/D off
        ADCON1 = 0x0f  'all digital
     
        CMCON = 0x07  'comp off, digital io
        CVRCON = 0x00
       
        HLVDCON = 0x00  'Low volt detect off
     
        TRISA = 0x00
        TRISB = 0x01
        TRISC = 0x00
        TRISC.4 = 1  'sdi input
        TRISD = 0x00
        TRISE = 0x00
     
        LATA = 0x00
        LATB = 0x00
        LATC = 0x00
        LATD = 0x00
        LATE = 0x0f  'porte2 set for sd card chip select
     
        flags = 0x00
        deg = 0xdf  'degree symbol
    Return                                      
     
     
    get_temp:
            'get new temperature reading and store in eeprom
            'MAX6675 temperature reading
            'this chip has no SPI input
            'all this chip is expecting is a clock source
            PORTE.0 = 0  'chip select
     
            SSPBUF = 0x11  'send dummy byte to receive first byte from chip
            While SSPSTAT.0 = 0
            Wend
            mb1 = SSPBUF
            SSPSTAT.0 = 0
     
            SSPBUF = 0x22  'send dummy byte to receive second byte from chip
            While SSPSTAT.0 = 0
            Wend
            mb2 = SSPBUF
            SSPSTAT.0 = 0
       
            PORTE.0 = 1  'deselct chip
    Return                                      
     
     
    convert:
            max6675.HB = mb1
            max6675.LB = mb2
            max6675 = ShiftRight(max6675, 3)
            max6675 = max6675 - 5
       
            mb1 = max6675.HB
            mb2 = max6675.LB
       
            temp = max6675 / 4
    Return                                      
     
     
    On High Interrupt
        If INTCON.1 = 1 Then  'int0
            INTCON.1 = 0
            flags.0 = 1
        Endif
    Resume                                      
     
     
    Last edited: Dec 14, 2015
  7. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    OK, WOW. I just finished readin a ton of stuff on SPI commincations and there is no way I am gouing to be able to bitbang an spi platform that will permit me to write a CSV file onto this sd card. Frankly, I aint smart enough for that. I'm going to submit a possible bug report to vladimir and hope there is a solution, otherwise, I'll HAVE to abandon oshonsoft in favor of a platform that will alow me to use the spi bus for sd cards AND other peripherals at the same time.

    Hope someone out there knows how to fix this. I really don't want to find yet another compiler.
     
  8. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    I have been thinking. I can find no way to force the SPI module to work with both the SD card and a separate peripheral that uses SPI communications. Something about the differing setups wil not allow them to work at the same time. I tried al kinds of combinations of the code to try to force it. I do have them working independently.

    This one takes readings from a dallas temperatre 1-wire sensor and stores data on the SD card without any problems:
    Code (text):
    Define SPI_CS_REG = PORTC
    Define SPI_CS_BIT = 2
    Define SPI_SCK_REG = PORTC
    Define SPI_SCK_BIT = 3
    Define SPI_SDI_REG = PORTC
    Define SPI_SDI_BIT = 4
    Define SPI_SDO_REG = PORTC
    Define SPI_SDO_BIT = 5
     
    Define LCD_LINES = 2
    Define LCD_CHARS = 16
    Define LCD_BITS = 4
    Define LCD_DREG = PORTD
    Define LCD_DBIT = 4
    Define LCD_EREG = PORTD
    Define LCD_EBIT = 3
    Define LCD_RSREG = PORTD
    Define LCD_RSBIT = 2
    Define LCD_RWREG = PORTD
    Define LCD_RWBIT = 1
     
    Define 1WIRE_REG = PORTE
    Define 1WIRE_BIT = 0
     
    Define CLOCK_FREQUENCY = 8
    'Define SIMULATION_WAITMS_VALUE = 10
     
    Dim finish As Bit
    Dim temp_lsb As Byte
    Dim temp_msb As Byte
    Dim dat As Byte
    Dim tenths As Single
    Dim temp_out As Single
    Dim loop As Bit
    Dim lp_cnt As Byte
    Dim end_loop As Bit
    Dim e_loop As Bit
    Dim ad_res As Long
    Dim tc_temp As Single
     
     
    main:
        OSCCON = 0x72  'internal, 8MHz
        Gosub setup
     
        Lcdinit LcdCurBlink
     
        WaitMs 2000
        Lcdcmdout LcdClear
        Lcdout "UL248 Fuse Test"
        Lcdcmdout LcdCurOff
       
        Gosub sd_start
       
        Lcdcmdout LcdClear
        Lcdout "Current Temp"
       
        While loop
            ADCON0.1 = 1  'start a/d
            1wireInit
            1wireSendByte 0xcc, 0x44
            WaitMs 750
    lp:
            1wireGetBit finish
            If finish = 0 Then Goto lp
            1wireInit
            1wireSendByte 0xcc, 0xbe
            1wireGetByte temp_lsb, temp_msb
            'Lcdout #temp_msb, " ", #temp_lsb
            Lcdcmdout LcdLine2Home
            dat = temp_lsb
            dat = dat And 0x0f
            tenths = dat * 0.062500
            temp_lsb = ShiftRight(temp_lsb, 4)
            temp_msb = ShiftLeft(temp_msb, 4)
            temp_lsb = temp_lsb Or temp_msb
            temp_out = temp_lsb + tenths
           
            WaitMs 200
            'get a/d result and convert to temp and
            'subtract cold junction temp
            ad_res.LB = ADRESL
            ad_res.HB = ADRESH
            tc_temp = ad_res * 0.00488280
            tc_temp = tc_temp / 416
           
            Call sd_t_out(temp_out)  'write degC to sd card
           
            Lcdout #temp_out, "C  "
            temp_out = temp_out * 1.8000 + 32
            Lcdout #temp_out, "F"
           
            Call sd_t_out(temp_out)  'write degF to sd card
           
            SDCardFAT32FileWrite CrLf  'new line
            Toggle LATA.3  'heartbeat
            WaitMs 3000
           
            lp_cnt = lp_cnt + 1
            If lp_cnt = 20 Then
                SDCardFAT32FileClose
                If sd_fat32_status.sd_fat32_wr_opened = 0 Then
                    Lcdcmdout LcdClear
                    Lcdout "UL248.txt clsd!"
                Endif
                While end_loop
                Wend
            Endif
        Wend
    End                                              
     
     
    setup:
        INTCON = 0x00  'glbl/periph int dis
     
        CCP1CON = 0x00  'cap/comp off
     
        ADCON0 = 0x01  'a/d off
        ADCON1 = 0x0e  'an0
        ADCON2 = 0x91  'rt just
       
        CMCON = 0x07
       
        CVRCON = 0x00
       
        HLVDCON = 0x00
       
        'all output
        TRISA = 0x01
        LATA = 0x00
       
        TRISB = 0x00
        LATB = 0x00
       
        TRISC = 0x00
        LATC = 0x00
       
        TRISD = 0x00
        LATD = 0x00
       
        TRISE = 0x00
        LATE = 0x00
       
        lp_cnt = 0
        loop = 1
        end_loop = 1
        e_loop = 1
    Return                                          
     
     
    sd_start:
        SDCardInit
     
        WaitMs 2000
        Lcdcmdout LcdClear
        If sd_status.sd_error = 1 Then
            Lcdout "Unknown card!"
            While e_loop = 1
            Wend
        Endif
        If sd_status.sd_mmc = 1 Then Lcdout "MMC card!"
        If sd_status.sd_sd = 1 Then Lcdout "SD card!"
        If sd_status.sd_sdsc = 1 Then Lcdout "SDSC card!"
        If sd_status.sd_sdhc = 1 Then Lcdout "SDHC card!"
        WaitMs 1000  'time to reseat if needed
       
        SDCardFAT32Init
        Lcdcmdout LcdClear
        If sd_fat32_status.sd_fat32_error = 0 Then
            Lcdout "FAT32 initlized!"
        Endif
       
        WaitMs 2000
        SDCardFAT32FileDelete "UL248.txt"
        If sd_fat32_status.sd_fat32_deleted = 1 Then
            Lcdcmdout LcdClear
            Lcdout "File Deleted"
        Endif
        SDCardFAT32FileCreate "UL248.txt"
        Lcdcmdout LcdClear
        If sd_fat32_status.sd_fat32_wr_opened = 1 Then
            Lcdout "UL248.txt open!"
        Endif
        WaitMs 2000
       
        SDCardFAT32FileWrite "degC,  degF", CrLf
    Return                                          
     
     
    Proc sd_t_out(dat As Single)
    'dat is composed of degC in xxx.xxxx format
        Dim lng_num_str As String
        Dim new_cnt As Single
        Dim num_part As String
        Dim digit As String
       
        lng_num_str = #dat
        new_cnt = dat
           
            If new_cnt >= 0 And new_cnt < 10 Then
                digit = LeftStr(lng_num_str, 1)
                SDCardFAT32FileWrite digit, "."
                num_part = LeftStr(lng_num_str, 3)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 4)
                digit = RightStr(num_part, 1)
            Endif
           
            If new_cnt >= 10 And new_cnt < 100 Then
                digit = LeftStr(lng_num_str, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 2)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit, "."
                num_part = LeftStr(lng_num_str, 4)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 5)
                digit = RightStr(num_part, 1)
            Endif
           
            If new_cnt >= 100 Then
                digit = LeftStr(lng_num_str, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 2)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 3)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit, "."
                num_part = LeftStr(lng_num_str, 5)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 6)
                digit = RightStr(num_part, 1)
            Endif
            SDCardFAT32FileWrite digit, ", "
    End Proc

    This one grabs data from a MAX6675 over SPI without any problem
    Code (text):

    'LCD Configuration - 4-bit lower
    Define LCD_LINES = 2
    Define LCD_CHARS = 16
    Define LCD_BITS = 4
    Define LCD_DREG = PORTD
    Define LCD_DBIT = 4
    Define LCD_RSREG = PORTD
    Define LCD_RSBIT = 0
    Define LCD_RWREG = PORTD
    Define LCD_RWBIT = 1
    Define LCD_EREG = PORTD
    Define LCD_EBIT = 2
     
    'SPI Configuration
    Define SPI_CS_REG = PORTE
    Define SPI_CS_BIT = 2
    Define SPI_SCK_REG = PORTC
    Define SPI_SCK_BIT = 3
    Define SPI_SDI_REG = PORTC
    Define SPI_SDI_BIT = 4
    Define SPI_SDO_REG = PORTC
    Define SPI_SDO_BIT = 5
    SPIPrepare
     
    Define CLOCK_FREQUENCY = 40
    Define SINGLE_DECIMAL_PLACES = 2
     
    'global variables
    Dim flags As Byte
    Dim i As Byte
    Dim mb1 As Byte
    Dim mb2 As Byte
    Dim max6675 As Word
    Dim temp As Single
    Dim t_av As Single
    Dim x As Byte
     
    main:
        OSCCON = 0x00  'external osc
        Gosub setup
       
        Lcdinit 0
       
        Lcdout "Ready"
        WaitMs 1000
     
        Lcdcmdout LcdClear
        Lcdout "Temperature:"
       
        Gosub get_temp
        Gosub convert
        Lcdcmdout LcdLine2Home
        Lcdout #temp
        x = 0xdf
        Lcdout x, "C  "
       
        temp = temp * 1.8 + 32
        Lcdout #temp, x, "F"
       
    loop:
        If flags.0 = 1 Then  'interrupt has occurred
            flags.0 = 0
            Gosub write_data
        Endif
       
        t_av = 0
        For i = 1 To 5
            Gosub get_temp
            Gosub convert
            t_av = t_av + temp
            WaitMs 400
        Next i
       
        temp = t_av / 5
       
        Lcdcmdout LcdLine2Clear
        Lcdout #temp
        Lcdout x, "C  "
       
        temp = temp * 1.8 + 32
        Lcdout #temp, x, "F"
       
        For i = 0 To 2  'blink to show complete
            LATE.1 = 1
            WaitMs 50
            LATE.1 = 0
            WaitMs 50
        Next i
        Goto loop  'infinite loop
    End                                              
     
     
    setup:
        INTCON = 0xd0  'int0 en
        INTCON2 = 0xc0  'pull ups disabled, int0 on rising egde
     
        CCP1CON = 0x00  'cap / comp off
        CCP2CON = 0x00
       
        SSPCON1 = 0x21  'spi on, fosc/16, clk idel state low
        SSPSTAT = 0x40  'sample in middle, cke=1 - xfer on clk high to low
       
        ADCON0 = 0x00  'A/D off
        ADCON1 = 0x0f  'all digital
       
        CMCON = 0x07  'comp off, digital io
        CVRCON = 0x00
           
        HLVDCON = 0x00  'Low volt detect off
       
        TRISA = 0x00
        'LATA.5 = 1
        TRISB = 0x01
        TRISC = 0x00
        'TRISC.4 = 1  'sdi input
        TRISD = 0x00
        TRISE = 0x00
       
        LATA = 0x00
        LATB = 0x00
        LATC = 0x00
        LATD = 0x00
        LATE = 0x01  'porte0 set for MAX6675 chip select
     
        flags = 0x00
    Return                                          
     
     
    get_temp:
            'get new temperature reading and store in eeprom
            'MAX6675 temperature reading
            'this chip has no SPI input
            'all this chip is expecting is a clock source
            PORTE.0 = 0  'chip select
       
            SSPBUF = 0x11  'send dummy buyte to receive first byte from chip
            While SSPSTAT.0 = 0
            Wend
            mb1 = SSPBUF
            SSPSTAT.0 = 0
       
            SSPBUF = 0x22  'send dummy buyte to receive first byte from chip
            While SSPSTAT.0 = 0
            Wend
            mb2 = SSPBUF
            SSPSTAT.0 = 0
           
            PORTE.0 = 1  'deselct chip
    Return                                          
     
     
    convert:
            max6675.HB = mb1
            max6675.LB = mb2
            max6675 = ShiftRight(max6675, 3)
            max6675 = max6675 - 5
           
            mb1 = max6675.HB
            mb2 = max6675.LB
           
            temp = max6675 / 4
    Return                                          
     
     
    write_data:
    'I never got this to work - This was going to be the SD Card data logging function
    Return                                          
     
     
    'Proc sspsend(adr As Byte, dat As Byte)
        'PORTA.5 = 0  'chip select
       
        'SSPBUF = 0x40  'send chip id, RW bit = 0 (write)
        'While SSPSTAT.0 = 0
        'Wend
        'SSPSTAT.0 = 0
       
        'SSPBUF = adr  'send address
        'While SSPSTAT.0 = 0
        'Wend
        'SSPSTAT.0 = 0
       
        'SSPBUF = dat  'send data
        'While SSPSTAT.0 = 0
        'Wend
        'SSPSTAT.0 = 0
       
        'PORTA.5 = 1
    'End Proc
     
    'Function sspread(adr As Byte) As Byte
        'PORTA.5 = 0  'chip select
       
        'SSPBUF = 0x41  'send chip id, RW bit = 1 (read)
        'While SSPSTAT.0 = 0
        'Wend
        'SSPSTAT.0 = 0
       
        'SSPBUF = adr  'send address
        'While SSPSTAT.0 = 0
        'Wend
        'SSPSTAT.0 = 0
       
        'send/receive is simultaneous, so when the dummy byte is sent
        'the byte I want to receive is also being clocked in
        'See datasheet: satates "17.3 SPI MODE
        'The SPI mode allows 8 bits of data to be SYNCHRONOUSLY
        'transmitted and received simulateously
        'SSPBUF = 0xff
        'While SSPSTAT.0 = 0
        'Wend
        'SSPSTAT.0 = 0
       
        'sspread = SSPBUF
     
        'PORTA.5 = 1
    'End Function
     
     
    On High Interrupt
        If INTCON.1 = 1 Then  'int0
            INTCON.1 = 0
            flags.0 = 1
        Endif
    Resume                                          
     
    I know they are for different chips, but the fact is, I can perform both functions independently. I can't get them to work on the same chip.

    So, I am thinking maybe use 2 separate chips. Both would need SPI and EUSART modules. I can use one to gather data from the MAX6675 and send via USART to the second. The second then operates as master and sends data to the SD Card. This is obviously not ideal, but what do you think? Workable?
     
  9. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    Ok. Finished coding 2 separate programs for 2 separate chips: 18F4550 is grabbing the data from the MAX6675 and sending via USART to 18F4520. The 18F4520 receives the data from the USART, converts it to °C and displays it on the LCD. I'll work on getting that data into the SD card tomorrow. Too tired.... head hurts.... walll... is... so... hard....

    Anyway, I only had these 2 chips. I will eventually use smaller chips (28 pin narrow dip) to save some realestate. Not an ideal solution, but it seems to work. I fugure there must be a way to combine the sd spi with other peripheral devices, but it's beyond my knowledge base to find it.

    I'll post the update after I get the sd card working.... notice the delusional optimism....

    Thanks for the help.
     
  10. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,174
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    ONLINE
    Hi Mity,
    Sorry for delayed reply.
    In the Spring of this year I had all Raw, 16FAT and 32FAT programs working OK.
    The only problem I had was that the Compiler did not recognise FileExist or FileAppend commands, I sent a bug report to Vlad, the reply I got was useless.

    The intention was to build a weather station data logger, using a RTC DS3231, DHT22,BMP180 modules, the data recorded on the SD Card would be read by the PC, the project worked OK on the bench.
    Due to other work, I had to set aside the project until a week ago, now only the Raw data option will work!!!.

    If and when I get back the FAT options I will try your code.:banghead:

    I guess you know that the FAT options require a PIC with greater than 1K of free SRAM.
    I use 18F2550, 18F4520 and 18F452 PIC's

    Eric
     
  11. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    Yeah, I'm making sure the chip can handle the code size. It seems if I am going to use a single chip solution that I'm going to have to use a different compiler. I cringe at the thought. I may just bite the bullet and use the 2 chip solution I mentioned above. I am not at work yet, so I don't know if it will do all I need, but so far it's looking good.
     
  12. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    Ok, the 2 chip solution works. I have a 18F4550 grabbing data from the max6675 and sending via spi to a 18F4520 via USART. The 18F4520 stores the data on an SD Card in SPI mode and displays the data on an LCD. This is ok. Not great, but workable.

    However, now a new issue is up. I apparently have to wait for all the data to be written before I can remove the SD card or the file that I am creating is blank. I have tried issuing the SDCardFAT32FileClose command, and that does in fact close the file so that the data written before the command is in the file, but then I can write no more data to the file. The program freezes if I try to reinitialze the SD Card. This tells me that I can opnly open the file once, write all the data and then close the file. After that, there is no way to apparently reopen the file for anything else. I have tried the FaileAppend command as well with no luck.

    Has anyone run acros this before? Am I doing something wrong? Is there a special sequence or specific time delay that I have to have for this to work?

    Any thoughts?
     
  13. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,174
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    ONLINE
    hi,
    The FileAppend command is a command I have never been able to get working, I did send a bug report.

    BTW I now have my FAT32 working again with a18F2550, but cannot get the UART to transmit uncorrupted data, a bug report has been sent.

    Post the program code that is locking up, I will try it.

    Eric
    EDIT:
    Try this.
    Code (text):
    Define CONFIG1L = 0x3c
    Define CONFIG1H = 0x0c
    Define CONFIG2L = 0x18
    Define CONFIG2H = 0x00
    Define CONFIG3L = 0x00
    Define CONFIG3H = 0x83
    Define CONFIG4L = 0x80
    Define CONFIG4H = 0x00
    Define CONFIG5L = 0x0f
    Define CONFIG5H = 0xc0
    Define CONFIG6L = 0x0f
    Define CONFIG6H = 0xe0
    Define CONFIG7L = 0x0f
    Define CONFIG7H = 0x40


    'redo, 16Dec2015 this program works OK with 8Gb SD

    'demo5b 18F2550

    Define STRING_MAX_LENGTH = 16
    Define CLOCK_FREQUENCY = 20

    AllDigital

    Dim cnt As Byte
    Dim word_var As Word

    Dim file_data(32) As Byte

    Define LCD_LINES = 4
    Define LCD_CHARS = 16
    Define LCD_BITS = 4
    Define LCD_DREG = PORTB
    Define LCD_DBIT = 4

    Define LCD_EREG = PORTB
    Define LCD_EBIT = 3
    Define LCD_RSREG = PORTB
    Define LCD_RSBIT = 2
    Define LCD_RWREG = PORTC
    Define LCD_RWBIT = 0
    Define LCD_READ_BUSY_FLAG = 1


    Define SPI_CS_REG = PORTA
    Define SPI_CS_BIT = 5
    Define SPI_SCK_REG = PORTB
    Define SPI_SCK_BIT = 1
    Define SPI_SDI_REG = PORTB
    Define SPI_SDI_BIT = 0
    Define SPI_SDO_REG = PORTC
    Define SPI_SDO_BIT = 7

    INTCON2 = 0x00

    PORTB = 0
    LATB = 0
    ADCON1 = 0xff
    TRISB = %11110101
    TRISA = 0x00

    Lcdinit
    Lcdout "FAT32a 17-12-15"
    WaitMs 500

    SDCardInit

    SDCardFAT32Init
    Lcdcmdout LcdClear

    If sd_fat32_status.sd_fat32_error = 0 Then
    Lcdout "FAT32 init OK"
    Else
    Lcdout "Init Fail!"
    Endif

    WaitMs 500

    SDCardFAT32FileCreate "mydata1.txt"
    Lcdcmdout LcdClear

    If sd_fat32_status.sd_fat32_wr_opened = 1 Then
    Lcdout "mydata1 Created"
    Endif
    WaitMs 500

    For cnt = 1 To 100
    SDCardFAT32FileWrite "17December2015", CrLf
    Next cnt

    Lcdcmdout LcdLine1Clear
    If sd_fat32_status.sd_fat32_wr_opened = 0 Then
    Lcdout "mydata1 written!"
    Endif
    SDCardFAT32FileClose
    WaitMs 500

    SDCardFAT32FileOpen "mydata1.txt"
    Lcdcmdout LcdLine1Clear
    If sd_fat32_status.sd_fat32_notfound = 1 Then
    Lcdout "Not found!"
    Endif

    If sd_fat32_status.sd_fat32_opened = 1 Then
    Lcdout "mydata1 found!"
    WaitMs 500
    Lcdcmdout LcdLine1Clear
    Lcdout "filesize: ", #sd_fat32_filelen
    WaitMs 500
    Gosub read_file
    Endif

    SDCardFAT32FileClose

    End                                              

    read_file:
    SDCardFAT32FileRead
    Lcdcmdout LcdLine2Clear
    Lcdout "Rd Cnt Dwn:", #sd_fat32_filelen
    WaitMs 100
    For cnt = 0 To 31
    file_data(cnt) = sd_fat32_buff(cnt)
    Next cnt
    Lcdcmdout LcdLine3Clear
    Lcdcmdout LcdLine4Clear

    Lcdcmdout LcdLine3Home
    For cnt = 0 To 15
    Lcdout file_data(cnt)
    Next cnt
    Lcdcmdout LcdLine4Home
    For cnt = 16 To 31
    Lcdout file_data(cnt)
    Next cnt


    WaitMs 100

    If sd_fat32_bytes_read = 0 Then Return
    Goto read_file
    Return                                          
     
     
    Last edited: Dec 17, 2015
  14. jayanthd

    jayanthd New Member

    Joined:
    Dec 17, 2015
    Messages:
    6
    Likes:
    0
    In PIC18F for output ports or pins you have to use LATx

    Replace
    Code (text):

    Define LCD_EREG = PORTB
     
    with

    Code (text):

    Define LCD_EREG = LATB
     
     
  15. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    Zoiks.

    Well, while this is not really a bug, it is certainly not documented and is rather inconvenient. After toying with this for a number of hours, arranging and rearranging the various commands I found that as long as all the sd card initialization commands AND all the open, write, append etc commands are in the main body, that is, not separated by a level of subroutine/function calls then everything works like it should. Very frustrating. This means there is much less modularity to my code. It works, but it's uglier than it was.... and I didn't think that was possible. I'll post my code next week so everyone can see the mess... I mean fun I've been having.

    on a new note: has anyone encountered rounding errors hen using Single data type variables? I will pen a new thread for that.
     
  16. Mity Eltu

    Mity Eltu Member

    Joined:
    Apr 1, 2014
    Messages:
    49
    Likes:
    0
    Location:
    Tennessee, USA
    OK. Got a reply from Vladimir. The current configuration of the SD Card commands and the SPI module precludes operation of both at the same time. In other words, you can't use the SD Card commands and then turn around and use the SPI module for other communications. That's sad. That significantly limits the functionality of the compiler as a viable alternative when faced with some of the tasks I need to perform.

    That said, as promised, here's the code for the WORKING SD Card datalogger. There are 2 chips I have working together for this project. I have a 18F4550 that takes thermocouple readings and sends the data via USART to a 18F4520. The 18F4520 crunches the numbers and stores the temperatures on the SD Card using the commands. The biggest problem (aside form using SPI and the SD Card module at the same time - shame) was getting the data to write to the card and close the file so that, in the event the card were removed, the data would be viewable on the card. In other words, if the file that I am writing to is not closed in some way, when the card is read by a PC, there was no actual data on it. The reason for this has something to do with putting the SD Card write sequences in a subroutine. When the subroutine finished, there was no way to reopen the file for writing data. The fileope and fileappend commands didn't do anything. Apparently they must be preceeded by the sdcardinit and sdcardfat32init commands. Tryong to use these commands in more than 1 place in the program caused all kinds of bad behavior. The solution? I had to move all the sd card writing to the main body of the program. That way I only needed to initialize the sd card stuff once. From there, there fileappend command worked as needed.

    Sorry if that was a little verbose.

    Anyway, here's the code. Some of the wait periods are really long, and I don't know yet I can make them shorter. That's the next step, but in the meantime, I hope this helps someone else who may be struggling with this.
    Code (text):
    '18F4520
    'internal 8MHz osc
     
    'the purpose of this program is to receive data via
    'USART from the slave device 18F4550, process the
    '2 bytes received into a deg C value, display
    'the value on the LCD and store the value on an SD Card
     
    'The original version of this program works as anticipated.
    'This rev will attempt to add SD Card datalogging
     
    'This works as expected.
    'Timer 0 is added to give timing for roughly 5 minutes.
    'This will need to be changed to an RTC for the prototype
    'The unit should have approximately 12 entries per hour.
    'For this test there should be 13 entries:
    'initial temp + 12 at roughly 5 minumte increments
     
    'need to implement a write finish routine for each write cycle
    'so that if the card is removed, the data is retained.
     
    'This program works as expected.
     
    Define CONFIG1L = 0x00
    Define CONFIG1H = 0x08
    Define CONFIG2L = 0x19
    Define CONFIG2H = 0x00
    Define CONFIG3L = 0x00
    Define CONFIG3H = 0x85
    Define CONFIG4L = 0x80
    Define CONFIG4H = 0x00
    Define CONFIG5L = 0x0f
    Define CONFIG5H = 0xc0
    Define CONFIG6L = 0x0f
    Define CONFIG6H = 0xe0
    Define CONFIG7L = 0x0f
    Define CONFIG7H = 0x40
     
    'LCD Configuration - 4-bit lower
    Define LCD_LINES = 2
    Define LCD_CHARS = 16
    Define LCD_BITS = 4
    Define LCD_DREG = PORTD
    Define LCD_DBIT = 4
    Define LCD_RSREG = PORTD
    Define LCD_RSBIT = 0
    Define LCD_RWREG = PORTD
    Define LCD_RWBIT = 1
    Define LCD_EREG = PORTD
    Define LCD_EBIT = 2
     
    'SPI Configuration
    Define SPI_CS_REG = PORTE
    Define SPI_CS_BIT = 2
    Define SPI_SCK_REG = PORTC
    Define SPI_SCK_BIT = 3
    Define SPI_SDI_REG = PORTC
    Define SPI_SDI_BIT = 4
    Define SPI_SDO_REG = PORTC
    Define SPI_SDO_BIT = 5
     
    Define CLOCK_FREQUENCY = 8
    Define SINGLE_DECIMAL_PLACES = 2
    Define SDCARD_DEFAULT_WRITE = 0x00
     
    'global variables
    Dim flags As Byte
    Dim x As Byte  'deg symbol
    Dim max_dat As Word
    Dim temp As Single
    Dim dat As Byte
    Dim i As Word
    Dim cnt As Byte
     
    main:
        OSCCON = 0x72  'internal 8MHz
        Gosub setup
       
        Lcdinit 0
        Hseropen 9600
       
        Lcdout "Ready"
        WaitMs 1000
     
        Lcdcmdout LcdClear
        Lcdout "Temperature:"
     
        'initialize the sd card
        'This was originally in a subroutine, but the append command
        'would not work wihtout the initialize command comming first
        'and initializing a second time caused the program to freeze.
        '---------------------------------------------------
        SDCardInit
     
        WaitMs 1000
        Lcdcmdout LcdClear
        If sd_status.sd_error = 1 Then Lcdout "Unknown card!"
        While sd_status.sd_error = 1
        Wend
        If sd_status.sd_mmc = 1 Then Lcdout "MMC card!"
        If sd_status.sd_sd = 1 Then Lcdout "SD card!"
        If sd_status.sd_sdsc = 1 Then Lcdout "SDSC card!"
        If sd_status.sd_sdhc = 1 Then Lcdout "SDHC card!"
        WaitMs 1000
       
        SDCardFAT32Init
        Lcdcmdout LcdClear
        If sd_fat32_status.sd_fat32_error = 0 Then
            Lcdout "FAT32 initialized!"
        Else
            Lcdout "Not init."
        Endif
       
        WaitMs 2000
        SDCardFAT32FileCreate "UL248.txt"
        Lcdcmdout LcdClear
        If sd_fat32_status.sd_fat32_wr_opened = 1 Then
            Lcdout "UL248.txt created!"
        Else
            Lcdout "not created"
        Endif
        WaitMs 2000
        '--------------------------------------------------------
       
        SDCardFAT32FileWrite "TC1, TC2", CrLf
        SDCardFAT32FileClose
       
        Lcdcmdout LcdLine2Home
        x = 0xdf  'degree symbol
        'Lcdout x, "C"
        WaitMs 1000
       
       
        T0CON.7 = 1  'start tmr0
        i = 0
        flags.0 = 1  'take initial temp
        cnt = 1  'make this 1 less than the setting for the loop
    loop:
        If flags.0 = 1 Then
            flags.0 = 0
            cnt = cnt + 1
            If cnt = 2 Then  '(should be set for 5 minutes)start routine: get temps, send to sd card
                cnt = 0  'reset interrupt count
               
                SDCardFAT32FileAppend "UL248.txt"  'this reopens the file for additional data
                WaitMs 1000
           
                Toggle PORTE.1
                Lcdcmdout LcdLine2Home
               
                Hserout 0x11  'send rdy
               
                'get tc1 data
                Hserin dat  'the program will wait here till a byte is received
                max_dat.HB = dat
                Hserin dat
                max_dat.LB = dat
                temp = max_dat / 4
                Lcdout "1:", #temp
                Call sd_t_out(temp)
       
                'clear possible errors
                RCSTA.FERR = 0  'framing
                RCSTA.OERR = 0  'overrun
                WaitMs 200
       
                Toggle PORTE.1
                'get tc2 data
                Hserin dat  'the program will wait here till a byte is received
                max_dat.HB = dat
                Hserin dat
                max_dat.LB = dat
                temp = max_dat / 4
                Lcdout " 2:", #temp
                Call sd_t_out(temp)
                SDCardFAT32FileWrite CrLf
                SDCardFAT32FileClose
                WaitMs 500
               
                i = i + 1
               
                If i = 500 Then  'closing will be only after themral stability
                    SDCardFAT32FileClose
                    Lcdcmdout LcdClear
                    Lcdout "Finished"
                    here: Goto here
                Endif
            Endif
        Endif
       
        Goto loop  'infinite loop
    End                                              
     
     
    setup:
        INTCON = 0xe0  'tmr0 int enabled
        INTCON2 = 0x84  'pull ups disabled, tmr0 int hi priority
        RCON.7 = 1  'priority ints enabled
       
        CCP1CON = 0x00  'cap / comp off
        CCP2CON = 0x00
       
        ADCON0 = 0x00  'A/D off
        ADCON1 = 0x0f  'all digital
       
        CMCON = 0x07  'comp off, digital io
        CVRCON = 0x00
           
        HLVDCON = 0x00  'Low volt detect off
       
        TRISA = 0x00
        TRISB = 0x00
        TRISC = 0x00
        TRISD = 0x00
        TRISE = 0x00
       
        LATA = 0x00
        LATB = 0x00
        LATC = 0x00
        LATD = 0x00
        LATE = 0x00
       
        'setup timer3 for interval timing
        T0CON = 0x07  'timer0 off, 1:256 prescale: approx 8.4s int
     
        flags = 0x00
    Return                                          
     
     
    Proc sd_t_out(dat As Single)
    'dat is composed of degC in xxx.xx format
        Dim lng_num_str As String
        Dim new_cnt As Single
        Dim num_part As String
        Dim digit As String
       
        lng_num_str = #dat
        new_cnt = dat
           
            If new_cnt >= 0 And new_cnt < 10 Then
                digit = LeftStr(lng_num_str, 1)
                SDCardFAT32FileWrite digit, "."
                num_part = LeftStr(lng_num_str, 3)
                digit = RightStr(num_part, 1)
            Endif
           
            If new_cnt >= 10 And new_cnt < 100 Then
                digit = LeftStr(lng_num_str, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 2)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit, "."
                num_part = LeftStr(lng_num_str, 4)
                digit = RightStr(num_part, 1)
            Endif
           
            If new_cnt >= 100 Then
                digit = LeftStr(lng_num_str, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 2)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit
                num_part = LeftStr(lng_num_str, 3)
                digit = RightStr(num_part, 1)
                SDCardFAT32FileWrite digit, "."
                num_part = LeftStr(lng_num_str, 5)
                digit = RightStr(num_part, 1)
            Endif
            SDCardFAT32FileWrite digit, ", "
    End Proc                                        
     
     
    On High Interrupt
        If INTCON.2 = 1 Then  'tmr0 int
            INTCON.2 = 0
            flags.0 = 1
        Endif
    Resume                                          
     
     
  17. languer

    languer Active Member

    Joined:
    Oct 26, 2010
    Messages:
    193
    Likes:
    25
    Location:
    Arizona
    That seems to be the best way to achieve what you are trying to do. You could do something similar with a single Arduino, with a single PIC using a different compiler, or with a single PIC doing your own SPI/MMC library; but most of Oshonsoft's routines use bit-banged access which limits multiplexing the SPI port.
     
  18. ericgibbs

    ericgibbs Well-Known Member Most Helpful Member

    Joined:
    Jan 4, 2007
    Messages:
    21,174
    Likes:
    644
    Location:
    Ex Yorks' Hants UK
    ONLINE
    Hi Mity,
    The Waitms times can be reduced without causing a problem, I have also used a Bit detect loop with a time out counter.
    This gives an optimum response and also covers the occasions when the program fails to get the Status Bit it's testing.

    The Create/Write, Append and Delete function all work OK in subr 's.

    I have noticed that when I Create/Write a file and keep Appending data there are no problems, however, if use the Read command, the data is all read back OK, but I can no longer Append data, it reports 'file not found' . After a Read, the file length buffer shows zero length.!!

    Have you noticed this problem.?

    Eric
     

Share This Page