WPGGJ 2024-06-18 15:22 采纳率: 47.4%
浏览 1

AS5050编码器读取角度有问题求帮助

这是AS5050读取角度的代码,目前使用了这两个寄存器,能够读取角度,但是一直存在瑕疵

Angular Data - [0x3FFF]
Power ON Reset (POR) Register - [0x3F22]
void printDataToSerial(uint16_t data) {
    char buffer[50];
    sprintf(buffer, "数据: %u\r\n", data);
    HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
}

void readAndPrintData(void) {
    uint16_t angleData = 0;
    uint8_t txBuffer[2];
    uint8_t rxBuffer[2];
    HAL_StatusTypeDef status;

    uint16_t readCmd = 0x3FFF; // 正确的读取角度命令

    txBuffer[0] = (readCmd >> 8) & 0xFF; //0x3F
    txBuffer[1] = readCmd & 0xFF;    //0xFF

    // 发送读取命令
    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_RESET);
    status = HAL_SPI_Transmit(&hspi2, txBuffer, 2, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_SET);
    if (status != HAL_OK) {
        HAL_UART_Transmit(&huart1, (uint8_t*)"SPI Transmit Error\r\n", strlen("SPI Transmit Error\r\n"), HAL_MAX_DELAY);
        return;
    }
    char txbuffer[100];
    sprintf(txbuffer, "发送命令: 0x%02X 0x%02X \r\n", txBuffer[0], txBuffer[1]);
    HAL_UART_Transmit(&huart1, (uint8_t*)txbuffer, strlen(txbuffer), HAL_MAX_DELAY);
    HAL_Delay(1);

    // 读取数据
    txBuffer[0] = 0x00;
    txBuffer[1] = 0x00;

    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_RESET);
    status = HAL_SPI_TransmitReceive(&hspi2, txBuffer, rxBuffer, 2, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_SET);
    if (status != HAL_OK) {
        HAL_UART_Transmit(&huart1, (uint8_t*)"SPI Transmit/Receive Error\r\n", strlen("SPI Transmit/Receive Error\r\n"), HAL_MAX_DELAY);
        return;
    }

    // 拼接数据
    angleData = (rxBuffer[0] << 8) | rxBuffer[1];    //高位<<8 | 低位字节

    uint16_t angleValue = angleData & 0x03FF;    //0x03FF 是一个掩码,用于提取低10位的数据
    float actualAngle = (angleValue / (float)MAX_RAW_VALUE) * 360.0f;//公式

    bool alarmHi = (angleData & (1 << 13)) != 0;
    bool alarmLo = (angleData & (1 << 12)) != 0;

    char buffer[100];
    sprintf(buffer, "接收数据: 0x%02X 0x%02X 角度值: %u 实际角度值: %.2f° 下限报警: %d 上限报警: %d\r\n", 
            rxBuffer[0], rxBuffer[1], angleValue, actualAngle, alarmLo, alarmHi);
    HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
}

uint16_t constructCommand(uint16_t address, bool rwFlag) {
    // 确保正确设置命令和地址
    return (address & 0x3FFF) | (rwFlag ? 0x8000 : 0);    //0x8000读    0写
}

void readData(uint16_t address, uint8_t *data, uint8_t numBytes) {
    uint8_t txBuffer[2];
    uint8_t rxBuffer[numBytes];
    uint16_t cmd = constructCommand(address, true); // 读操作命令

    txBuffer[0] = (cmd >> 8) & 0xFF;
    txBuffer[1] = cmd & 0xFF;

    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_RESET);
    HAL_StatusTypeDef status = HAL_SPI_Transmit(&hspi2, txBuffer, 2, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_SET);
    if (status != HAL_OK) {
        HAL_UART_Transmit(&huart1, (uint8_t*)"SPI Transmit Error\r\n", strlen("SPI Transmit Error\r\n"), HAL_MAX_DELAY);
        return;
    }

    HAL_Delay(1);

    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_RESET);
    status = HAL_SPI_TransmitReceive(&hspi2, txBuffer, rxBuffer, numBytes, HAL_MAX_DELAY);
    HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_SET);
    if (status != HAL_OK) {
        HAL_UART_Transmit(&huart1, (uint8_t*)"SPI Transmit/Receive Error\r\n", strlen("SPI Transmit/Receive Error\r\n"), HAL_MAX_DELAY);
        return;
    }

    memcpy(data, rxBuffer, numBytes);
}

uint8_t readData8(uint16_t address) {
    uint8_t data;
    readData(address, &data, 1);
    return data;
}

uint16_t readData16(uint16_t address) {
    uint8_t data[2];
    readData(address, data, 2);
    return (data[0] << 8) | data[1];
}

uint8_t readPorRegister() {
    HAL_UART_Transmit(&huart1, (uint8_t*)"读取 POR 寄存器...\r\n", strlen("读取 POR 寄存器...\r\n"), HAL_MAX_DELAY);
    return readData8(0x3F22); // 确保该地址正确
}

