搜索
bottom↓
回复: 10

求助:“CS5532发送转换命令(0x80)后,SDO不变低”的问题

[复制链接]

出0入0汤圆

发表于 2009-11-12 23:45:29 | 显示全部楼层 |阅读模式
各位大侠,请帮忙分析分析,不胜感激!


对CS5532的使用如下:
1. 硬件简单说明: V+=3V;V-=负3V;Ref+=3V;Ref-=负3V,晶振4.9152
2. 软件操作步骤说明
   1)上电后延时了50个ms(datasheet说超过20ms就可以)
   2)发送31个ff,1个fe,完成对端口复位
   3)发送命令03,bit RS=1,即数据0x20000000,复位内部逻辑
   4)等待读取配置寄存器,直到读出RV bit=1,即:数据0x10000000
   5)设置配置寄存器
   6)设置通道寄存器
   7)偏移,增益寄存器(下面的代码中没有,但是也测试过)
   8)发送数据转换指令0x80(datasheet说,不校准也可以直接转换,只是误差大而已)
   9)等待SDO=0
3. 问题描述:
   1)1-7个步骤正常,能够读出RV bit=1
   2)此外,也尝试过在第8个步骤之前,写入,读取配置,增益,偏移,通道寄存器,
      变化写入数据,发现读取数据和写入的一致,也侧面证明了CS5532工作基本正常
   3) 执行了步骤8以后,程序卡死在了步骤9
4. 以下是详细代码,请参考
sbit CS5532_SPI_DO = P1^0;
sbit CS5532_SPI_CS = P1^1;
sbit CS5532_SPI_CK = P1^2;
sbit CS5532_SPI_DI = P1^3;

