TLE5012B磁传感器STM32F103 SPI驱动程序

硬件连接(三线SPI)

TLE5012B引脚 STM32F103引脚 说明
1: NC - 空脚
2: SCK PA5 SPI时钟,建议串联120Ω电阻
3: CSQ PB0 片选,低电平有效,建议串联120Ω电阻
4: DATA PA6(SCK) & PA7(MOSI) 双向数据线,MOSI和MISO并线使用
5: NC - 空脚
6: VDD 3.3V 电源
7: GND GND
8: NC - 空脚

注意:DATA引脚需要2.2K上拉电阻到3.3V,如果不加电阻,需要配置内部上拉。

工程文件结构

TLE5012B_Driver/
├── Core/
│   ├── main.c
│   └── ...
├── Drivers/
│   ├── TLE5012B/
│   │   ├── tle5012b.h
│   │   ├── tle5012b.c
│   │   └── tle5012b_conf.h
│   └── ...
└── ...

驱动程序代码

1. 头文件(tle5012b.h)

#ifndef __TLE5012B_H
#define __TLE5012B_H

#include "stm32f10x.h"
#include <stdint.h>
#include <math.h>

// 硬件引脚定义
#define TLE5012_CS_PORT        GPIOB
#define TLE5012_CS_PIN         GPIO_Pin_0

#define TLE5012_SCK_PORT       GPIOA
#define TLE5012_SCK_PIN        GPIO_Pin_5

#define TLE5012_MOSI_PORT      GPIOA
#define TLE5012_MOSI_PIN       GPIO_Pin_7

#define TLE5012_MISO_PORT      GPIOA
#define TLE5012_MISO_PIN       GPIO_Pin_6

// 片选控制宏
#define TLE5012_CS_LOW()       GPIO_ResetBits(TLE5012_CS_PORT, TLE5012_CS_PIN)
#define TLE5012_CS_HIGH()      GPIO_SetBits(TLE5012_CS_PORT, TLE5012_CS_PIN)

// TLE5012B寄存器命令定义
#define READ_STATUS            0x8001  // 读取状态寄存器
#define READ_ANGLE_VALUE       0x8021  // 读取角度值
#define READ_ANGLE_SPEED       0x8031  // 读取角速度
#define READ_ANGLE_REVOLUTION  0x8041  // 读取圈数
#define READ_TEMPERATURE       0x8061  // 读取温度

#define WRITE_MOD1_VALUE       0x5060  // 写MOD1寄存器
#define MOD1_VALUE             0x0001  // MOD1默认值

#define WRITE_MOD2_VALUE       0x5080  // 写MOD2寄存器
#define MOD2_VALUE             0x0801  // MOD2默认值

#define WRITE_MOD3_VALUE       0x5091  // 写MOD3寄存器
#define MOD3_VALUE             0x0000  // MOD3默认值

#define WRITE_MOD4_VALUE       0x50E0  // 写MOD4寄存器
#define MOD4_VALUE             0x0098  // MOD4默认值(9位,512)

#define WRITE_IFAB_VALUE       0x50B1  // 写IFAB寄存器
#define IFAB_VALUE             0x000D  // IFAB默认值

// 错误码定义
#define TLE5012_OK             0
#define TLE5012_ERROR          1
#define TLE5012_TIMEOUT        2
#define TLE5012_CRC_ERROR      3

// 角度范围定义
#define ANGLE_MAX              360.0f
#define ANGLE_RESOLUTION       0.0055f  // 360°/65536

// 数据结构体
typedef struct {
    float angle;            // 角度值(0-360°)
    int16_t raw_angle;      // 原始角度值
    int16_t speed;          // 角速度
    int16_t revolution;     // 圈数
    int16_t temperature;    // 温度
    uint16_t status;        // 状态寄存器
    uint8_t initialized;    // 初始化标志
} TLE5012B_Data_t;

// 函数声明
void TLE5012B_Init(void);
uint8_t TLE5012B_ReadAngle(float *angle);
uint8_t TLE5012B_ReadSpeed(int16_t *speed);
uint8_t TLE5012B_ReadTemperature(int16_t *temp);
uint8_t TLE5012B_ReadStatus(uint16_t *status);
uint8_t TLE5012B_ReadAll(TLE5012B_Data_t *data);
uint8_t TLE5012B_Calibrate(void);
uint8_t TLE5012B_Reset(void);

