16675|53

34

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

AD9106 相关问题 [复制链接]

 
本帖最后由 cheney03 于 2021-4-20 11:34 编辑

项目要用到AD9106这款芯片,现在遇到了点问题.

 首先我把我的需求说一下。我需要至少生成两路正弦波,并且能够同步输出,幅度/相位/频率(频率固定60/120/240/480/960KHz) 均可改变。

因为我的输出频率在1MHz以下,所以时钟我采用的是单端输入,参考的是数据手册page 24of48 图39设计,如图 此设计是否可行?

 

我采用的是单片机IO口模拟SPI写AD9106,目前棘手的问题是数据无法写入芯片,SPI写数据正确,已经用逻辑分析仪验证

 因为配置BGDR(写地址0x03),改变数据,通过万用表测量到REFIO引脚的无电平变化,正常改变code值,VREFIO的值也会改变。

 

 

QQ截图20210416104331.bmp (1.38 MB, 下载次数: 7)

QQ截图20210416104331.bmp

QQ截图20210416103936.bmp (974.94 KB, 下载次数: 0)

逻辑分析仪SPI写数据

逻辑分析仪SPI写数据

QQ截图20210416103517.bmp (166.76 KB, 下载次数: 0)

QQ截图20210416103517.bmp

QQ截图20210416103223.bmp (522.8 KB, 下载次数: 0)

用有源晶振单端输入

用有源晶振单端输入

最新回复

正常DDS是输出周期变化波形的,比如正弦或三角波等。 如果你想看看输出电流和输入的CODE变化关系可以使用“直流常数”功能,具体可在数据手册里找。   详情 回复 发表于 2022-10-21 19:46

赞赏

1

查看全部赞赏

点赞(1) 关注
 
 

回复
举报

34

帖子

0

TA的资源

一粒金砂(中级)

沙发
 

原理图是参考虾哥的帖子https://bbs.eeworld.com.cn/thread-511550-1-1.html,还有官方设计的

AD9106 Schematic.pdf

106.81 KB, 下载次数: 37

 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

#include <reg52.h>
#include <intrins.h>
sbit TRIGGER =P2^0;
sbit SCLK    =P2^1;
sbit SDIO    =P2^2;
sbit CS      =P2^3;
sbit RESET   =P2^4;




void SET_CS()
{
	CS=1;       	 //P2.3->/CS, /CS=1
}

void CLR_CS()
{
	CS=0;	         // /CS=0
}

void SET_SCLK() 
{
	SCLK=1;         //P2.3->SCLK, SCLK=1
}

void CLR_SCLK()
{
	SCLK=0;					// SCLK=0
}

void SET_SDIO(void)  
{
  SDIO=1;          //P2.2->SDIO, SDIO=1
}

void CLR_SDIO(void) 
{
  SDIO=0;					 //SDIO=0
}

void SET_Trigger(void) 
{
  TRIGGER=1;	     //P2.3->Trigger, Trigger=1
}

void CLR_Trigger(void) 
{
  TRIGGER=0;		  //Trigger=0
}

void SET_Reset(void) 
{
  RESET=1;	     //P2.3->Trigger, Trigger=1
}

void CLR_Reset(void) 
{
  TRIGGER=0;		  //Trigger=0
}

void delay (int length)
{
	while (length>=0)
	length--;
}


void spi_write_byte(unsigned char temp)
{
   unsigned char i;
   for(i=0;i<8;i++)//32
  {
	 if(temp&0x80)
	 {
	 	SET_SDIO();			                  //Send 1 to SDIO pin
	 }
	 else
	{
		CLR_SDIO();			           				//Send 0 to SDIO pin
	}

		delay(1);		     
		SET_SCLK();					   						//SCLK Rising
		delay(2);
		CLR_SCLK();					   						//SCLK falling
		delay(1);
		temp<<= 1;	                    	//Rotate data
	 }
}

