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电阻,经过电阻测量,还是挺准的。

硬件电路图

相关推荐
飞凌嵌入式1 小时前
飞凌嵌入式亮相第九届瑞芯微开发者大会:AIoT模型创新重做产品
人工智能·嵌入式硬件·嵌入式·飞凌嵌入式
程序员JerrySUN8 小时前
Linux 内核基础统简全解:Kbuild、内存分配和地址映射
java·linux·运维·服务器·嵌入式硬件·缓存·文件系统
努力做小白10 小时前
Linux驱动19 --- FFMPEG
linux·运维·驱动开发·单片机·嵌入式硬件·ffmpeg
LiuYiCheng12345611 小时前
星慈光编程虫2号小车讲解第二篇--向左向右平移
单片机
范纹杉想快点毕业11 小时前
基于C语言的Zynq SOC FPGA嵌入式裸机设计和开发教程
c语言·开发语言·数据库·嵌入式硬件·qt·fpga开发·嵌入式实时数据库
LiuYiCheng12345612 小时前
星慈光编程虫2号小车讲解第一篇--向前向后
单片机
lxmyzzs13 小时前
【已解决】Jetson Orin NX apt更换国内源
嵌入式硬件·计算机视觉·bug
CC呢13 小时前
基于单片机智能交通灯设计
stm32·单片机·嵌入式硬件·交通灯
望获linux14 小时前
【Linux基础知识系列】第六十三篇 - 文件编辑器基础:vim
linux·运维·服务器·网络·嵌入式硬件·操作系统·嵌入式软件