// 底层SPI函数
static uint16_t TLE5012B_SPI_ReadWrite(uint16_t data);
static uint8_t TLE5012B_ReadRegister(uint16_t reg_addr, uint16_t *data);
static uint8_t TLE5012B_WriteRegister(uint16_t reg_addr, uint16_t data);
static uint16_t TLE5012B_CalculateCRC(uint16_t data);

#endif /* __TLE5012B_H */

2. 配置文件(tle5012b_conf.h)

#ifndef __TLE5012B_CONF_H
#define __TLE5012B_CONF_H

// SPI配置
#define TLE5012_SPI               SPI1
#define TLE5012_SPI_CLK           RCC_APB2Periph_SPI1
#define TLE5012_SPI_GPIO_CLK      RCC_APB2Periph_GPIOA
#define TLE5012_CS_GPIO_CLK       RCC_APB2Periph_GPIOB

// SPI时钟分频
#define TLE5012_SPI_PRESCALER     SPI_BaudRatePrescaler_8  // 9MHz (72MHz/8)

// 超时设置
#define TLE5012_TIMEOUT           1000  // 1ms超时

// 调试模式
#define TLE5012_DEBUG             0     // 0:关闭调试,1:开启调试

// 角度计算方式
#define USE_FLOAT_CALCULATION     1     // 1:使用浮点计算,0:使用定点计算

// 自动校准
#define TLE5012_AUTO_CALIBRATE    1     // 1:开启自动校准,0:关闭

#endif /* __TLE5012B_CONF_H */

3. 主驱动程序(tle5012b.c)

#include "tle5012b.h"
#include "tle5012b_conf.h"
#include <stdio.h>

// 全局变量
static TLE5012B_Data_t tle5012_data;

/************************************************************
 * TLE5012B初始化函数
 * 功能:初始化SPI接口和TLE5012B传感器
 * 注意:TLE5012B使用三线SPI,MOSI和MISO并线
 ************************************************************/
void TLE5012B_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    
    // 1. 使能时钟
    RCC_APB2PeriphClockCmd(TLE5012_SPI_CLK | TLE5012_SPI_GPIO_CLK | TLE5012_CS_GPIO_CLK, ENABLE);
    
    // 2. 配置片选引脚PB0
    GPIO_InitStructure.GPIO_Pin = TLE5012_CS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(TLE5012_CS_PORT, &GPIO_InitStructure);
    TLE5012_CS_HIGH();  // 默认片选高电平
    
    // 3. 配置SPI引脚(三线模式)
    // PA5: SCK - 复用推挽输出
    GPIO_InitStructure.GPIO_Pin = TLE5012_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(TLE5012_SCK_PORT, &GPIO_InitStructure);
    
    // PA7: MOSI - 复用推挽输出(发送时)
    GPIO_InitStructure.GPIO_Pin = TLE5012_MOSI_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(TLE5012_MOSI_PORT, &GPIO_InitStructure);
    
    // PA6: MISO - 浮空输入(接收时)
    GPIO_InitStructure.GPIO_Pin = TLE5012_MISO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(TLE5012_MISO_PORT, &GPIO_InitStructure);
    
    // 4. 配置SPI1
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;  // 16位数据
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;          // 时钟极性:低电平空闲
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        // 时钟相位:第二个边沿采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;           // 软件NSS
    SPI_InitStructure.SPI_BaudRatePrescaler = TLE5012_SPI_PRESCALER;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  // MSB先发送
    SPI_InitStructure.SPI_CRCPolynomial = 7;            // CRC多项式
    
    SPI_Init(TLE5012_SPI, &SPI_InitStructure);
    SPI_Cmd(TLE5012_SPI, ENABLE);
    
    // 5. 初始化数据结构
    tle5012_data.angle = 0.0f;
    tle5012_data.raw_angle = 0;
    tle5012_data.speed = 0;
    tle5012_data.revolution = 0;
    tle5012_data.temperature = 0;
    tle5012_data.status = 0;
    tle5012_data.initialized = 0;
    
    // 6. 延时等待传感器稳定
    Delay_ms(10);
    
    // 7. 读取状态寄存器验证通信
    uint16_t status = 0;
    if(TLE5012B_ReadStatus(&status) == TLE5012_OK) {
        tle5012_data.initialized = 1;
        printf("TLE5012B初始化成功!状态寄存器:0x%04X\r\n", status);
        
        // 配置传感器寄存器
        TLE5012B_Configure();
    } else {
        printf("TLE5012B初始化失败!\r\n");
    }
}