void WriteToAD9106(unsigned int Address, unsigned int Data) 
{
  
	
	CLR_CS();
	CLR_SCLK();
  
  delay(1);  
	spi_write_byte(Address >> 8);
  spi_write_byte(Address); 
  
  spi_write_byte(Data >> 8);
  spi_write_byte(Data); 	
  SET_CS();
}

//void WriteToAD9106(unsigned int InstruAndData,unsigned int InstruAndData2)
//{
//unsigned  int SendValue =0;
//unsigned  int	SendValue2 =0;
//unsigned  int i = 0;

//SendValue = InstruAndData;
//SendValue2 = InstruAndData2; 	
//delay(1);
//	                                    //bring CS low
//CLR_SCLK();
//CLR_CS();
//delay(1);
//for(i=0;i<16;i++)//32
//{
//	if(SendValue&0x8000)
//	{
//		SET_SDIO();			                  //Send 1 to SDIO pin
//	}
//	else
//	{
//		CLR_SDIO();			           				//Send 0 to SDIO pin
//	}

//		delay(1);		     
//		SET_SCLK();					   						//SCLK Rising
//		delay(2);
//		CLR_SCLK();					   						//SCLK falling
//		delay(1);
//		SendValue <<= 1;	              	//Rotate data
//	}
//for(i=0;i<16;i++)//32
//{

//	if(SendValue2&0x8000)
//	{
//		SET_SDIO();			                  //Send 1 to SDIO pin
//	}
//	else
//	{
//		CLR_SDIO();			           				//Send 0 to SDIO pin
//	}
//		delay(1);		     
//		SET_SCLK();					   						//SCLK Rising
//		delay(2);
//		CLR_SCLK();					   						//SCLK falling
//		delay(1);
//		SendValue <<= 1;	              	//Rotate data
//	}

//		SET_CS();	                     		//bring CS high again
//}

void AD9106_Init()
{
 SET_CS();	
 SET_Trigger();
 CLR_Reset();	
 delay(14);
 SET_Reset();	
 
 WriteToAD9106(0x001f,0x0000);//模式连续运行。
 WriteToAD9106(0x000c,0x9f1f);
 WriteToAD9106(0x0027,0x3131);//DDS输出,预存波形
 WriteToAD9106(0x0037,0x00fc);//上斜坡锯齿波

 WriteToAD9106(0x0035,0x4000);//Data=0x4000  Very important,the maximum value is 0x4000
 WriteToAD9106(0x003e,0x006c);//Register 0x3E, Data=0x0E38
 WriteToAD9106(0x003f,0xe600);//Register 0x3F, Data=0xE600	   5MHz output,50MHz fsys 
 WriteToAD9106(0x001d,0x0001);//用新配置更新所有SPI设置(自清零)

 WriteToAD9106(0x001e,0x0001);//PAT_STATUS 0x1E, run bit=1	   Very important
 WriteToAD9106(0x001d,0x0001);
 delay(14);
 CLR_Trigger();
 WriteToAD9106(0x001d,0x0001);
}	


