|
|
View previous topic :: View next topic |
Author |
Message |
mquemelli
Joined: 18 Oct 2016 Posts: 9
|
How to use SPI with PIC18F4550 and ADC MAX11040K |
Posted: Tue Oct 18, 2016 10:37 am |
|
|
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: 9228 Location: Greensville,Ontario
|
|
Posted: Tue Oct 18, 2016 2:34 pm |
|
|
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
|
|
Posted: Tue Oct 18, 2016 4:14 pm |
|
|
No, I have supplied the peripheral correctly with 3 volts and the pic with 5. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 18, 2016 4:23 pm |
|
|
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: 9228 Location: Greensville,Ontario
|
|
Posted: Tue Oct 18, 2016 7:08 pm |
|
|
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
|
|
Posted: Tue Oct 18, 2016 7:32 pm |
|
|
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: 19515
|
|
Posted: Wed Oct 19, 2016 12:56 am |
|
|
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: 9228 Location: Greensville,Ontario
|
|
Posted: Wed Oct 19, 2016 5:00 am |
|
|
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: 19515
|
|
Posted: Wed Oct 19, 2016 7:14 am |
|
|
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.... |
|
|
mquemelli
Joined: 18 Oct 2016 Posts: 9
|
Changing PIC to MCP2210 |
Posted: Sun Dec 18, 2016 11:38 am |
|
|
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. |
|
|
|
|
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
|