/************************************************************
 * 配置TLE5012B寄存器
 * 功能:设置传感器工作模式、分辨率等参数
 ************************************************************/
static void TLE5012B_Configure(void) {
    // 写MOD1寄存器
    TLE5012B_WriteRegister(WRITE_MOD1_VALUE, MOD1_VALUE);
    Delay_us(10);
    
    // 写MOD2寄存器
    TLE5012B_WriteRegister(WRITE_MOD2_VALUE, MOD2_VALUE);
    Delay_us(10);
    
    // 写MOD3寄存器
    TLE5012B_WriteRegister(WRITE_MOD3_VALUE, MOD3_VALUE);
    Delay_us(10);
    
    // 写MOD4寄存器
    TLE5012B_WriteRegister(WRITE_MOD4_VALUE, MOD4_VALUE);
    Delay_us(10);
    
    // 写IFAB寄存器
    TLE5012B_WriteRegister(WRITE_IFAB_VALUE, IFAB_VALUE);
    Delay_us(10);
    
    printf("TLE5012B寄存器配置完成!\r\n");
}

/************************************************************
 * 读取角度值
 * 参数:angle - 角度值指针(0-360°)
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_ReadAngle(float *angle) {
    uint16_t raw_data = 0;
    uint8_t ret = TLE5012_ERROR;
    
    if(!tle5012_data.initialized) {
        return TLE5012_ERROR;
    }
    
    // 读取角度寄存器
    ret = TLE5012B_ReadRegister(READ_ANGLE_VALUE, &raw_data);
    
    if(ret == TLE5012_OK) {
        // 提取15位角度数据(bit0-14)
        uint16_t angle_raw = (raw_data & 0x7FFF) << 1;
        
        // 保存原始值
        tle5012_data.raw_angle = (int16_t)angle_raw;
        
        // 转换为角度(0-360°)
        #if USE_FLOAT_CALCULATION
            tle5012_data.angle = (float)angle_raw * 360.0f / 65536.0f;
        #else
            // 定点计算:angle = raw * 360 * 100 / 65536
            uint32_t temp = (uint32_t)angle_raw * 36000UL;
            tle5012_data.angle = (float)(temp / 65536) / 100.0f;
        #endif
        
        // 角度归一化到0-360°
        if(tle5012_data.angle >= 360.0f) {
            tle5012_data.angle -= 360.0f;
        } else if(tle5012_data.angle < 0) {
            tle5012_data.angle += 360.0f;
        }
        
        *angle = tle5012_data.angle;
        
        #if TLE5012_DEBUG
            printf("角度原始值:0x%04X,角度:%.2f°\r\n", angle_raw, tle5012_data.angle);
        #endif
    }
    
    return ret;
}

/************************************************************
 * 读取角速度
 * 参数:speed - 角速度指针
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_ReadSpeed(int16_t *speed) {
    uint16_t raw_data = 0;
    uint8_t ret = TLE5012_ERROR;
    
    if(!tle5012_data.initialized) {
        return TLE5012_ERROR;
    }
    
    // 读取角速度寄存器
    ret = TLE5012B_ReadRegister(READ_ANGLE_SPEED, &raw_data);
    
    if(ret == TLE5012_OK) {
        // 提取15位角速度数据
        int16_t speed_raw = (int16_t)((raw_data & 0x7FFF) << 1);
        
        // 转换为实际角速度(根据数据手册换算)
        // 具体换算公式需要参考TLE5012B数据手册
        tle5012_data.speed = speed_raw;
        *speed = speed_raw;
        
        #if TLE5012_DEBUG
            printf("角速度原始值:0x%04X,角速度:%d\r\n", raw_data, speed_raw);
        #endif
    }
    
    return ret;
}

/************************************************************
 * 读取温度
 * 参数:temp - 温度指针
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_ReadTemperature(int16_t *temp) {
    uint16_t raw_data = 0;
    uint8_t ret = TLE5012_ERROR;
    
    if(!tle5012_data.initialized) {
        return TLE5012_ERROR;
    }
    
    // 读取温度寄存器
    ret = TLE5012B_ReadRegister(READ_TEMPERATURE, &raw_data);
    
    if(ret == TLE5012_OK) {
        // 提取温度数据(bit0-8)
        int16_t temp_raw = (int16_t)(raw_data & 0x01FF);
        
        // 转换为实际温度(根据数据手册换算)
        // T = (raw_value * 0.8) - 75
        float temperature = (float)temp_raw * 0.8f - 75.0f;
        tle5012_data.temperature = (int16_t)(temperature * 10);  // 保存为0.1°C精度
        
        *temp = tle5012_data.temperature;
        
        #if TLE5012_DEBUG
            printf("温度原始值:0x%04X,温度:%.1f°C\r\n", raw_data, temperature);
        #endif
    }
    
    return ret;
}

/************************************************************
 * 读取状态寄存器
 * 参数:status - 状态寄存器指针
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_ReadStatus(uint16_t *status) {
    uint16_t raw_data = 0;
    uint8_t ret = TLE5012_ERROR;
    
    // 读取状态寄存器
    ret = TLE5012B_ReadRegister(READ_STATUS, &raw_data);
    
    if(ret == TLE5012_OK) {
        tle5012_data.status = raw_data;
        *status = raw_data;
        
        #if TLE5012_DEBUG
            printf("状态寄存器:0x%04X\r\n", raw_data);
            printf("  Bit15(CRC错误):%d\r\n", (raw_data >> 15) & 0x01);
            printf("  Bit14(命令错误):%d\r\n", (raw_data >> 14) & 0x01);
            printf("  Bit13(帧错误):%d\r\n", (raw_data >> 13) & 0x01);
            printf("  Bit12(磁铁丢失):%d\r\n", (raw_data >> 12) & 0x01);
            printf("  Bit11(过温):%d\r\n", (raw_data >> 11) & 0x01);
            printf("  Bit10(欠压):%d\r\n", (raw_data >> 10) & 0x01);
            printf("  Bit9(过压):%d\r\n", (raw_data >> 9) & 0x01);
            printf("  Bit8(校准完成):%d\r\n", (raw_data >> 8) & 0x01);
        #endif
    }
    
    return ret;
}

/************************************************************
 * 读取所有数据
 * 参数:data - 数据指针
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_ReadAll(TLE5012B_Data_t *data) {
    uint8_t ret = TLE5012_OK;
    
    // 读取角度
    ret |= TLE5012B_ReadAngle(&data->angle);
    
    // 读取角速度
    ret |= TLE5012B_ReadSpeed(&data->speed);
    
    // 读取温度
    ret |= TLE5012B_ReadTemperature(&data->temperature);
    
    // 读取状态
    ret |= TLE5012B_ReadStatus(&data->status);
    
    // 复制其他数据
    data->raw_angle = tle5012_data.raw_angle;
    data->revolution = tle5012_data.revolution;
    data->initialized = tle5012_data.initialized;
    
    return ret;
}

/************************************************************
 * 传感器校准
 * 功能:执行自动校准
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_Calibrate(void) {
    uint16_t status = 0;
    uint32_t timeout = 0;
    
    if(!tle5012_data.initialized) {
        return TLE5012_ERROR;
    }
    
    printf("开始TLE5012B校准...\r\n");
    
    // 发送校准命令(具体命令需要参考数据手册)
    // 这里需要根据实际校准流程编写
    
    // 等待校准完成
    while(timeout++ < 10000) {  // 10秒超时
        TLE5012B_ReadStatus(&status);
        
        if(status & 0x0100) {  // 检查校准完成位
            printf("TLE5012B校准完成!\r\n");
            return TLE5012_OK;
        }
        
        Delay_ms(1);
    }
    
    printf("TLE5012B校准超时!\r\n");
    return TLE5012_TIMEOUT;
}

/************************************************************
 * 传感器复位
 * 功能:软复位传感器
 * 返回:错误码
 ************************************************************/