void main()
{
//unsigned  int InstruAndData_PatternType=0x001F0000;	         //Register 0x1F,  Data=0x0000(Continuous)	
//unsigned  int InstruAndData_Wave4=0x00263131;	               //Register 0x26,  Data=0x3131(wavefrom typ)	  DAC4 and DAC3 select the DDS prestore wave form.
//unsigned  int InstruAndData_DGAIN4=0x00324000;		           //DAC4_DGAIN 0x32, Data=0x4000  Very important,the maximum value is 0x4000
//unsigned  int InstruAndData_DGAIN3=0x00334000;			         //DAC3_DGAIN 0x33,
//unsigned  int InstruAndData_DDSMSB=0x003E1999;//0x003E0E38;	 //Register 0x3E, Data=0x0E38
//unsigned  int InstruAndData_DDSLSB=0x003F9A00;//0x003FE600;	 //Register 0x3F, Data=0xE600	   10MHz output,180MHz fsys 10M=(FTW/2^24)*180M FTW=0XE38E6(932067.5555555556)
//unsigned  int InstruAndData_DDS4_PW=0x00401300;		           //Register 0x40, DDS4  degree	   adjust the DDS4 and DDS3 to have the same phase
//unsigned  int InstruAndData_Run=0x001E0001;                  //PAT_STATUS 0x1E, run bit=1	   Very important
//unsigned  int InstruAndData_update=0x001D3D70;//0x001D0001;	 //Register 0x1D, Data=0xE600

// AD9106_Init();	

	while(1)
  {
       
//	  AD9106_Init();
      WriteToAD9106(0x0003,0x003F);
		
////  WriteToAD9106(0x3203,0x982F);
////  WriteToAD9106(InstruAndData_PatternType);
//    WriteToAD9106(0x001F,0x0000);		
////  WriteToAD9106(InstruAndData_Wave4);
//	  WriteToAD9106(0x0026,0x3131);
////  WriteToAD9106(InstruAndData_DGAIN4);
//	  WriteToAD9106(0x0032,0x4000);
////  WriteToAD9106(InstruAndData_DGAIN3);
//    WriteToAD9106(0x0033,0x4000);		
////  WriteToAD9106(InstruAndData_DDSMSB);
//    WriteToAD9106(0x003E,0x1999); 		
////  WriteToAD9106(InstruAndData_DDSLSB);
//	  WriteToAD9106(0x003F,0x9A00);
////  WriteToAD9106(InstruAndData_DDS4_PW);
//    WriteToAD9106(0x0040,0x1300);

////  WriteToAD9106(InstruAndData_update);
//    WriteToAD9106(0x001D,0x3D70);
////  WriteToAD9106(InstruAndData_Run);
//    WriteToAD9106(0x001E,0x0001);
////  WriteToAD9106(InstruAndData_update);
//    WriteToAD9106(0x001D,0x3D70);
//    delay(10);
 //   CLR_Trigger();
////  WriteToAD9106(InstruAndData_update);
//    WriteToAD9106(0x001D,0x3D70);
////  while(1);
//	   
  }	
}

 

点评

程序也是参考官方的,发现用官方的SPI写例程连续写地址+数据共32位数据不对,后面我分开写地址和数据,用逻辑分析仪I抓取SPI写数据正确,但是数据无法写入芯片,WriteToAD9106(0x0003,0x003F);写地址0x0003,改变数据  详情 回复 发表于 2021-4-20 11:50
 
 
 

回复

9797

帖子

24

TA的资源

版主

4
 

用示波器测量一下时钟“CLKP”是否正常,用万用表测试一下AVDD,DVDD电压是否正常,除硬件问题。

芯片复位后,使用SPI读取全部非零的寄存器,对比数据手册看数值是否一致。

用官方提供的ADuC7026例程做移植,或者参照https://wiki.analog.com/resources/eval/dpg/eval-ad9106这里的例程测试能否正常通信。

 

点评

示波器测输入时钟晶振输入正常,AVDD,DVDD均为3.3V,接REFIO电容两端参考电压为0.999V,DLDO1/DLDO2/CLKLDO 电容两端电压均为1.8V  详情 回复 发表于 2021-4-20 15:34
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

5
 
cheney03 发表于 2021-4-20 11:43 #include <reg52.h> #include <intrins.h> sbit TRIGGER =P2^0; sbit SCLK =P2^1; sbit ...

程序也是参考官方的,发现用官方的SPI写例程连续写地址+数据共32位数据不对,后面我分开写地址和数据,用逻辑分析仪I抓取SPI写数据正确,但是数据无法写入芯片,WriteToAD9106(0x0003,0x003F);写地址0x0003,改变数据字,通过万用表测量到REFIO引脚的无电平变化,说明数据没有写入

点评