void CS5532Test(void)
{
  int i;
  unsigned char rec=0;
  unsigned char rec1,rec2,rec3,rec4;
  //reset port
  CS5532Delay(  50000  );
  
  CS5532_SPI_CK = 0;CS5532Delay(3);
  CS5532_SPI_CS = 0;CS5532Delay(3);
  
  //复位端口,datasheet上说最少15个ff和1个fe,不放心,用了31个ff
  //其中用15个ff也做过测试,效果和31个ff一样
  for( i = 0; i< 31; i++ )
    CS5532ByteSend( 0xff );
  CS5532ByteSend( 0xfe );
  //复位内部逻辑,发送指令03,数据是0x20000000
  CS5532Delay(  50000  );
  CS5532ByteSend( 0x03 );
  CS5532ByteSend( 0x20 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  //等待复位(RV=1)完成,当读出值为0x10000000时候,复位完成
  while( rec != 0x10 )
  {
    CS5532ByteSend( 0x0b );
    rec = CS5532ByteRec( );
    CS5532ByteRec( );
    CS5532ByteRec( );
    CS5532ByteRec( );
  }
  //设置配置寄存器,V+,V-是正负3V,Ref电压是正负3V
  CS5532Delay(  100  );
  CS5532ByteSend( 0x03 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  //设置通道寄存器
  CS5532Delay(  100  );
  CS5532ByteSend( 0x05 );
  CS5532ByteSend( 0x02 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  CS5532ByteSend( 0x00 );
  //发送单词转换命令
  CS5532ByteSend( 0x80 );
  while( CS5532_SPI_DO == 1 );//等待SDO从1变成0
  CS5532ByteSend( 0x00 );     //清楚SDO flag
  rec1 = CS5532ByteRec( );    //读取32bit数据
  rec2 = CS5532ByteRec( );
  rec3 = CS5532ByteRec( );
  rec4 = CS5532ByteRec( );

}
void CS5532ByteSend( unsigned char ucData )
{
  int i;

  for( i = 0; i < 8; i++ )  
  {
    if( ucData & 0x80 )
      CS5532_SPI_DI = 1;
    else
      CS5532_SPI_DI = 0;
    CS5532Delay(10);
    CS5532_SPI_CK = 1;
    CS5532Delay(10);
    ucData = ucData << 1;
    CS5532_SPI_CK = 0;
    CS5532Delay(10);
  }  
  CS5532_SPI_DI = 0;
}

unsigned char CS5532ByteRec( void )
{
  int i;
  unsigned char ucData = 0;
  
  for( i = 0; i < 8; i++ )  
  {
    ucData = ucData << 1;
    if( CS5532_SPI_DO )
      ucData = ucData | 0x01;
    else
      ucData = ucData & 0xfe;
    CS5532Delay(10);
    CS5532_SPI_CK = 1;
    CS5532Delay(10);
    CS5532_SPI_CK = 0;
    CS5532Delay(10);
  }  
  return ucData;
}
void CS5532Delay( unsigned int i ) { while(i--); }

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2009-11-13 09:41:58 | 显示全部楼层
有用过的朋友请指点指点,着急等待中!

出0入0汤圆

发表于 2009-11-13 11:26:27 | 显示全部楼层
这是我以前写的,调试通过的,你可以看下,如有问题,和我联系吧:hanbao0371@sina.com
/******************************************
Project    :读取CS5532的数据,并在LED上显示





*******************************************/
#ifndef  _CS5532_
#define  _CS5532_



/*********端口定义*********/
#define CS5532_CS    PD1                        //定义片选端
#define CS5532_SDO   PD2                        //定义数据输入端
#define CS5532_SDI   PD3                        //定义数据输出端
#define CS5532_SCLK  PD4                        //定义移位脉冲端

#define BIT_CS    PORTD |= BIT(CS5532_CS)       //置CS端为1
#define CLR_CS    PORTD &=~BIT(CS5532_CS)       //清CS端
#define BIT_SDI   PORTD |= BIT(CS5532_SDI)      //置SDI端为1
#define CLR_SDI   PORTD &=~BIT(CS5532_SDI)      //清SDI端
#define BIT_SCLK  PORTD |= BIT(CS5532_SCLK)     //置SCLK端为1
#define CLR_SCLK  PORTD &=~BIT(CS5532_SCLK)     //清SCLK端


/************全局变量定义************/
uchar CS5532_data[8]={0};
uchar zhongduan_flag=0;                          //转换数据完成标志位
/*~~~~~~~~~宏定义,配置建立通道寄存器~~~~~~~~~~~~*/
#define Physics_channel1        0x00             //通道1
#define Physics_channel2        0x01             //通道2
      /************设置增益”***********/
#define Gain_bit                3                //增益控制位是3位
#define Gain_1                  0                //Gain=1
#define Gain_2                  1                //Gain=2
#define Gain_4                  2                //Gain=4
#define Gain_8                  3                //Gain=8
#define Gain_16                 4                //Gain=16
#define Gain_32                 5                //Gain=32
#define Gain_64                 6                //Gain=6
      /********设置字数率(FRS=0)*********/
#define WR_bit                  4                //Word_Rate(字输出率)控制是4位
#define WR_120                  0                //Word_Rate=120Hz
#define WR_60                   1                //Word_Rate=60Hz  
#define WR_30                   2                //Word_Rate=30Hz
#define WR_15                   3                //Word_Rate=15Hz
#define WR_7.5                  4                //Word_Rate=7.5Hz
#define WR_3840                 8                //Word_Rate=384120Hz  
#define WR_1920                 9                //Word_Rate=1920Hz
#define WR_960                  10               //Word_Rate=960Hz
#define WR_480                  11               //Word_Rate=480Hz
#define WR_240                  12               //Word_Rate=240Hz
     /*******设置单/双极性******/
#define Jixing_bit              1                //Unipolar/Bipolar控制是1位
#define Select_unipolar         1                //选择单极性
#define Select_bipolar          0                //选择双极性

                  
/********向CS5532写入一个字节数据*********/
void write_byte(uchar data)
{
  uchar i=0;
  CLR_SCLK;                                     //清SCLK端
  for(i=0;i<8;i++)
   {
    if((data<<i)& 0x80)                          //从MSB开始发送,
             BIT_SDI;                                   //与0x80后为1时,SDI输出1
          else                                         //否则,SDI输出0
              CLR_SDI;
        BIT_SCLK;                                    //SCLK上升沿,完成一位数据的写入
        delay_us(1);
        CLR_SCLK;
        delay_us(1);  
   }
}

/************配置建立通道寄存器**************
uchar Channel1_setup_set(uchar value ,uchar bit)
{
  uchar i=0,xy=0;
/*  
  for(i=0;i<bit;i++)
   {
     xy <<= 1;
     xy |= 0x01;
   }
  xy &=~xy;
*/
      
//}

/**********读寄存器************/
ulong Read_Register(uchar commd)
{
  uchar i=0;
  ulong Register_buf=0;
  CLR_CS;                                         //置片选有效                                 
  write_byte(commd);                              //被访问的寄存器地址
//  CLR_SCLK;
  CLR_SDI;
  delay_us(1);
  for(i=0;i<32;i++)
  {
    CLR_SDI;                                      //读数据期间,SDI输出必须为0
    Register_buf <<= 1;
    BIT_SCLK;                                     //SCLK上升沿,完成一位数据的写入
        delay_us(1);
        if(PIND & 0x04 )                                //读取32位数据
           Register_buf |= 0x00000001;
        delay_us(1);   
        CLR_SCLK;
        delay_us(1);
  }
//  BIT_CS;
  delay_us(1);  
  return (Register_buf);
}


/************初始化CS5532*************/
void init_CS5532 (void)
{
  uchar i=0;
  delay_ms(2000);                                   //延时20MS
  delay_ms(2000);                                   //延时20MS
  BIT_CS;
  delay_us(1);
  CLR_CS;                                         //置片选有效                                 
  delay_us(1);
  for(i=0;i<18;i++)                               //写入15次0xff
    write_byte(0xff);
  write_byte(0xfe);                               //写一次0xfe
/******向配置寄存器写入复位命令*****/
  write_byte(0x03);                               //通道1,配置寄存器
  write_byte(0x20);                               //分4次写入32位数据,RESET=1,
  write_byte(0x00);
  write_byte(0x00);
  write_byte(0x00);                               /**按理说应写入32位数据,但手册上默然后几位是0,故写入24位数据**/  

  delay_ms(2000);                                //等待复位完成
  
  write_byte(0x03);
  write_byte(0x02);                               //RESET=0,VREF=2.5V,FRS=0
  write_byte(0x00);
  write_byte(0x00);
  write_byte(0x00);  
/********配置建立通道寄存器**********/
  write_byte(0x05);                               //单个建立通道寄存器地址
  write_byte(0x02);                               //通道1,Gain=1,字速率为7.5(FRS=0 )
  write_byte(0x40);
  write_byte(0x02);                               //为32位数据,其实是两个相同的16位的数据
  write_byte(0x40);

  write_byte(0xc0);                               //启动持续转换命令
}

/*********读取CS5532的数据**********/
ulong Read_CS5532(void)
{
  uchar i=0,j=0;
  ulong data_buf=0;
  CLR_CS;                                         //置片选端有效
  CLR_SCLK;                                       //脉冲端置低
//  CLR_SDI;                                        //SDI输出0
  CLR_SDI;  
  for(i=0;i<8;i++)                                //连续写入8个0到SDI
   {
        BIT_SCLK;
        delay_us(1);
        CLR_SCLK;
        delay_us(1);   
   }
   for(i=0;i<32;i++)
    {
          BIT_SCLK;                                 //下降沿读数据
          delay_us(1);
          data_buf <<= 1;                          //先收到的数据放在最高位
          if(PIND & 0x04 )                        //读取到高电平时,该位为1
            data_buf |= 0x00000001;
          else
            data_buf &= 0xfffffffe;
          CLR_SCLK;
          delay_us(1);  
          }
   data_buf >>= 8;
   return (data_buf);         
}

/********MCU初始化函数*******/
void mcu_init(void)
{
  DDRA=0xff;                              //PA口设为输出
  PORTA=0xff;
  DDRB=0xff;                              //PB口设为输出
  PORTB=0xff;
   
  DDRC=0xff;
  PORTC=0xff;
                                             
  DDRD =0xfe;                            //SDO设为输入,其他的为输出
  PORTD=0xff;
  
  timer1_init();
//  CS5513_init();
  init_CS5532();
//  SHT11_connect_reset();                  //SHT11初始化复位
}

/*********读取到的32位数据分装在6个数组中,便于送数码管显示***********/
void Change_To_display (ulong data)
{
  uchar i=0;
// data >>= 4;
/***
  ulong temp=0;
  uchar tempf=0;                                  //定义数据整数部分  
  float tempi=0,data1;                            //定义数据小数部分

  data >>= 4;                                    
  data1 = (float)((data*2.5)/1048576);            //甩掉4位数据后,转换为电压值      
//  data = (data*2.5)/16777215;
  tempf=(uchar)data1;      
  tempi=data1-tempf;                              //获得小数部分
  CS5532_data[0]=duan_ma[(uchar)tempf];           //获得整数部分

  temp=(ulong)(tempi*100000);                     //数据放大1000000倍,便于显示小数
  for(i=5;i>0;i--)
  {
   CS5532_data=duan_ma[temp%10];
   temp = temp/10;
  }
  CS5532_data[0] &= 0x7f;                          //个位上数据加小数点
***/
  /***用于测试读取AD最大值和最小值的十六进制显示*/
  for(i=0;i<4;i++)                                 //高16位数据分离
   CS5532_data=duan_ma[(uchar)((data & (0xf0000000 >>i*4))>>(28-i*4))];
  for(i=4;i<8;i++)                                 //低16位数据分离
    CS5532_data=duan_ma[(uchar)((data & (0xf0000000 >> 4*i))>>(12-4*(i-4)))];

}



/***********未在实际中测试*******************
名称:Self_offset_calibration
功能:完成自我漂移校验
说明:
       硬件电路说明:差分模拟输入电压连接到一起后接入到CS5532的AIN-
       自我漂移校验只针对增益为1时,对其他值不起作用
*********************************************/
void Self_offset_calibration(void)
{
  /********配置寄存器至校验模式********/         
  write_byte(0xc1);                              //CSRP2~0=000(指向建立通道寄存器1和2)
                                                 //CC2~0=001,自我漂移校验
  write_byte(0x0a);                              //IS=1,OGS=0
  write_byte(0x00);                              //校验后的数据保存至漂移寄存器中
  write_byte(0x00);
  
  write_byte(0x81);                              //启动自我漂移校验

  timer1_init();                                 //校验初始化完成后,开启外中断
  if(zhongduan_flag == 1)                        //转换完成标志位有效
          {
           GICR  = 0x00;                                 //关闭中断
     SREG  = 0x00;
           zhongduan_flag=0;         
           Change_To_display(Read_Register(0x09));     //读取漂移寄存器       
           SREG  |= 0x80;                              //开中断
           GICR  |= 0x40;        
          }
  /******配置寄存器至普通模式*******/       
  write_byte(0x03);
  write_byte(0x02);                               //RESET=0,VREF=2.5V,FRS=0
  write_byte(0x00);
  write_byte(0x00);
  write_byte(0x00);                                          
}


#pragma interrupt_handler INT1_isr:3       
void INT1_isr(void)
{
  GICR  = 0x00;                              //关闭外部中断
  SREG  = 0x00;
  zhongduan_flag=1;                          //转换数据完成
//  Change_To_display(Read_CS5532());

}       


/***********显示程序*************/
void display(void)
{
uchar i=0,j=0;
for(i=0;i<6;i++)
  {
   PORTA = SHT11_data;
   PORTB = 0x80>>i;
   delay_ms(100);
  }
}

#endif

出0入0汤圆

发表于 2009-11-13 11:31:46 | 显示全部楼层
问题好像出现你读CS5532上,读取的时候是读取32位,而且保存的时候是后者24位的数据,
你最好用示波器看下,CS5532在初始化后,是否能观察到SDO被拉低,如果没有,说明你的初始化程序有问题。

出0入0汤圆

 楼主| 发表于 2009-11-13 13:02:25 | 显示全部楼层
感谢hanbao0371 朋友的帮助,有两点问题,请请教一下
1. > 读取的时候是读取32位,而且保存的时候是后者24位的数据,
   现在我的问题是,发送完毕0x80(或者0xc0)转换命令之后,SDO一直不等于0,
   个人感觉和“读数据的位数”有什么关系呢。
2. > 你最好用示波器看下,CS5532在初始化后,是否能观察到SDO被拉低,如果没有,说明你的初始化程序有问题。
   手册上没有提到过初始化之后,SDO会拉低,应该是您个人的经验把,如果是这样子,非常感谢,我可以试试。
再次感谢您的回答。

出0入0汤圆

发表于 2009-11-16 13:22:02 | 显示全部楼层
本人程序:
CLR AD_CS
                                LCALL INIT_SPI     ;初始化,发15个FFH和1个FEH
                                CLR AD_CS
                                NOP
                                NOP
                                MOV A,#03H          ;复位寄存器
                                LCALL Write8bit
                                MOV A,#20H
                                LCALL Write8bit
                                LCALL Write8bit
                                LCALL Write8bit
                                LCALL Write8bit
                                ;MOV A,#03H          ;写设置寄存器
                                ;LCALL Write8bit
                                ;MOV A,#20H
                                ;LCALL Write8bit
                                ;MOV A,#00H
                                ;LCALL Write8bit
                                ;MOV A,#00H
                                ;LCALL Write8bit
                                ;MOV A,#00H
                                ;LCALL Write8bit
                                MOV A,#05H          ;写通道寄存器
                                LCALL Write8bit
                                MOV A,#10H
                                LCALL Write8bit
                                MOV A,#80H
                                LCALL Write8bit
                                MOV A,#10H
                                LCALL Write8bit
                                MOV A,#80H
                                LCALL Write8bit
                                ;MOV A,#01H          ;写偏移寄存器
                                ;LCALL Write8bit
                                ;MOV A,#000H
                                ;LCALL Write8bit
                                ;MOV A,#000H
                                ;LCALL Write8bit
                                ;MOV A,#000H
                                ;LCALL Write8bit
                                ;MOV A,#000H
                                ;LCALL Write8bit
                                ;MOV A,#02H          ;写增益寄存器
                                ;LCALL Write8bit
                                ;MOV A,#01H
                                ;LCALL Write8bit
                                ;MOV A,#00H
                                ;LCALL Write8bit
                                ;MOV A,#00H
                                ;LCALL Write8bit
                                ;MOV A,#00H
                                ;LCALL Write8bit
                                
                                MOV A,#0c0H          ;发送连续转换命令
                                CLR AD_SDI
                                LCALL Write8bit
NNN:                            NOP
LOOP:                           ;LCALL DELAY1uS
                                JB AD_SDO,$         ;等待输出口变低
                                MOV A,#00H
                                LCALL Write8bit
                                MOV R0,#30H        ;调用读取32位子程序
                                LCALL Read32bit
                                LCALL DELAY200MS
jmp loop
本人在用中,也有些许问题,愿意共同讨论的加我的qq 273045940

出0入0汤圆

发表于 2009-11-16 21:37:08 | 显示全部楼层
to hmilyxia
    发送完毕0x80(或者0xc0)转换命令之后,SDO一直不等于0,
   个人感觉和“读数据的位数”有什么关系呢。

这样理解好像不太对,好像没有关系。
所谓的初始化就是:
  /******配置寄存器至普通模式*******/
  write_byte(0x03);
  write_byte(0x02);                               //RESET=0,VREF=2.5V,FRS=0
  write_byte(0x00);
  write_byte(0x00);
  write_byte(0x00);      
上面的程序按硬件电路进行配置后,应该就能看到SDO拉低了,最好用示波器看下波形。
我不是经常上论坛的,有事发EMAIL:hanbao0371@sina.com,这个每天都要用

出0入0汤圆

 楼主| 发表于 2009-11-23 14:19:38 | 显示全部楼层
问题已经解决了。给大家反馈一下结果,是硬件上电顺序问题。
解决办法:调整了上电顺序,单片机先上电,然后再给CS5532上电。
之前的问题,可能是由于CS5532上电过程中,单片机也在上电,对CS5532构成了影响,
导致上电过程过程有问题。

出0入0汤圆

发表于 2013-7-24 23:10:15 | 显示全部楼层
楼主说的问题我的也是,9楼的回答我明天调试一下试试,如果方便的话我们可以讨论一下,我qq7937298276,期待楼主的赐教

出0入0汤圆

发表于 2014-9-24 17:16:39 | 显示全部楼层
标记,CS5532驱动程序.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 18:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表