uint8_t TLE5012B_Reset(void) {
    // 发送复位命令(具体命令需要参考数据手册)
    // 这里需要根据实际复位流程编写
    
    Delay_ms(10);  // 等待复位完成
    
    // 重新初始化
    TLE5012B_Init();
    
    return TLE5012_OK;
}

/************************************************************
 * 底层SPI读写函数(16位)
 * 参数:data - 要发送的数据
 * 返回:接收到的数据
 ************************************************************/
static uint16_t TLE5012B_SPI_ReadWrite(uint16_t data) {
    uint16_t retry = 0;
    uint16_t rx_data = 0;
    
    // 等待SPI空闲
    while(SPI_I2S_GetFlagStatus(TLE5012_SPI, SPI_I2S_FLAG_TXE) == RESET) {
        if(retry++ > TLE5012_TIMEOUT) {
            return 0xFFFF;  // 超时
        }
    }
    
    // 发送数据
    SPI_I2S_SendData(TLE5012_SPI, data);
    
    // 等待接收完成
    retry = 0;
    while(SPI_I2S_GetFlagStatus(TLE5012_SPI, SPI_I2S_FLAG_RXNE) == RESET) {
        if(retry++ > TLE5012_TIMEOUT) {
            return 0xFFFF;  // 超时
        }
    }
    
    // 读取数据
    rx_data = SPI_I2S_ReceiveData(TLE5012_SPI);
    
    return rx_data;
}