可以试着排除硬件或通信问题,比如复位后读全部非零寄存器,或者写入后再读出对比看是否一致。 或者测量硬件看是否正常。  详情 回复 发表于 2021-4-20 12:49
 
 
 

回复

9797

帖子

24

TA的资源

版主

6
 
cheney03 发表于 2021-4-20 11:50 程序也是参考官方的,发现用官方的SPI写例程连续写地址+数据共32位数据不对,后面我分开写地址和数据,用 ...

可以试着排除硬件或通信问题,比如复位后读全部非零寄存器,或者写入后再读出对比看是否一致。

或者测量硬件看是否正常。

点评

还有一个疑问,我主机MCU供电电压是5V的,AD9106的供电电压3.3V,SPI通讯是否要求主从机电压一致?若像我这样SPI通讯,电压过高是否会损坏或者击穿芯片?  详情 回复 发表于 2021-4-20 15:00
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

7
 
littleshrimp 发表于 2021-4-20 12:49 可以试着排除硬件或通信问题,比如复位后读全部非零寄存器,或者写入后再读出对比看是否一致。 或者测 ...

还有一个疑问,我主机MCU供电电压是5V的,AD9106的供电电压3.3V,SPI通讯是否要求主从机电压一致?若像我这样SPI通讯,电压过高是否会损坏或者击穿芯片?

点评

不能使用5V驱动,应该会损坏,但不一定肯定会损坏。 [attachimg]534380[/attachimg]  详情 回复 发表于 2021-4-20 16:29
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

8
 
littleshrimp 发表于 2021-4-20 11:48 用示波器测量一下时钟“CLKP”是否正常,用万用表测试一下AVDD,DVDD电压是否正常,除硬件问题。 ...

示波器测输入时钟晶振输入正常,AVDD,DVDD均为3.3V,接REFIO电容两端参考电压为0.999V,DLDO1/DLDO2/CLKLDO 电容两端电压均为1.8V

点评

那还是重点检查通信吧,应该是通信方面的问题。  详情 回复 发表于 2021-4-20 16:29
 
 
 

回复

9797

帖子

24

TA的资源

版主

9
 
cheney03 发表于 2021-4-20 15:00 还有一个疑问,我主机MCU供电电压是5V的,AD9106的供电电压3.3V,SPI通讯是否要求主从机电压一致?若像我 ...

不能使用5V驱动,应该会损坏,但不一定肯定会损坏。

个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

9797

帖子

24

TA的资源

版主

10
 
cheney03 发表于 2021-4-20 15:34 示波器测输入时钟晶振输入正常,AVDD,DVDD均为3.3V,接REFIO电容两端参考电压为0.999V,DLDO1/DLDO2/CLKL ...

那还是重点检查通信吧,应该是通信方面的问题。

点评

有个很奇怪的现象,按图中接法,逻辑分析仪单独接单片机,抓取的数据正确,但是中间连接了我的AD9106实验板,无法抓取数据,感觉是芯片的SLCK/SDIO/CS这几引脚有阻碍作用。AD9106的输入时钟(CLKP/CLKN)对SPI通讯没  详情 回复 发表于 2021-4-21 11:40
先发送命令字+地址  接着读两字节(数据为16位),然后两字节数据再做处理,这样时序方面有没错呢?  详情 回复 发表于 2021-4-20 16:45
我也觉得通信方面问题比较大,写数据我用逻辑分析仪抓取数据是对的,读要怎么读寄存器呢,小白不怎么会写程序  详情 回复 发表于 2021-4-20 16:37
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

11
 
littleshrimp 发表于 2021-4-20 16:29 那还是重点检查通信吧,应该是通信方面的问题。

我也觉得通信方面问题比较大,写数据我用逻辑分析仪抓取数据是对的,读要怎么读寄存器呢,小白不怎么会写程序

点评

