找回密码
 立即注册
查看: 52|回复: 2

求助!!!弄了一天了,tle5012就是通信不上,现在只用了读取角度

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:31
  • 最近打卡:2025-10-30 13:40:00
已绑定手机

7

主题

10

回帖

209

积分

中级会员

积分
209
发表于 6 天前 | 显示全部楼层 |阅读模式

#include "encoder.h"
#include "sys_tick.h"
#include <string.h>

// 引脚定义(TLE5012与AI8051U连接)
#define CS          P14    // TLE5012 CS引脚(P1.4)
#define SPI_MOSI    P15
#define SPI_MISO    P16   
#define SPI_SCK     P17   

// -------------------------- TLE5012命令修正(符合协议) --------------------------
// 1. 基础读命令(Lock=0000B,地址0x00~0x04,2字节命令)
uint8 xdata TLE5012_CMD_UNLOCK[]     = {0x60,0x00};        // 写解锁命令(必须先发,否则写入无效)
uint8 xdata TLE5012_CMD_READ_STATUS[]    = {0x80, 0x01}; // 读状态(0x00,返回2字节)
uint8 xdata TLE5012_CMD_READ_ANGLE[]     = {0x80, 0x41}; // 读角度(0x01,返回2字节)
uint8 xdata TLE5012_CMD_READ_TEMP[]      = {0x80, 0x02}; // 读温度(0x02,返回2字节)
uint8 xdata TLE5012_CMD_READ_SPEED[]     = {0x80, 0x03}; // 读速度(0x03,返回2字节)


uint8 test[]={0xd0,0x82};




// -------------------------- 数据缓冲区定义(修正大小) --------------------------
uint8 xdata encoder_tx_buf[5] = {0}; // SPI发送缓冲区(存命令)
uint8 xdata encoder_rx_buf[5] = {0}; // SPI接收缓冲区(存回复+数据)

uint8 xdata encoder_angle_buf[2] = {0}; // DMA接收缓冲区(存回复+数据)

uint8 Read_register_num = 0; // 读取寄存器数量


// 解析后的数据(添加有效性标志)
float encoder_angle = 0;    // 角度(0~4095→0~360°,12位有效)
int16 xdata encoder_speed = 0;     // 速度(RPM,16位有符号)
int16 xdata encoder_temp = 0;      // 温度(℃,需换算)
uint16 xdata encoder_status = 0;   // 状态(判断校准是否完成)
bit B_ENCODER_DATA_VALID = 0;      // 数据有效标志

// 控制标志
bit B_ENCODER_DMA_BUSY = 0;        // DMA忙标志
bit B_ENCODER_CAL_DONE = 0;        // 校准完成标志
bit B_ENCODER_TIMEOUT = 0;         // 超时标志
bit B_ENCODER_NEXT_DMA_MODE = 0;      // 下一次DMA模式标志位 0:DMA接收 1:DMA完成
// 超时时间记录
uint32 xdata encoder_timeout_start = 0;
// 超时相关定义
uint8 xdata ENCODER_TIMEOUT_MS = 10;  // 超时时间(毫秒)



