CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

How to use SPI with PIC18F4550 and ADC MAX11040K

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
mquemelli



Joined: 18 Oct 2016
Posts: 9

View user's profile Send private message

How to use SPI with PIC18F4550 and ADC MAX11040K
PostPosted: Tue Oct 18, 2016 10:37 am     Reply with quote

I'm trying to use SPI with PIC18F4550 to communicate with ADC device MAX11040k, my compiler is PCW 4.140. Here is the data sheet:
https://datasheets.maximintegrated.com/en/ds/MAX11040K-MAX11060.pdf

I can't get the bytes from the register, all that I could make was get zeros.
My code sends a command by Matlab via USB (this part is working because I tested before) and then the PIC sends the bytes to write or read the register. Here is my code:

Code:

#include <18f4550.h>
#device adc=10
#use delay(clock = 48M)
#fuses XTPLL,USBDIV,CPUDIV1,VREGEN, MCLR, NODEBUG, PLL1 , NOWDT, NOPUT

#include <usb_cdc.h>
   
   int8 comandoUsb=0;

int main(){
   set_tris_c (1); // set porto C como entrada digital
   
   int8 byte1=1, byte2=1, byte3=1, byte4=1, byte5=1, byte6=1, byte7=1, byte8=1;
   int8 byte9=1, byte10=1, byte11=1, byte12=1;
   int8 comando1=0b01000000;  // Write Sampling Instant Control Register 32 bits
   int8 comando2=0b11000000;  // Read Sampling Instant Control Register  32 bits
   int8 comando3=0b01010000;  // Write Data-Rate Control Register 16 bits
   int8 comando4=0b11010000;  // Read Data-Rate Control Register  16 bits
   int8 comando5=0b01100000;  // Write Configuration Register 8 bits
   int8 comando6=0b11100000;  // Read Configuration Register 8 bits
   int8 comando7=0b11110000;  // Read Data Register 96 bits
   
   int i=0, result=0;         //declarando variavel de incremento e decremento
   
   output_low(pin_D0);        // setando pino D0 em baixo
   
   setup_spi(spi_master|spi_l_to_h|spi_clk_div_4 ); //configurando Biblioteca SPI
   delay_ms(10);
   
  //------------------------Starting USB---------------------------------//
  //--------------------------------------------------------------------------//
 
   output_high(pin_b7);    // set pin B7 high to check the USB comunication
   usb_init();
   while(!usb_cdc_connected() || !usb_enumerated()){
      output_high(pin_b7);
   }
   output_low(pin_b7);
   
   //---------------------Mainly CODE------------------------------------//
  //--------------------------------------------------------------------------//
   while (1){
   
      if(usb_cdc_kbhit()){                          //get the comand from Matlab
         comandoUsb = usb_cdc_getc();
      }
     
     
      //SPI cases

      switch(comandoUsb){
         case 'a':
            output_high(pin_b7); //just to check if the case is working
            delay_ms(500);
            output_low(pin_b7);
            delay_ms(500);
           
           
            spi_write(comando6);  // read config register
           
           
            byte1 = spi_read(0);
            usb_cdc_putc(byte1);
           
           
            comandoUsb=0;
            break;
           
         case 'b':
            output_high(pin_b7); //just to check if the case is working
            delay_ms(500);
            output_low(pin_b7);
            delay_ms(500);
           
            spi_write(comando4); // read data-rate control
            byte1= spi_read(0);
            byte2= spi_read(0);
            usb_cdc_putc(byte1);
            usb_cdc_putc(byte2);
           
            comandoUsb=0;
            break;
           
          case 'c':
            output_high(pin_b7);    //just to check if the case is working
            delay_ms(500);
            output_low(pin_b7);
            delay_ms(500);
           
            spi_write(comando5);  //write config register
            spi_write(0b00100100);
           
            comandoUsb=0;
            break;
           
          case 'd':
           
            output_high(pin_b7); //just to check if the case is working
            delay_ms(500);
            output_low(pin_b7);
            delay_ms(500);
           
            spi_write(comando7);  // read data register
            byte1 = spi_read(0);
            byte2 = spi_read(0);
            byte3 = spi_read(0);
            byte4 = spi_read(0);
            byte5 = spi_read(0);
            byte6 = spi_read(0);
            byte7 = spi_read(0);
            byte8 = spi_read(0);
            byte9 = spi_read(0);
            byte10= spi_read(0);
            byte11= spi_read(0);
            byte12= spi_read(0);
           
            usb_cdc_putc(byte1);
            usb_cdc_putc(byte2);
            usb_cdc_putc(byte3);
            usb_cdc_putc(byte4);
            usb_cdc_putc(byte5);
            usb_cdc_putc(byte6);
            usb_cdc_putc(byte7);
            usb_cdc_putc(byte8);
            usb_cdc_putc(byte9);
            usb_cdc_putc(byte10);
            usb_cdc_putc(byte11);
            usb_cdc_putc(byte12);
     
            comandoUsb=0;
            break;
           
          default:
            comandoUsb=0;
            break;
           
      }  //switch case
   
     
   }  //while
 
 
}//main



I appreciate any help. I would like to know if there is something wrong with my code.
temtronic



Joined: 01 Jul 2010
Posts: 9162
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Oct 18, 2016 2:34 pm     Reply with quote