/************************************************************
 * 读取寄存器
 * 参数:reg_addr - 寄存器地址
 *       data - 数据指针
 * 返回:错误码
 ************************************************************/
static uint8_t TLE5012B_ReadRegister(uint16_t reg_addr, uint16_t *data) {
    uint16_t tx_data = 0;
    uint16_t rx_data = 0;
    uint16_t crc = 0;
    
    // 片选低电平
    TLE5012_CS_LOW();
    Delay_us(1);
    
    // 发送读取命令
    tx_data = reg_addr;
    rx_data = TLE5012B_SPI_ReadWrite(tx_data);
    
    // 发送空数据读取响应
    tx_data = 0x0000;
    rx_data = TLE5012B_SPI_ReadWrite(tx_data);
    
    // 片选高电平
    TLE5012_CS_HIGH();
    Delay_us(1);
    
    // 提取数据(去掉CRC位)
    *data = rx_data & 0x7FFF;
    
    // 计算CRC校验
    crc = TLE5012B_CalculateCRC(rx_data);
    
    // 检查CRC
    if((rx_data >> 15) != (crc & 0x01)) {
        #if TLE5012_DEBUG
            printf("CRC错误!接收:0x%04X,计算CRC:%d\r\n", rx_data, crc);
        #endif
        return TLE5012_CRC_ERROR;
    }
    
    return TLE5012_OK;
}

/************************************************************
 * 写入寄存器
 * 参数:reg_addr - 寄存器地址
 *       data - 要写入的数据
 * 返回:错误码
 ************************************************************/
static uint8_t TLE5012B_WriteRegister(uint16_t reg_addr, uint16_t data) {
    uint16_t tx_data = 0;
    uint16_t rx_data = 0;
    
    // 片选低电平
    TLE5012_CS_LOW();
    Delay_us(1);
    
    // 发送写入命令和数据
    tx_data = reg_addr;
    rx_data = TLE5012B_SPI_ReadWrite(tx_data);
    
    tx_data = data;
    rx_data = TLE5012B_SPI_ReadWrite(tx_data);
    
    // 片选高电平
    TLE5012_CS_HIGH();
    Delay_us(1);
    
    return TLE5012_OK;
}

/************************************************************
 * 计算CRC校验
 * 参数:data - 要计算的数据
 * 返回:CRC值(1位)
 ************************************************************/
static uint16_t TLE5012B_CalculateCRC(uint16_t data) {
    uint16_t crc = 0;
    uint8_t i;
    
    // TLE5012B使用奇偶校验作为CRC
    // 计算数据中1的个数
    for(i = 0; i < 15; i++) {
        if(data & (1 << i)) {
            crc ^= 1;
        }
    }
    
    return crc;
}