从AD9106写一字节,模拟SPI总线方式 void spi_write_byte(unsigned char temp) { unsigned char i; for(i=0;i<8;i++)//32 { if(temp&0x80) { SET_SDIO(); //Send 1  详情 回复 发表于 2021-4-20 16:40
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

12
 
cheney03 发表于 2021-4-20 16:37 我也觉得通信方面问题比较大,写数据我用逻辑分析仪抓取数据是对的,读要怎么读寄存器呢,小白不怎么会写 ...
从AD9106写一字节,模拟SPI总线方式
void spi_write_byte(unsigned char temp)
{
   unsigned char i;
   for(i=0;i<8;i++)//32
  {
	 if(temp&0x80)
	 {
	 	SET_SDIO();			                  //Send 1 to SDIO pin
	 }
	 else
	{
		CLR_SDIO();			           				//Send 0 to SDIO pin
	}

		delay(1);		     
		SET_SCLK();					   						//SCLK Rising
		delay(2);
		CLR_SCLK();					   						//SCLK falling
		delay(1);
		temp<<= 1;	                    	//Rotate data
	 }
}


//从AD9106读一字节,模拟SPI总线方式
unsigned char spi_read_byte()
{
    unsigned char tdata,i;
    for(i=8;i;i--)
    {   delay(1);	
        CLR_SCLK();
        delay(2);
	    SET_SCLK();
        tdata<<=1;
        if(SDIO)
		tdata|=1;
    
    }
    return tdata;
}





unsigned int Read_AD9106(unsigned int Address) 
{
  
	unsigned int data1,data2;
	unsigned int tdata;
	
	CLR_CS();
	CLR_SCLK();
  
    delay(1);  
    spi_write_byte(Address >> 8);//
    spi_write_byte(Address);    //发送命令字和地址
  
    data1=spi_read_byte();     //读取数据
    data2=spi_read_byte();
  	
    SET_CS();
    tdata=(data1<<8)|data2;
    return tdata;
}

 

 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

13
 
littleshrimp 发表于 2021-4-20 16:29 那还是重点检查通信吧,应该是通信方面的问题。

先发送命令字+地址  接着读两字节(数据为16位),然后两字节数据再做处理,这样时序方面有没错呢?

 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

14
 
littleshrimp 发表于 2021-4-20 16:29 那还是重点检查通信吧,应该是通信方面的问题。

有个很奇怪的现象,按图中接法,逻辑分析仪单独接单片机,抓取的数据正确,但是中间连接了我的AD9106实验板,无法抓取数据,感觉是芯片的SLCK/SDIO/CS这几引脚有阻碍作用。AD9106的输入时钟(CLKP/CLKN)对SPI通讯没影响吧,是不是只要上电,硬件SLCK/SDIO/CS连接正确就能写数据到芯片?

QQ图片20210421111645.png_temp.bmp (2.64 MB, 下载次数: 0)

QQ图片20210421111645.png_temp.bmp

点评

现在SPI写数据可以写入芯片,改变BGDR值,VREFIO电平有改变.。但是我的数据跟数据手册中的不一样。当BGDR=0x00时,电压应该是1.04V,我的测出来是0.98V。当BGDR=0x20(32)时,电压应该是0.84V,我的测出来是0.78V。  详情 回复 发表于 2021-4-21 15:40
现在两端的电平都是3.3V吗?  详情 回复 发表于 2021-4-21 12:01
 
 
 

回复

9797

帖子

24

TA的资源

版主

15
 
cheney03 发表于 2021-4-21 11:40 有个很奇怪的现象,按图中接法,逻辑分析仪单独接单片机,抓取的数据正确,但是中间连接了我的AD9106实验 ...

现在两端的电平都是3.3V吗?

点评

是的,电平一样。问题终于解决了,是我SPI通讯线过长,之前的线长40cm,换了20cm的,成功写入。再次感谢你的解答,后面可能还会遇到问题,到时再向你请教。  详情 回复 发表于 2021-4-21 13:31
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

16
 
littleshrimp 发表于 2021-4-21 12:01 现在两端的电平都是3.3V吗?

是的,电平一样。问题终于解决了,是我SPI通讯线过长,之前的线长40cm,换了20cm的,成功写入。再次感谢你的解答,后面可能还会遇到问题,到时再向你请教。

 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

17
 
cheney03 发表于 2021-4-21 11:40 有个很奇怪的现象,按图中接法,逻辑分析仪单独接单片机,抓取的数据正确,但是中间连接了我的AD9106实验 ...

现在SPI写数据可以写入芯片,改变BGDR值,VREFIO电平有改变.。但是我的数据跟数据手册中的不一样。当BGDR=0x00时,电压应该是1.04V,我的测出来是0.98V。当BGDR=0x20(32)时,电压应该是0.84V,我的测出来是0.78V。

QQ截图20210421153428.png (59.76 KB, 下载次数: 0)

QQ截图20210421153428.png
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

18
 

波形已经调出来了,但是波形不稳会上下抖动,而且一段时间后会失真

25EE7E7016FDC332A0F4CC190F2A6E88.jpg (136.75 KB, 下载次数: 0)

25EE7E7016FDC332A0F4CC190F2A6E88.jpg

08784FEC890A89C59EF77E3D80A8170E.jpg (140.95 KB, 下载次数: 0)

08784FEC890A89C59EF77E3D80A8170E.jpg
 
 
 

回复

34

帖子

0

TA的资源

一粒金砂(中级)

19
 
本帖最后由 cheney03 于 2021-4-25 11:07 编辑
void AD9106_Init()
{
   SET_CS();	
   SET_Trigger();
   CLR_Reset();	
   delay(14);
   SET_Reset();	
 
   WriteToAD9106(0x001f,0x0000);        //模式连续运行。 
// WriteToAD9106(0x0009,0x9F1F);      // DAC4 RSET  (0x000c,0x9f1f);DAC1 RSET
   WriteToAD9106(0x0026,0x3131);        //(0x0027,0x3131); //DDS输出,预存波形
   WriteToAD9106(0x0032,0x4000);        // DAC4_DGAIN
   WriteToAD9106(0x0033,0x4000);        // DAC3_DGAIN
 
//WriteToAD9106(0x0036,0x00fc);        //DAC3/4 //(0x0037,0x00fc); DAC1/2锯齿配置寄存器 上斜坡锯齿波

//WriteToAD9106(0x0035,0x4000);      //Data=0x4000  Very important,the maximum value is 0x4000
  WriteToAD9106(0x003e,0x0A3D); //       //Register 0x3E, Data=0x009D
  WriteToAD9106(0x003f,0x7100); //      //Register 0x3F, Data=0x4900	   1MHz output,25MHz fsys 
  WriteToAD9106(0x001d,0x0001);       //用新配置更新所有SPI设置(自清零)

  WriteToAD9106(0x001e,0x0001);      //PAT_STATUS 0x1E, run bit=1	   Very important
  WriteToAD9106(0x001d,0x0001);      //用新配置更新所有SPI设置(自清零)
  delay(14);
  CLR_Trigger();
  WriteToAD9106(0x001d,0x0001);      //用新配置更新所有SPI设置(自清零)
}

初始化函数是按这个配置的

点评

你的电流输出没有加缓冲放大器是吗?  详情 回复 发表于 2021-4-25 11:25
 
 
 

回复

9797

帖子

24

TA的资源

版主

20
 
cheney03 发表于 2021-4-25 11:06 void AD9106_Init() { SET_CS(); SET_Trigger(); CLR_Reset(); delay(14); SET_R ...

你的电流输出没有加缓冲放大器是吗?

点评

暂时没加(缓冲放大器我用的是AD4817-2),按官方的设计,接进去芯片会发烫,可能我硬件有问题(待查),就直接在输出端对地接电阻测量的  详情 回复 发表于 2021-4-25 11:41
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表