// -------------------------- SPI初始化 --------------------------
void Encoder_SPI_Init(void)
{

    SPCTL = 0x01;

    SSIG = 1;   //1: 忽略SS脚,由MSTR位决定主机还是从机       0: SS脚用于决定主机还是从机。
    SPEN = 1;   //1: 允许SPI,                             0:禁止SPI,所有SPI管脚均为普通IO
    DORD = 0;   //1:LSB先发,                              0:MSB先发
    MSTR = 1;   //1:设为主机                                0:设为从机
    CPOL = 0;   //1: 空闲时SCLK为高电平,                   0:空闲时SCLK为低电平
    CPHA = 1;   //1: 数据在SCLK前沿驱动,后沿采样.          0: 数据在SCLK前沿采样,后沿驱动.
    P_SW1 = (P_SW1 & ~0x0c) | ((0<<2) & 0x0c);      //切换IO
   
    //sck  P17 推挽输出 高速模式
    P1M0 |= 0x80;  
    P1M1 &= 0x7F;
    P1SR &= ~0x80;

    //cs  P14 推挽输出
    P1M0 |= 0x10;  
    P1M1 &= 0xEF;
    P1SR &= ~0x10;

    //mosi  P15 开漏输出,方便单线读写,写1可释放总线
    P1M0 |= 0x20;
    P1M1 |= 0x20;

    //sck cs大电流驱动
    P1DR &= ~0x90;

    //打开MISO、MOSI的上拉电阻
    P1PU |= 0x60;



   
   
}
//初始化为DMA发送模式
void DMA_Encoder_SPI_Init(void)
{
   
    // 1. 停止当前DMA(避免残留操作)
    DMA_SPI_CR = 0x00;
    DMA_SPI_STA = 0x00;    // 清除发送完成状态标志
   
    // 2. 配置DMA缓冲区地址
    DMA_SPI_TXAH = (uint8)((uint16)encoder_tx_buf >> 8); // 发送缓冲区高字节
    DMA_SPI_TXAL = (uint8)((uint16)encoder_tx_buf);      // 发送缓冲区低字节
    DMA_SPI_RXAH = (uint8)((uint16)encoder_rx_buf >> 8); // 接收缓冲区高字节
    DMA_SPI_RXAL = (uint8)((uint16)encoder_rx_buf);      // 接收缓冲区低字节
   
    // 3. DMA核心配置
    // 使能中断+同时使能TX+优先级2+数据优先级3
    DMA_SPI_CFG = 0x00;// 先清零
    system_delay_ms(1);
    DMA_SPI_CFG = (1<<7) | (1<<6);//使能中断+同时使能TX
    DMA_SPI_CFG |= 0x0B; // 优先级2+数据优先级3
    // 不自动控制SS脚(CS手动控制),文档34.4.9节DMA_SPI_CFG2
    DMA_SPI_CFG2 = (0<<2) | 0;
    B_ENCODER_NEXT_DMA_MODE = 0; // 置标志位为DMA发送模式

   
   
}


void ENCODER_SPI_DMA_Tx(uint8 xdata *TxBuf, uint8 tx_len)
{
    B_ENCODER_DMA_BUSY = 1; // 置忙标志
    B_ENCODER_TIMEOUT = 0;  // 清超时标志

    //关闭DMA以防冲突
    DMA_SPI_CR = 0x00;
    //拉低CS开始传输
    CS = 0;

    // 1. 更新发送缓冲区地址(若TxBuf变化)
    if (TxBuf != encoder_tx_buf)
    {
        DMA_SPI_TXAH = (uint8)((uint16)TxBuf >> 8);
        DMA_SPI_TXAL = (uint8)((uint16)TxBuf);
    }
   
    // 2. 配置传输长度(文档34.4.4节:总字节数=实际长度-1)
    DMA_SPI_AMTH = (uint8)((tx_len - 1) / 256);
    DMA_SPI_AMT  = (uint8)((tx_len - 1) % 256);
   
    // 3. 清除标志并启动DMA(文档34.4.4节DMA_SPI_CR)
    DMA_SPI_STA = 0x00;
    DMA_SPI_CR = (1<<7) | (1<<6) | 1; // DMA_ENSPI=1 + SPI_TRIG_M=1 + SPI_CLRFIFO=1
}

void ENCODER_SPI_DMA_Rx(uint8 xdata *RxBuf, uint8 rx_len)
{
    B_ENCODER_DMA_BUSY = 1; // 置忙标志
    B_ENCODER_TIMEOUT = 0;  // 清超时标志

    //关闭DMA以防冲突
    DMA_SPI_CR = 0x00;

    // 1. 更新接收缓冲区地址(若RxBuf变化)
    if (RxBuf != encoder_rx_buf)
    {
        DMA_SPI_RXAH = (uint8)((uint16)RxBuf >> 8);
        DMA_SPI_RXAL = ((uint16)RxBuf & 0x00FF);
    }

    // 2. 配置接收长度(文档34.4.4节:总字节数=实际长度-1)
    DMA_SPI_AMTH = (uint8)((rx_len - 1) / 256);
    DMA_SPI_AMT  = (uint8)((rx_len - 1) % 256);

    // 3. 清除标志并启动DMA(文档34.4.4节DMA_SPI_CR)
    DMA_SPI_STA = 0x00;
    DMA_SPI_CR = (1<<7) | (1<<6) | 1; // DMA_ENSPI=1 + SPI_TRIG_M=1 + SPI_CLRFIFO=1
}