first possible problem is that peripheral is a '3 volt' device so are you using 5 volt PIC ?

Jay
mquemelli



Joined: 18 Oct 2016
Posts: 9

View user's profile Send private message

PostPosted: Tue Oct 18, 2016 4:14 pm     Reply with quote

No, I have supplied the peripheral correctly with 3 volts and the pic with 5.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 18, 2016 4:23 pm     Reply with quote

1. Besides the 3v/5v problem,
2. You're not using the \CS signal which is required for the Maxim device.
3. You're using SPI Mode 1. The Maxim data sheet says to use Mode 2.
(CPOL = 1, CPHA = 0). The Maxim data sheet is very specific about this. It says:
Quote:
SCLK must idle high


Code:
// SPI mode definitions (for 16F and 18F PICs).
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)


You need to correct all these things, and you need to learn how to write
SPI driver code by using functions. Your program will be much more
easy to read, understand and debug.
temtronic



Joined: 01 Jul 2010
Posts: 9162
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Oct 18, 2016 7:08 pm     Reply with quote

Had a look at the datasheet. I know 400 pages of boring technical things like charts,graphs, spec, etc. , but if you want to use PICs you HAVE to understand a LOT of those 400+ pages. After 2 decades ,I'm still learning.....

1) SPI data in IS an ST logic pin, so it needs minimum of 80% VDD ( 80% of 5 volt(vdd) is 4 volts

2) AD device might output 3.5 at best(fed from 3.6)

conclusion ...PIC will never,ever see a logic one .

Options to make it work
a) use the 'L' version of that PIC

b) use 'logic level translation' between the two devices

c) use a 3 volt rated PIC,like the 'Swiss Army Knife' 18F46K22.

No amount of 'clever' software code will get nonfunctional hardware running.

Jay
mquemelli



Joined: 18 Oct 2016
Posts: 9

View user's profile Send private message

PostPosted: Tue Oct 18, 2016 7:32 pm     Reply with quote

Jay and PCM Programmer, thanks a lot for help me, I will fix all this problems. Now I can see more clearly what is happening. If it work or not I will post here the result.
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Wed Oct 19, 2016 12:56 am     Reply with quote

If you must use the 3.3v device and the 5v PIC, then there are two solutions.

The first is to use hardware SPI, and is the same as for talking to an SD card. You need voltage dividers on the clock output, and data output line on the PIC (just resistors), and a buffer which accepts 'TTL' level signals, and outputs 4v or more to drive the PIC. The classic chip for this is the 74ACT125D. This gives well over 4v out, when driven using 5v, but has a Vih of just 2v (make sure you are getting the 'T' version). Nice non-inverting buffer.

The second solution, is to use software SPI. Some pins on your PIC have TTL buffers instead of Schmitt buffers. So (for instance), any of the PortA pins, have such buffers. However even easier (no hardware changes needed), use #USE SPI, on the same pins you are currently selecting, but use the 'FORCE_SW' option. The input buffer for pin B0, when used as a normal port input (or for software SPI), is a TTL input buffer.

Obvious downside is that the second is slower.
temtronic



Joined: 01 Jul 2010
Posts: 9162
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Oct 19, 2016 5:00 am     Reply with quote

Of all the options, I prefer a single chip, 3 volt solution. No additional components, no chance to miswire a 3rd chip, easier PCB layout, etc.

I understand it can be difficult to get some parts in other countries and that professors like to teach using 'their' PICs and parts.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Wed Oct 19, 2016 7:14 am     Reply with quote

Very much agreed.

However the other methods can be worthwhile/necessary, if other parts of the board 'must' be 5v. There are different scenarios For instance:

USB powered circuit. So running off 5v. Using a 3.3v USB PIC, means adding a regulator. He obviously has a regulator to drive the 3.3v device, but might only have limited power.
Other 5v circuitry involved. Choices are 'up' converting for these from a 3.3v PIC, or 'down' converting for the single chip.
It is generally fractionally easier to 'down' convert, since on SPI, then only needs one line buffered.

Like most things this is where 'thought' comes in. Sometimes it is easier to select perhaps a fractionally more expensive device, than getting involved in level switching....

We have also yet to mention just how hard it is to design an analog circuit well enough to warrant even 16bit, let alone the 24bit operation. A 'basic' error like not realising that a 3.3v output can't drive a SPI input on a PIC, doesn't give great confidence at the level of design knowledge involved.... Crying or Very sad
mquemelli



Joined: 18 Oct 2016
Posts: 9

View user's profile Send private message

Changing PIC to MCP2210
PostPosted: Sun Dec 18, 2016 11:38 am     Reply with quote

Hi guys, as you had told me about the hardware incompatibility betwenn PIC18F4550 and MAX11040. I had to change PIC to another device from Microchip too, I choosed to use MCP2210 that is a protocol converter USB-to-SPI, the MCP is level voltage compatible with the ADC converter, and also Microchip made available a .dll library in C++, wich makes easier to use this device.
Everybody who wants look about it can access this link:
http://www.microchip.com/wwwproducts/en/MCP2210

Here is the connections that I made, now I am able to use SPI protocol: https://www.dropbox.com/s/ft039ptb7ack78u/esquematico%20mcp%20max.png?dl=0

Thanks a lot for help me.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group