MCU驱动AD5231BRUZ_10K

芯片:AD5231 10k的量程

mcu: 普冉的F002B

通信协议:SPI

关于AD5231的数据手册可以到立创商城里面下载。

直接贴驱动代码

SPI配置

复制代码
#include "py_spi.h"
#include <py32f002b_hal_rcc.h>
#include "am_gpio_config.h"


SPI_HandleTypeDef Spi1Handle;

PyGpioStructDef ad5231_cs_gpio={AD5321_SPI_CS_GPIOx,AD5321_SPI_CS_GPIOx_PINx};

static void py_spi_gpio_config(void)
{

    GPIO_InitTypeDef  GPIO_InitStruct;

    __HAL_RCC_GPIOB_CLK_ENABLE();                   
    __HAL_RCC_GPIOA_CLK_ENABLE();  


      /*
    PB0   ------> SCK
    PA1   ------> MISO
    PA0   ------> MOSI
    PA6   ------> NSS
  */
    /*SCK*/
    GPIO_InitStruct.Pin       = SPI_CLK_GPIOx_PINx;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;

    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
    HAL_GPIO_Init(SPI_CLK_GPIOx, &GPIO_InitStruct);

    /* SPI NSS*/
    GPIO_InitStruct.Pin = AD5321_SPI_CS_GPIOx_PINx;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(AD5321_SPI_CS_GPIOx, &GPIO_InitStruct);


    /* MOSI*/
    GPIO_InitStruct.Pin       = SPI_MOSI_GPIOx_PINx ;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
    HAL_GPIO_Init(SPI_MOSI_GPIOx, &GPIO_InitStruct);

    /* MISO*/
    GPIO_InitStruct.Pin       = SPI_MISO_GPIOx_PINx ;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
    HAL_GPIO_Init(SPI_MISO_GPIOx, &GPIO_InitStruct);

    HAL_GPIO_WritePin(AD5321_SPI_CS_GPIOx, AD5321_SPI_CS_GPIOx_PINx, GPIO_PIN_SET);

}


/**
  * @brief  SPI_FLASH初始化 cs软件控制
  * @param  无
  * @note  	无
  * @retval 无
  */
 void py_spi_init(SPI_HandleTypeDef *spi_handle)
 {

    __HAL_RCC_SPI1_CLK_ENABLE(); 

    py_spi_gpio_config();

     /* 初始化SPI配置 */
     /* SPI1 */
     spi_handle->Instance               = SPI1;     
     /* 4 分频 */
     spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;  
     /* 全双工 */
     spi_handle->Init.Direction         = SPI_DIRECTION_2LINES;   
     /* 时钟极性低 */    
     spi_handle->Init.CLKPolarity       = SPI_POLARITY_LOW;   
     /* 数据采样从第一个时钟边开始 */
     spi_handle->Init.CLKPhase          = SPI_PHASE_1EDGE ;  
     /* SPI数据长度为8位 */    
     spi_handle->Init.DataSize          = SPI_DATASIZE_8BIT;  
     /* MSB 模式 */    
     spi_handle->Init.FirstBit          = SPI_FIRSTBIT_MSB; 
     /* NSS硬件模式 */    
     spi_handle->Init.NSS               = SPI_NSS_SOFT;  //软件CS
     /* 主模式 */
     spi_handle->Init.Mode = SPI_MODE_MASTER;                         
     
     /* SPI初始化 */
     HAL_SPI_Init(spi_handle);
 }

//cs控制
void py_spi_cs_writepin(PyGpioStructDef cs_gpio,uint8_t x)
{
    HAL_GPIO_WritePin(cs_gpio.GPIOx,cs_gpio.GPIO_Pin,x);
}


//SPI阻塞模式下发送和接收数据

/// @brief SPI发送一个字节
/// @param data     数据
/// @param Timeout  超时时间
/// @return 0发送成功
uint8_t py_spi_send_u8(uint8_t data , uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_Transmit(&Spi1Handle, &data, 1, Timeout);
}

/// @brief py_spi_send_u16 发送U16数据
/// @param data 数据
/// @param Timeout 超时时间
/// @return  0发送成功
uint8_t py_spi_send_u16(uint16_t data , uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_Transmit(&Spi1Handle, &data, 2, Timeout);
}