// -------------------------- TLE5012写寄存器 --------------------------
void TLE5012_Write(uint8 reg,uint8 dat)
{
   

   

   
}
// -------------------------- TLE5012读寄存器 --------------------------
void TLE5012_Read(uint8 reg,uint8 reg_num)
{
   

   

    // 构造读命令1_0000_0_ADDR_ND
    //读(1)_Lock(4)_UPD(1)__ADDR(6)_ND(4)
    encoder_tx_buf[0] = (uint8)TLE5012_READ_CMD<<7;
    encoder_tx_buf[1] = (reg<<4)|(reg_num<<0); // 第二字节补全命令格式


    // 启动DMA发送命令
    ENCODER_SPI_DMA_Tx(encoder_tx_buf, 2);
    Read_register_num = reg_num;

}



// -------------------------- 编码器初始化(整合SPI/DMA/校准) --------------------------
void encoder_init(void)
{
   
     
   
    Encoder_SPI_Init();
    DMA_Encoder_SPI_Init();
  


}

// -------------------------- 启动连续读取(优化CS时序) --------------------------
void encoder_start_continuous_read(void)
{
  
}

// -------------------------- 数据解析(修正越界与有效性) --------------------------
void encoder_parse_data(void)
{
   
     
   
    // 2. 解析角度(0x01寄存器,高12位有效)
    encoder_angle = (float)360/32768.0 * (((encoder_angle_buf[0]&0x7F) << 8) | encoder_angle_buf[1]);
   
   
    B_ENCODER_DATA_VALID = 1;
}

// -------------------------- 超时检测函数 --------------------------
void encoder_check_timeout(void)
{
    if (B_ENCODER_TIMEOUT) {
        B_ENCODER_TIMEOUT = 0;
        // 通过USB输出超时信息
        printf_usb("Encoder communication timeout!\r\n");
    }
}
//DMA转运完成中断服务程序
void ENCODER_SPI_DMA_ISR(void) interrupt DMA_SPI_VECTOR
{
    // 1. 清除中断标志(文档强制要求,避免重复触发)
    DMA_SPI_STA = 0;
   
    // 2. 释放忙标志
    B_ENCODER_DMA_BUSY = 0;
   
    if(!B_ENCODER_NEXT_DMA_MODE)    //下一次DMA模式为接收
    {
      
        // rgb_set_color_state(RGB_COLOR_BLUE, RGB_STATE_BREATH); // 设置RGB状态为蓝色呼吸灯,表示首次发送数据
        P15 = 1; //释放MOSI总线,准备接收数据
        system_delay_ms(1); //短延时,确保总线稳定
        ENCODER_SPI_DMA_Rx(encoder_rx_buf, (Read_register_num+1)*2);
        B_ENCODER_NEXT_DMA_MODE = 1;
        //关闭DMA
        DMA_SPI_CR = 0x00;
    }
    else{                        //DMA接收完成
        B_ENCODER_NEXT_DMA_MODE = 0;
        //解析数据
        encoder_parse_data();
        // rgb_set_color_state(RGB_COLOR_RED, RGB_STATE_BREATH);
        //拉高CS结束传输
        CS = 1;

        //关闭DMA
        DMA_SPI_CR = 0x00;
        
    }
   
   
   
   
}



下面是调用

    TLE5012_Read(TLE5012_ANGLE_VALUE_AVAL_ADDR,1); // 读取角度寄存器







回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:31
  • 最近打卡:2025-10-30 13:40:00
已绑定手机

7

主题

10

回帖

209

积分

中级会员

积分
209
发表于 6 天前 | 显示全部楼层
痛苦
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:599
  • 最近打卡:2025-10-30 07:14:21
已绑定手机

87

主题

6407

回帖

1万

积分

超级版主

积分
12064
发表于 6 天前 | 显示全部楼层
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-10-31 06:22 , Processed in 0.126244 second(s), 56 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表