uint16_t readAngularData() {
    HAL_UART_Transmit(&huart1, (uint8_t*)"读取角度数据...\r\n", strlen("读取角度数据...\r\n"), HAL_MAX_DELAY);
    return readData16(0x3FFF) & 0x03FF;
}


主要代码就这一段,目前就是角度数据(低10位)和角度不匹配,还有就是POR寄存器数据一直在变,按理说不会变动的,还有一个大问题就是角度一直都只有几个方向159或者338,按理说360°都应该读取的,但是一直就只有几个角度,下面是串口助手收到的数据。谁能帮忙指导一下,到底该怎么修改啊,找不到问题,SPI设置的nss是GPIO_MODE_OUTPUT_PP、其他的是GPIO_MODE_AF_PP,mode 0 ,这一个128我不知道对不对


```c
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;

img

  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-06-18 15:22
    关注

    引自免费微信小程序:皆我百晓生

    从你提供的信息来看,主要的问题集中在角度数据的读取不准确以及POR寄存器值的异常变化上。首先,我们来解决角度数据读取的问题。

    角度数据读取问题

    你提到的角度数据只显示为几个特定的值,这可能是由于SPI通信中的时序问题或者是读取命令的构建不正确导致的。在读取角度数据时,你使用了0x3FFF作为地址,这是正确的,但是要注意确保读取操作是在AS5050准备好输出数据时进行的。此外,确保SPI的波特率设置适合于AS5050,过高的波特率可能导致数据读取不完整或错误。

    检查点:

    1. SPI波特率:确认SPI的波特率是否设置得过高,例如你设置的SPI_BAUDRATEPRESCALER_128,这可能需要根据实际的时钟频率和AS5050的推荐值进行调整。

      hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; // 尝试降低波特率
      
    2. 读取时序:确保在读取数据前有足够的时间让AS5050准备数据。在发送读取命令后,可能需要加入适当的延时。

    POR寄存器值的变化

    通常情况下,POR寄存器在上电复位后会保持一个固定的值,除非设备经历再次复位。如果这个寄存器的值不断变化,这可能意味着SPI通信在某些时刻干扰了寄存器的正常状态,或者设备正在经历频繁的复位。检查以下几点:

    1. SPI通信的稳定性:确保CS引脚(片选信号)的控制是稳定的,在读取过程中没有意外地释放CS引脚,导致通信中断。

    2. 电源稳定性:检查供电线路,确保没有电压波动或电源噪声导致设备频繁复位。

    代码修改建议

    对于角度数据的读取,可以尝试以下代码修改:

    // 读取角度数据
    void readAngularData(uint16_t *angle) {
        uint16_t cmd = constructCommand(0x3FFF, true); // 构建读命令
        uint8_t rxBuffer[2];
        
        HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_RESET);
        HAL_StatusTypeDef status = HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd, 2, HAL_MAX_DELAY);
        if (status != HAL_OK) {
            HAL_UART_Transmit(&huart1, (uint8_t*)"SPI Transmit Error\r\n", strlen("SPI Transmit Error\r\n"), HAL_MAX_DELAY);
            return;
        }
        HAL_Delay(1); // 确保AS5050有时间准备数据
    
        status = HAL_SPI_Receive(&hspi2, rxBuffer, 2, HAL_MAX_DELAY);
        HAL_GPIO_WritePin(CS_GPIO_PORT, CS_PIN, GPIO_PIN_SET);
        if (status != HAL_OK) {
            HAL_UART_Transmit(&huart1, (uint8_t*)"SPI Receive Error\r\n", strlen("SPI Receive Error\r\n"), HAL_MAX_DELAY);
            return;
        }
    
        *angle = (rxBuffer[0] << 8) | rxBuffer[1];
    }
    

    对于POR寄存器的读取,同样需要确保读取过程中的稳定性和准确性,可以使用类似的方法修改。

    结论

    通过上述的检查点和代码修改,你应该能更接近找到问题所在。如果问题仍然存在,可能需要更深入地检查硬件连接、电源状况以及设备本身的健康状态。希望这些建议能帮助你解决问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 修改了问题 6月18日
  • 创建了问题 6月18日

悬赏问题

  • ¥15 CPU卡指令整合指令数据都在图片上
  • ¥15 火车票关联12306问题
  • ¥15 odoo17处理受托加工产品
  • ¥15 如何用MATLAB编码图三的积分
  • ¥15 圆孔衍射光强随孔径变化
  • ¥15 MacBook pro m3max上用vscode运行c语言没有反应
  • ¥15 ESP-PROG配置错误,ALL ONES
  • ¥15 结构功能耦合指标计算
  • ¥50 AI大模型精调(百度千帆、飞浆)
  • ¥15 非科班怎么跑代码?如何导数据和调参