/// @brief py_spi_send_Buff 发送数据包
/// @param databuf 数据地址
/// @param len  长度
/// @param Timeout 超时
/// @return 0发送成功
uint8_t py_spi_send_Buff(uint8_t *databuf ,uint16_t len, uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_Transmit(&Spi1Handle, databuf, len, Timeout);
}

/// @brief SPI读取一个字节
/// @param data     数据
/// @param Timeout  超时时间
/// @return 0发送成功
uint8_t py_spi_read_u8(uint8_t *data , uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_Receive(&Spi1Handle, data, 1, Timeout);
}

/// @brief py_spi_send_u16 读取U16数据
/// @param data 数据
/// @param Timeout 超时时间
/// @return  0发送成功
uint8_t py_spi_read_u16(uint16_t *data , uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_Receive(&Spi1Handle, data, 2, Timeout);
}

/// @brief py_spi_send_Buff 读取数据包
/// @param databuf 数据地址
/// @param len  长度
/// @param Timeout 超时
/// @return 0发送成功
uint8_t py_spi_read_Buff(uint8_t *databuf ,uint16_t len, uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_Receive(&Spi1Handle, databuf, len, Timeout);
}






/// @brief spi阻塞模式下,发送和接收
/// @param pTxData 发送地址
/// @param pRxData 接收地址
/// @param len     个数
/// @param Timeout 超时时间
/// @return 0发送成功
uint8_t py_spi_send_and_read(uint8_t *pTxData, uint8_t *pRxData, uint16_t len,uint32_t Timeout)
{   
    return (uint8_t)HAL_SPI_TransmitReceive(&Spi1Handle, pTxData, pRxData, len, Timeout);
}

#ifndef __PY_SPI_H
#define __PY_SPI_H


#include "py32f0xx_hal.h"
#include <py32f002bx5.h>
#include "./py_gpio/py_gpio.h"

//硬件SPI




extern SPI_HandleTypeDef Spi1Handle;
extern PyGpioStructDef ad5231_cs_gpio;


void py_spi_init(SPI_HandleTypeDef *spi_handle);

void py_spi_cs_writepin(PyGpioStructDef cs_gpio,uint8_t x);

uint8_t py_spi_send_u8(uint8_t data , uint32_t Timeout);
uint8_t py_spi_send_u16(uint16_t data , uint32_t Timeout);
uint8_t py_spi_send_Buff(uint8_t *databuf ,uint16_t len, uint32_t Timeout);

uint8_t py_spi_read_u8(uint8_t *data , uint32_t Timeout);
uint8_t py_spi_read_u16(uint16_t *data , uint32_t Timeout);
uint8_t py_spi_read_Buff(uint8_t *databuf ,uint16_t len, uint32_t Timeout);

uint8_t py_spi_send_and_read(uint8_t *pTxData, uint8_t *pRxData, uint16_t len,uint32_t Timeout);

上面的SPI代码,和STM32的HAL库基本差不多。

下面是AD5231的驱动代码,驱动AD5231主要就是修改他的寄存器,正常使用到的命令就几个就够了,先简单的了解一下AD5231的命令吧

1.写入RDAC

2.读RDAC

3.将RDAC写入EEMEM

4.将EEMEM的数据恢复到REAC寄存器,基本就这几条,具体的参数命令可以看数据手册

AD5231的数据协议是3个字节,一共24bit.

下面直接贴驱动代码,只需要把SPI修改成你自己的驱动,基本就没问题。

复制代码
#include "ad5231.h"


#include "./delay/delay.h"



#define ad5231_delat_us(x) Delay_us(x)

static uint8_t ad5231_cs_set(uint8_t x)
{
    py_spi_cs_writepin(ad5231_cs_gpio,x);
}



/// @brief spi发送数据并读取数据
/// @param data 数据地址
/// @return 1成功 ,0失败
static uint8_t ad5231_spi_send_data(uint8_t *txdata,uint8_t *rxdata)
{
    uint8_t ret =0;
    
    ad5231_cs_set(0);
    ret = py_spi_send_and_read(txdata,rxdata,3,1000);
    ad5231_cs_set(1);
   
    if(ret == 0){
        return 1;
    }
    else{
        return 0;
    }
}







