本项目使用STM32的SPI只接收来读取MAX6675的数据,这样可以节省一个IO。
MAX6675 进行热电偶冷端补偿和数字化 K 型热电偶信号。输出 12 位分辨率、 SPI 兼容、只读的数据。转换器的精度为 0.25℃,最高可读+1024℃,如果使用数据的 8LSB 则温度范围为 0℃到+700℃。带有热电偶开路检测功能,如需启用热电偶断路检测功能,负极端 T - 必须接地,接地点应尽可能靠近接地引脚(GND)。
原理图如下

时序图如下

将 CS 拉低后,SO 引脚会输出第一位数据。一次完整的串行接口读取操作需要 16 个时钟周期,需在时钟信号下降沿读取 16 位输出数据。第 15 位(D15)为无效符号位,恒为 0;D14 至 D3 位存储转换后的温度数值,数据格式为高位在前、低位在后;D2 位常态为低电平,若热电偶输入端断路则变为高电平;D1引脚为低电平,用于给MAX6675提供设备标识,D0引脚为三态输出。

串行时钟最大4.3M,在配置SPI时钟时需要注意。
STM32CubeMX部分配置

下面是驱动代码
Core\Inc\max6675.h
/**
******************************************************************************
* @file : max6675.h
* @brief : Header for max6675.c file.
******************************************************************************
*/
/* Define to prevent recursive inclusion */
#ifndef __MAX6675_H
#define __MAX6675_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes */
#include "stm32f1xx_hal.h"
/* Exported functions prototypes */
void MAX6675_Init(void);
float MAX6675_ReadTemperature(void);
uint16_t MAX6675_ReadRawData(void);
#ifdef __cplusplus
}
#endif
#endif /* __MAX6675_H */
Core\Src\max6675.c
/**
******************************************************************************
* @file : max6675.c
* @brief : MAX6675 Cold-Junction-Compensated Thermocouple-to-Digital Converter driver
******************************************************************************
*/
#include "max6675.h"
#include "main.h"
#include "spi.h"
/**
* @brief Microsecond delay function (24MHz system clock)
* @param us: Delay time in microseconds
* @retval None
*/
static void MAX6675_DelayUs(uint32_t us)
{
/* 24MHz system clock: 1 cycle = 41.67ns */
/* Each loop iteration takes approximately 3 cycles */
/* 1us = 24 cycles ≈ 8 loop iterations */
us *= 8;
while (us--) {
__NOP();
}
}
/**
* @brief Initialize MAX6675
* @param None
* @retval None
*/
void MAX6675_Init(void)
{
/* Set SSB pin high (deselect) */
HAL_GPIO_WritePin(SSB_GPIO_Port, SSB_Pin, GPIO_PIN_SET);
}
/**
* @brief Read raw data from MAX6675
* @param None
* @retval Raw 16-bit data from MAX6675
*/
uint16_t MAX6675_ReadRawData(void)
{
uint8_t rx_buf[2] = {0};
/* Ensure SPI is ready */
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
/* Pull SSB low to start communication */
HAL_GPIO_WritePin(SSB_GPIO_Port, SSB_Pin, GPIO_PIN_RESET);
MAX6675_DelayUs(1);
// 手动读取并丢弃DR寄存器残留数据(清空脏数据)
__HAL_SPI_CLEAR_OVRFLAG(&hspi1);
/* Receive 2 bytes from MAX6675 using blocking mode */
HAL_SPI_Receive(&hspi1, rx_buf, 2, 100);
/* Pull SSB high to end communication */
HAL_GPIO_WritePin(SSB_GPIO_Port, SSB_Pin, GPIO_PIN_SET);
MAX6675_DelayUs(1);
/* Combine bytes: MSB first, LSB second */
uint16_t raw_data = ((uint16_t)rx_buf[0] << 8) | rx_buf[1];
return raw_data;
}
/**
* @brief Read temperature from MAX6675
* @param None
* @retval Temperature value in Celsius
*/
float MAX6675_ReadTemperature(void)
{
uint16_t raw_data = MAX6675_ReadRawData();
/* Check if thermocouple is open (no connection) */
if (raw_data & 0x04) {
/* Thermocouple error - return error indicator */
return -1.0f;
}
/* Extract temperature (bits D14-D3) and convert to Celsius
* Resolution: 0.25°C per bit
*/
float temperature = (float)((raw_data >> 3) & 0x0FFF) * 0.25f;
return temperature;
}