/************************************************************
 * 延时函数
 ************************************************************/
static void Delay_ms(uint32_t ms) {
    uint32_t i, j;
    for(i = 0; i < ms; i++) {
        for(j = 0; j < 7200; j++);  // 72MHz下大约1ms
    }
}

static void Delay_us(uint32_t us) {
    uint32_t i;
    for(i = 0; i < us * 8; i++);  // 72MHz下大约1us
}

4. 使用示例(main.c)

#include "stm32f10x.h"
#include "tle5012b.h"
#include <stdio.h>

// 串口初始化(用于调试输出)
void USART1_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    
    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    
    // 配置USART1引脚
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  // TX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置USART1
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    
    USART_Cmd(USART1, ENABLE);
}

// 重定向printf到串口
int fputc(int ch, FILE *f) {
    USART_SendData(USART1, (uint8_t)ch);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    return ch;
}

int main(void) {
    float angle = 0.0f;
    int16_t speed = 0;
    int16_t temperature = 0;
    uint16_t status = 0;
    TLE5012B_Data_t sensor_data;
    
    // 系统初始化
    SystemInit();
    
    // 初始化串口(调试用)
    USART1_Init();
    printf("TLE5012B测试程序启动...\r\n");
    
    // 初始化TLE5012B
    TLE5012B_Init();
    
    // 主循环
    while(1) {
        // 读取所有数据
        if(TLE5012B_ReadAll(&sensor_data) == TLE5012_OK) {
            printf("角度:%.2f°,角速度:%d,温度:%.1f°C\r\n",
                   sensor_data.angle, sensor_data.speed, sensor_data.temperature/10.0f);
            
            // 检查状态
            if(sensor_data.status & 0x1000) {
                printf("警告:磁铁丢失!\r\n");
            }
            if(sensor_data.status & 0x0800) {
                printf("警告:过温!\r\n");
            }
        } else {
            printf("读取传感器数据失败!\r\n");
        }
        
        // 延时100ms
        Delay_ms(100);
    }
}

参考代码 TLE5012B基于STM32F103的SPI通信驱动程序 www.youwenfan.com/contentcnt/183261.html

关键配置说明

1. SPI配置要点

  • 数据大小:16位(SPI_DataSize_16b)
  • 时钟极性:低电平空闲(SPI_CPOL_Low)
  • 时钟相位:第二个边沿采样(SPI_CPHA_2Edge)
  • NSS模式:软件控制(SPI_NSS_Soft)
  • 波特率:建议SPI_BaudRatePrescaler_8(9MHz)

2. 三线SPI特殊处理

由于TLE5012B使用三线SPI(MOSI和MISO并线),需要注意:

  • 发送时:PA7配置为推挽输出
  • 接收时:PA6配置为浮空输入
  • 实际应用中可能需要动态切换引脚模式

3. 数据解析

  • 角度值:15位分辨率(0-32767对应0-360°)
  • 角速度:15位有符号数
  • 温度:9位数据,转换公式:T = (raw × 0.8) - 75

4. 错误处理

  • CRC校验:检查bit15的奇偶校验位
  • 状态寄存器:监控磁铁丢失、过温、欠压等状态

优化建议

  1. 中断模式:对于高速应用,可以使用SPI中断或DMA传输
  2. 滤波处理:对角度值进行滑动平均滤波,减少噪声
  3. 校准算法:实现自动零位校准和线性度补偿
  4. 多圈计数:结合圈数寄存器实现多圈绝对位置测量
  5. 温度补偿:根据温度值对角度进行补偿

常见问题解决

  1. 读取数据全为0或0xFFFF

    • 检查硬件连接,特别是DATA线的上拉电阻
    • 确认SPI时钟极性和相位设置正确
    • 检查片选信号时序
  2. 角度值跳变

    • 确保磁铁与传感器距离合适(通常1-3mm)
    • 使用径向充磁的圆磁铁
    • 添加软件滤波
  3. 通信不稳定

    • 在SCK、CS、DATA线上串联120Ω电阻
    • 缩短连接线长度
    • 在电源引脚添加去耦电容
posted @ 2026-04-19 10:48  晃悠人生  阅读(43)  评论(0)    收藏  举报