static uint8_t ad5231_write_cmd(uint8_t cmd,uint8_t addr,uint16_t data,uint8_t *rxdata)
{
    uint8_t txdata[3]={0};
    //uint8_t rxdata[3]={0};
    
    txdata[0] = ((cmd << 4) | addr);
    txdata[1] = (uint8_t)(data >> 8);
    txdata[2] = (uint8_t)(data & 0x00ff);
    
    return ad5231_spi_send_data(txdata,rxdata);
}


/// @brief 写入RDAC
/// @param data 0-2013
/// @return 1写入完成
uint8_t ad5231_write_rdac(uint16_t rdac)
{
     uint8_t rxdata[3]={0};

     if(rdac > AD5231_SizeRDAC){
        rdac = AD5231_SizeRDAC;
     }   

    return ad5231_write_cmd(AD5231_CMD_WRITE_RDAC,0x0,rdac,rxdata);
}

/// @brief 读取RDAC
/// @param data 0-2013
/// @return 1完成
uint8_t ad5231_read_rdac(uint16_t *rdac)
{

    uint8_t rxdata[3]={0};
    uint16_t data=0;

    if(ad5231_write_cmd(AD5231_CMD_READ_RDAC,0x0,0x0,rxdata))
    {
        ad5231_delat_us(200);
        ad5231_write_cmd(0x0,0x0,0x0,rxdata);
        data = rxdata[1] ;
        *rdac = ((data<<8) | rxdata[2]);
        return 1;
    }
    else
    {
        return 0;
    }
}


uint8_t ad5231_rdac_write_eemem(uint16_t rdac)
{
    uint8_t rxdata[3]={0};

    if(rdac > AD5231_SizeRDAC){
        rdac = AD5231_SizeRDAC;
     }  

    if(ad5231_write_cmd(AD5231_CMD_WRITE_RDAC,0x0,rdac,rxdata))
    {

        ad5231_delat_us(200);

        return ad5231_write_cmd(AD5231_CMD_WRITE_EEMEM,0x0,0x0,rxdata);

        
    }
    else
    {
        return 0;
    }

}

uint8_t ad5231_restores_eemem_to_rdac(void)
{
    uint8_t rxdata[3]={0};


    if(ad5231_write_cmd(AD5231_CMD_RESTORES_EEMEM_RDAC,0x0,0x0,rxdata))
    {

        ad5231_delat_us(300);

        return ad5231_write_cmd(AD5231_CMD_NOP,0x0,0x0,rxdata);//恢复编程
    }
    else
    {
        return 0;
    }

}


void ad5231_init(void)
{
    py_spi_init(&Spi1Handle);
   
}

//软件校准
static uint16_t ad5231_software_calibration_rdac(uint32_t r)
{
    
    double temp;

    temp = (double)r;

    if(r < AD5231_RWB_MIN){
        return 0;
    }
    else if(r > AD5231_RWB_MAX){
        return AD5231_SizeRDAC;
    }

    temp = ((temp -  88.193) / 8.6876);

    return (uint16_t)(temp+0.5);

}


uint8_t ad5231_set_RwB(uint32_t r)
{
    uint16_t rdac=0;

    if(r > AD5231_SizeR){
        r = AD5231_SizeR;
    }
    rdac = ad5231_software_calibration_rdac(r);

   return  ad5231_write_rdac(rdac);
}

uint8_t ad5231_set_RwA(uint32_t r)
{
    uint16_t rdac=0;
    rdac = ad5231_software_calibration_rdac((AD5231_SizeR -r));
    return   ad5231_write_rdac(rdac);
}


#ifndef __AD5231_H
#define __AD5231_H

#include "./py_gpio/py_gpio.h"
#include "./py_spi/py_spi.h"



//AD5272命令


