enter image description hereI'm trying to read data from MAX6675 with PIC16f1937. The bottom is my code
#define _XTAL_FREQ 4000000
#include <xc.h>
#include "MAX6675_header.h"
#include <stdbool.h>
#include <string.h>
volatile bool spi_rx_data_ready = false;
void __interrupt() interrupt_isr(){
INTCONbits.GIE = 0; //Disable interrupt
if(PIR2bits.BCLIF == 1){ //Checking to see if MSSP Bus Collision interrupt is triggered
PIR2bits.BCLIF = 0; //Reseting flag
}
else if(PIR1bits.SSPIF){ //Checking to see if MSSP Interrupt is triggered
spi_rx_data_ready = true; //A flag to indicate the data is received
PIR1bits.SSPIF = 0; //Reseting flag
}
INTCONbits.GIE = 1; //Enable interrupt
}
void PORT_configuration(){
TRISB = 0x00;
LATB = 0;
TRISCbits.TRISC3 = 0; //SCK as output
TRISCbits.TRISC4 = 1; //SDI as input
TRISCbits.TRISC5 = 0; //SDO as output
TRISCbits.TRISC6 = 0; //SS as output
LATCbits.LATC6 = 1; //SS is set to high to deselect slave
}
void SPI_Configuration(){
SSPCON1bits.SSPEN = 0; //Disabling serial port
ANSELA = 0x00; //Setting different PORTS as digital I/O
ANSELB = 0x00;
ANSELD = 0x00;
ANSELE = 0x00;
SSPSTATbits.SMP = 1; //Input data sampled at end of data output time
SSPSTATbits.CKE = 1; //Transmit occurs on transition from Idle to active clock state
SSPCON1bits.CKP = 0; //Idle state for clock is a high level
SSPCON1bits.SSPM = 0x00; //SPI Master mode, clock = FOSC/4
SSPCON1bits.SSPEN = 1; //Enabling serial port
PIE1bits.SSPIE = 1; //MSSP Interrupt Enable bit
PIE2bits.BCLIE = 1; //MSSP Bus Collision Interrupt Enable bit
}
void SPI_read(){
unsigned char Temp1=0,Temp2=0;
LATCbits.LATC6 = 0;
__delay_us(0.1); //Wait for 100 nano seconds
SSPBUF = 0x00; //Send dummy data to start communication
while(spi_rx_data_ready == false); //Wait for the data to be completely received
spi_rx_data_ready = false; //Reset the flag
Temp1 = SSPBUF;
LATCbits.LATC6 = 1;
__delay_ms(1000); //For better observation in PROTEUS (Remove for real_time application)
}
void main(void) {
//Select 8MHz internal oscillator
OSCCONbits.SCS = 0x03; //Internal oscillator block
OSCCONbits.IRCF = 0x0d; //FOSC = 4MHz
INTCONbits.GIE = 1; //To enable global interrupts
INTCONbits.PEIE = 1; //To enable peripheral interrupts
//Calling for configuration functions
PORT_configuration();
SPI_Configuration();
while(1){
SPI_read();
}
}
But the problem is that the output data of the MAX6675 is 16 bits and the microcontroller's SPI buffer is 8 bit (MAX6675 uses SPI protocol). How can I receive the second 8 bits?
EDITED SPI_READ()
void SPI_read(){
unsigned char Temp1=0,Temp2=0;
LATCbits.LATC6 = 0;
__delay_us(0.1); //Wait for 100 nano seconds
SSPBUF = 0x00; //Send dummy data to start communication
while(spi_rx_data_ready == false); //Wait for the data to be completely received
spi_rx_data_ready = false; //Reset the flag
LATD = SSPBUF;
SSPBUF = 0x00; //Send dummy data to start communication
while(spi_rx_data_ready == false); //Wait for the data to be completely received
spi_rx_data_ready = false; //Reset the flag
LATB = SSPBUF;
// LATD = Temp1;
// LATB = Temp2;
LATCbits.LATC6 = 1;
__delay_ms(1000); //For better observation in PROTEUS (Remove for real_time application)
}
3 Answers 3
You just send dummy data twice, and receive twice, without toggling the /CS line.
The delay between the two 8 bit values is not an issue.
-
\$\begingroup\$ I edited the SPI_READ() and included it in my main question with a picture of my PROTEUS. I did as you said but in PROTEUS I'm getting wrong numbers I think. \$\endgroup\$Momo– Momo2021年12月27日 09:59:10 +00:00Commented Dec 27, 2021 at 9:59
-
\$\begingroup\$ That's a little more detail than I want to get into, but I don't think the delay_us macro accepts floating point numbers. \$\endgroup\$Spehro 'speff' Pefhany– Spehro 'speff' Pefhany2021年12月27日 10:04:38 +00:00Commented Dec 27, 2021 at 10:04
-
\$\begingroup\$ I deleted that delay. But I'm not getting any good result. \$\endgroup\$Momo– Momo2021年12月27日 10:08:46 +00:00Commented Dec 27, 2021 at 10:08
In theory, Spehro is right but your timing is wrong.
This is the data that you will get from MAX6675.
As you can see from the datasheet, 100ns refers only to tCH, tCL, tCSS.
200ns is 1 Period and every bit comes at the rising edge of the period. In theory, you should get 8 bit in 1600ns. After 1600ns, you should be ready to get the second part of the data.
Try 1600ns delay, I might miscalculate but just give it a try.
-
\$\begingroup\$ Thanks for the help. I could solve the problem and I posted it. \$\endgroup\$Momo– Momo2021年12月27日 12:56:05 +00:00Commented Dec 27, 2021 at 12:56
Alright, the problem is solved. The right code is as follows:
#define _XTAL_FREQ 4000000
#include <xc.h>
#include "MAX6675_header.h"
#include <stdbool.h>
#include <string.h>
#define RS LATBbits.LATB2
#define EN LATBbits.LATB3
#define D4 LATBbits.LATB4
#define D5 LATBbits.LATB5
#define D6 LATBbits.LATB6
#define D7 LATBbits.LATB7
#include "lcd.h"
#include "stdio.h"
#include "stdlib.h"
volatile bool spi_rx_data_ready = false;
void __interrupt() interrupt_isr(){
INTCONbits.GIE = 0; //Disable interrupt
if(PIR2bits.BCLIF == 1){ //Checking to see if MSSP Bus Collision interrupt is triggered
PIR2bits.BCLIF = 0; //Reseting flag
}
else if(PIR1bits.SSPIF){ //Checking to see if MSSP Interrupt is triggered
spi_rx_data_ready = true; //A flag to indicate the data is received
PIR1bits.SSPIF = 0; //Reseting flag
}
INTCONbits.GIE = 1; //Enable interrupt
}
void PORT_configuration(){
TRISB = 0x00;
LATB = 0;
TRISD = 0x00;
LATD = 0;
TRISCbits.TRISC3 = 0; //SCK as output
TRISCbits.TRISC4 = 1; //SDI as input
TRISCbits.TRISC5 = 0; //SDO as output
TRISCbits.TRISC6 = 0; //SS as output
LATCbits.LATC6 = 1; //SS is set to high to deselect slave
}
void SPI_Configuration(){
SSPCON1bits.SSPEN = 0; //Disabling serial port
ANSELA = 0x00; //Setting different PORTS as digital I/O
ANSELB = 0x00;
ANSELD = 0x00;
ANSELE = 0x00;
SSPSTATbits.SMP = 1; //Input data sampled at end of data output time
SSPSTATbits.CKE = 1; //Transmit occurs on transition from Idle to active clock state
SSPCON1bits.CKP = 0; //Idle state for clock is a high level
SSPCON1bits.SSPM = 0x00; //SPI Master mode, clock = FOSC/4
SSPCON1bits.SSPEN = 1; //Enabling serial port
PIE1bits.SSPIE = 1; //MSSP Interrupt Enable bit
PIE2bits.BCLIE = 1; //MSSP Bus Collision Interrupt Enable bit
}
void SPI_read(){
int raw_value=0;
char d[16];
float temp=0.0;
unsigned char Temp1=0,Temp2=0;
LATCbits.LATC6 = 0;
SSPBUF = 0x00; //Send dummy data to start communication
while(spi_rx_data_ready == false); //Wait for the data to be completely received
spi_rx_data_ready = false; //Reset the flag
Temp1 = SSPBUF;
SSPBUF = 0x00; //Send dummy data to start communication
while(spi_rx_data_ready == false); //Wait for the data to be completely received
spi_rx_data_ready = false; //Reset the flag
Temp2 = SSPBUF;
raw_value = (Temp1 << 5) | (Temp2 >> 3) ;
temp = (float)raw_value / 4;
LATCbits.LATC6 = 1;
sprintf(d,"%f",temp);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String(d);
}
void main(void) {
//Select 8MHz internal oscillator
OSCCONbits.SCS = 0x03; //Internal oscillator block
OSCCONbits.IRCF = 0x0d; //FOSC = 4MHz
INTCONbits.GIE = 1; //To enable global interrupts
INTCONbits.PEIE = 1; //To enable peripheral interrupts
//Calling for configuration functions
PORT_configuration();
SPI_Configuration();
Lcd_Init();
while(1){
SPI_read();
}
}
So basically, I read it twice as @SpehroPefhany said. And remove the extra bits and put it into another variable and then divide it by 4 which is supposed to give you the temperature in centigrade.
-
\$\begingroup\$ Any body knows why we have to divide the result by 4? \$\endgroup\$Momo– Momo2021年12月27日 12:58:05 +00:00Commented Dec 27, 2021 at 12:58
-
1\$\begingroup\$ You should the datasheet of the part MA6675 very carefully. On top of first page: General Description The MAX6675 performs cold-junction compensation and digitizes the signal from a type-K thermocouple. The data is output in a 12-bit resolution, SPI-compatible, read-only format. This converter resolves temperatures to 0.25°C, allows readings as high as +1024°C, and exhibits thermocouple accuracy of 8 LSBs for temperatures ranging from 0°C to +700°C. Result is given as a multiple of 0.25 °C, after a divison by 4 you get a multiple of 1 °C with a fractional part of two bits. \$\endgroup\$Uwe– Uwe2021年12月27日 16:17:58 +00:00Commented Dec 27, 2021 at 16:17