AD5270数字电位器使用说明

一、背景

有个项目使用了AD5270数字电位器,用来替代了传统的电位器实现数字控制。但发送命令数据一直没有反应,电阻也出不来,搞了好久。

二、数字接口

兼容SPI接口,通讯时序也不细究了,直接上官网的参考代码(官网上也有不少人出现了各种各样的问题,但都没有具体说明是怎么解决的)。

2.1 C文件

#include <ADuCM360.h>
#include "AD5270.h"
//***************************************************************************
//define
//***************************************************************************
#define SYNC_HIGH			pADI_GP1->GPOUT |= 0x80 ;
#define SYNC_LOW			pADI_GP1->GPOUT &=~ 0x80 ;

#define SCLK_HIGH			pADI_GP1->GPOUT |= 0x20 ;
#define SCLK_LOW			pADI_GP1->GPOUT &=~ 0x20 ;

#define SDIN_HIGH			pADI_GP1->GPOUT |= 0x40;
#define SDIN_LOW			pADI_GP1->GPOUT &=~ 0x40;

#define SDO     			((pADI_GP1->GPIN &0x10 ) ==0x10) ? 1 :0;
#define NOP_NUMBER		(50)
//***************************************************************************
//declaration
//***************************************************************************
void AD5270_IO_Initialize(void);
void SPI_nop(unsigned long cnt);
unsigned int SPI_Tx_16bit(unsigned int sendData);

//***************************************************************************
//***************************************************************************
void AD5270_IO_Initialize(void)
{
	pADI_GP1->GPOEN |=  0xE0;	
	SYNC_LOW;	
	SCLK_LOW;
	SDIN_LOW;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void SPI_nop(unsigned long cnt)
{
    unsigned long i=0;
    for(i=0;i<cnt;i++)
    {
        __NOP();
    }
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
unsigned int SPI_Tx_16bit(unsigned int sendData)
{
     unsigned char i=0;
     unsigned char temp= 0x0000;
     unsigned int res= 0x0;

     SPI_nop(NOP_NUMBER);
     SYNC_LOW;
     SCLK_LOW;
     SPI_nop(NOP_NUMBER);

     for(i=0;i<16;i++)
     {
       SCLK_HIGH;
       if( (sendData & (1<< (15-i))) == (1<< (15-i)))
       {SDIN_HIGH;}
       else	 {SDIN_LOW;}
       SPI_nop(NOP_NUMBER);

       SCLK_LOW;

       temp=SDO;
       res |= (temp <<(15-i) );

       SPI_nop(NOP_NUMBER);
     }
     SPI_nop(NOP_NUMBER);
     SYNC_HIGH;
     return res;
}

管脚配置就根据自己的MCU自行修改了,我自己用的是STM32F103,就按STM32的修改。

2.2 H头文件

描述的是与芯片手册对应的命令码


#define COMMAND_NOP  									(0x00<<10)
#define COMMAND_W_RDAC 								(0x01<<10)
#define COMMAND_R_RDAC  							(0x02<<10)
#define COMMAND_STORE_RDAC_50TP  			(0x03<<10)
#define COMMAND_SOFTWARE_RESET  			(0x04<<10)
#define COMMAND_R_50TP_NEXT_FRAME  		(0x05<<10)
#define COMMAND_R_LAST_50TP_LOCATION  (0x06<<10)
#define COMMAND_W_CONTROL  						(0x07<<10)
#define COMMAND_R_CONTROL  						(0x08<<10)
#define COMMAND_SOFTWARE_SHUTDOWN  		(0x09<<10)

void AD5270_IO_Initialize(void);
unsigned int SPI_Tx_16bit(unsigned int sendData);

主函数

uint16_t RD_data = 255; //满量程1023
uint16_t RD_flag = 0x0;
uint32_t RDAC_val_read;
uint32_t RDAC_val_read2;

int main()
{	
	ADuCM360_Initialize();//配置自己的MCU管脚初始化

	AD5270_IO_Initialize();//初始化管脚的电平
	
	while(1)
	{
		if(RD_flag)
        {//RD_flag自己仿真置1进入一次设定
        	//enable RDAC write
			SPI_Tx_16bit(COMMAND_W_CONTROL|0x03);
			//Write RDAC Reg
			SPI_Tx_16bit(COMMAND_W_RDAC|RD_data);

			//read RDAC Reg
			SPI_Tx_16bit(COMMAND_R_RDAC);
			RDAC_val_read=SPI_Tx_16bit(COMMAND_NOP);
			delay_us(10);
			//read _NEXT_FRAME
			SPI_Tx_16bit(COMMAND_R_50TP_NEXT_FRAME);
			RDAC_val_read2=SPI_Tx_16bit(COMMAND_NOP);
			//save to 50-tp
			//SPI_Tx_16bit(COMMAND_STORE_RDAC_50TP);

			RD_flag = 0;
        }
        delay_ms(500);
	}
	
}

三、调试

问题来了,数据下发下去,阻值怎么都没反应。用示波器量管脚,下发的波形都是正常的。并且读回来的数据异常,都是0,因为SDO一直是低电平。导致我都怀疑是不是芯片接口坏了,怎么会没有回复。没回复,我就不能保证接口是否正常通讯,陷入了沉思。

重要的来了,我回去再去看了一下数据手册,发现了一个地方可能存在问题,SDO管脚是一个开漏输出,要搭配上拉电阻使用。我心想就算不读数据,我只发数据也不影响设置阻值才对啊。但后面还有一句话“even if it is not use”,就算SDO不使用也得接上拉电阻。这不接上拉电阻难道会影响其他几个通讯脚,反正也没什么思路,那就再补上一个2.2k的上拉电阻吧(我的接口硬件是没带上拉电阻,管脚也没配上拉),反正也没什么好的思路了。

奇迹就发生,RDAC_val_read,RDAC_val_read2这两个变量有数值了,RDAC_val_read还跟RD_data的值对应上,说明读写正常。再去量一下AW的电阻,果然有了20k*255/1023=4.99k,修改RD_data的值,触发发生,电阻果然正常变化了。说明SDO这个上拉电阻是必须要接的,不然直接就不能正常工作。

那不读数据,只设数据能不能正常工作呢,是要每次都要发送使能命令COMMAND_W_CONTROL吗?修改代码测试一下。

uint16_t RD_data = 255; //满量程1023
uint16_t RD_flag = 0x0;
uint32_t RDAC_val_read;
uint32_t RDAC_val_read2;

int main()
{	
	ADuCM360_Initialize();//配置自己的MCU管脚初始化

	AD5270_IO_Initialize();//初始化管脚的电平

    SPI_Tx_16bit(COMMAND_W_CONTROL|0x02);//不用0x03,试试0x02
	
	while(1)
	{
		if(RD_flag)
        {//RD_flag自己仿真置1进入一次设定
			
			//Write RDAC Reg
			SPI_Tx_16bit(COMMAND_W_RDAC|RD_data);

			RD_flag = 0;
        }
        delay_ms(500);
	}
	
}

那不读数据,只设数据是可以正常设置阻值的,发送使能命令COMMAND_W_CONTROL可以在初始化只发一次,下次发送设置阻值就可以不用发。但使能命令必须发一次,不然芯片也是不能正常工作的。

四、总结

所以,不要忽略手册这句话“open-drain output requires an external pull-up resistor even if it is not use.”,SDO一定得接上拉电阻。保证数字接口通讯正常。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值