#define AD5231_CMD_NOP          0x0         // NOP:无操作。
#define AD5231_CMD_RESTORES_EEMEM_RDAC  0X1  //EEMEMS软件复位到RDAC
#define AD5231_CMD_WRITE_EEMEM  0X2           //RDAC写入EEMEM
#define AD5231_CMD_WRITE_RDAC   0xB         // 写入RDAC。
#define AD5231_CMD_READ_RDAC    0xA        // 读取RDAC





#define AD5231_SizeR   9000//Ω  总电阻
#define AD5231_SizeRDAC   1024-1 //触点,抽头
#define AD5231_RW     55//
#define AD5231_RWB_MIN 90
#define AD5231_RWB_MAX 8970

void ad5231_init(void);
uint8_t ad5231_write_rdac(uint16_t rdac);//写RDAC
uint8_t ad5231_read_rdac(uint16_t *rdac);//读RDAC

uint8_t ad5231_rdac_write_eemem(uint16_t rdac);//把RDAC写入EEMEM
uint8_t ad5231_restores_eemem_to_rdac(void);//把EEMEM恢复到RDAC

uint8_t ad5231_set_RwB(uint32_t r);//设置WB端电阻
uint8_t ad5231_set_RwA(uint32_t r);//设置WA端电阻



#endif

这就是基本的驱动代码。

关于AD5231的一些问题点总结。

1.AD5231的总量程A-B端只有9kΩ,差了1k的阻值,有一点夸张。

我测得的0=88 Ω,1023时是8970 Ω。

2.SPI的速度降低一点,刚开始速度太快,读取RDAC时 返回数据错误。

3.需要连续命令时,中间需要一个延迟。

4.因为电阻值只有9k和数据测试差太多,所以就没使用数据手册的电阻和抽头的公式,需要自己写一个软件校准代码。可以使用wps做一个线性拟合。

复制代码
//软件校准
static uint16_t ad5231_software_calibration_rdac(uint32_t r)
{
    
    double temp;

    temp = (double)r;

    if(r < AD5231_RWB_MIN){
        return 0;
    }
    else if(r > AD5231_RWB_MAX){
        return AD5231_SizeRDAC;
    }

    temp = ((temp -  88.193) / 8.6876);

    return (uint16_t)(temp+0.5);

}


uint8_t ad5231_set_RwB(uint32_t r)
{
    uint16_t rdac=0;

    if(r > AD5231_SizeR){
        r = AD5231_SizeR;
    }
    rdac = ad5231_software_calibration_rdac(r);

   return  ad5231_write_rdac(rdac);
}

uint8_t ad5231_set_RwA(uint32_t r)
{
    uint16_t rdac=0;
    rdac = ad5231_software_calibration_rdac((AD5231_SizeR -r));
    return   ad5231_write_rdac(rdac);
}

这经过校准的代码。

通过按键设置输出1000,2000,3000电阻,经过电阻测量,还是挺准的。

硬件电路图

相关推荐
蓝斯4977 小时前
从.到实现一个Windows上的虚拟hid键盘设备
windows·单片机·计算机外设
熙芯XiChip8 小时前
硬实时与软实时RTOS核心区别
嵌入式硬件
伟大的前程8 小时前
unsigned int 定义的变量 在 电脑的 64 位系统中 和 32 位 cortex-m0 和 8 位的 51 单片机
单片机·嵌入式硬件
小渔村的拉线工9 小时前
1.HPM6E80 解析芯片整体工作原理和存储架构
单片机·嵌入式硬件·mcu·架构·hpm6e80
熙芯XiChip9 小时前
CAN与CANopen的本质区别
单片机
lilihewo10 小时前
Altium Designer 封装库的创建(分享pcb 3D封装库)
嵌入式硬件·51单片机
神罚天下ET11 小时前
典型arm位单片机启动流程(从上电到main.c)
c语言·arm开发·单片机
碧海银沙音频科技研究院12 小时前
蓝牙耳机使用WSDF5361锂保芯片进入船运模式实现方法
嵌入式硬件·算法
Zevalin爱灰灰12 小时前
模拟信号链电路——基于TL431的电压基准电路
单片机·嵌入式硬件
csdn杰哥13 小时前
瑞萨单片机开发教程[二十七] DTC 外部中断触发传输实验
单片机·嵌入式硬件·mongodb·瑞萨·ra6m5