huzhiyang 发表于 2013-7-23 19:26

CS5530程序,卡在了while(CS5530_SDO == 1);

#define Write_OFFSET      0x01   //写偏移寄存器
#define Read_OFFSET       0x09   //读偏移寄存器
#define Write_GAIN      0x02   //写增益寄存器
#define Read_GAIN         0x0a   //读增益寄存器
#define Write_CONFIG      0x03   //写配置寄存器
#define Read_CONFIG       0x0b   //读配置寄存器
#define START_SINGLE      0x80   //单次转换
#define START_CONTINUOUS0xc0   //连续转换
#define SYSTEM_OFFSET_CAL 0x85   //执行偏移校准
#define SYSTEM_GAIN_CAL   0x86   //执行增益校准
#define SYNC1             0xff   //串行口初始化序列命令之一
#define SYNC0             0xfe   //串行口初始化序列结束命令
#define NULL_BYTE         0x00   //用来清除端口标志位使得转换器保持在连续转换模式
// Configuration Register
#define STANDBY_MODE      0x00000000   //待机模式
#define SLEEP_MODE      (0x01L<<31)//休眠模式
#define POWER_SAVE_MODE   (0x01L<<30)//节电模式
#define NORMAL_MODE       (0x00L<<29)//正常操作
#define SYSTEM_RESET      (0x01L<<29)//激活一个复位周期 复位后自动清0
#define RESET_STATUS      (0x01L<<28)//复位有效 系统已复位 只读
#define SHORT_INPUTS      (0x00L<<27)//输入正常输入 个通道输入不断接
#define VREF_HIGH         (0x00L<<25)//参考电压 2.5~((VA+)-(VA-))V
#define VREF_LOW          (0x01L<<25)//参考电压 1~2.5V
#define CR_A1_0         (0x00L<<24)
#define CR_A1_1         (0x01L<<24)
#define CR_A0_0         (0x00L<<23)
#define CR_A0_1         (0x01L<<23)
#define LINE_FREQ_60      (0x00L<<19)//滤波数率选择 缺省输入字
#define LINE_FREQ_50      (0x01L<<19)//输出字数率及相应滤波器特性乘以系数5/6
#define DATARATE_100      (0x00L<<11)//字数率 不同位就不同
#define DATARATE_50       (0x01L<<11)
#define DATARATE_25       (0x02L<<11)
#define DATARATE_12P5   (0x03L<<11)
#define DATARATE_6P25   (0x04L<<11)
#define DATARATE_3200   (0x08L<<11)
#define DATARATE_1600   (0x09L<<11)
#define DATARATE_800      (0x0aL<<11)
#define DATARATE_400      (0x0bL<<11)
#define DATARATE_200      (0x0cL<<11)
#define BIPOLAR_MODE      (0x00L<<10)//极性选择双极性模式
#define UNIPOLAR_MODE   (0x01L<<10)//极性选择单极性模式
#define TURN_OFF_300NA    (0x00L<<9)   //不激活电流源
#define TURN_ON_300NA   (0x01L<<9)   //激活电流源300ma
//===========================================================================================
sbit CS5530_CLK=P1^2;               //时钟脚
sbit CS5530_CS=P0^0;                  //片选脚
sbit CS5530_SDO=P1^1;               //数据输出脚
sbit CS5530_SDI=P1^0;               //数据输入脚
#define cs5530_clk_h    CS5530_CLK=1//时钟线拉高
#define cs5530_clk_l    CS5530_CLK=0; //时钟线拉低
#define cs5530_cs_h   CS5530_CS=1   //片选拉高(禁止器件)
#define cs5530_cs_l   CS5530_CS=0   //片选拉低(选中器件)
#define cs5530_in_h   CS5530_SDI=1//MOSI输出1
#define cs5530_in_l   CS5530_SDI=0//MOSI输出0
#define cs5530_out      CS5530_SDO    //读CS5530的输出数据位

bitb_HasGetNewADDat;
bitb_ad_err;
bitb_fangdian;
signed long idata ad_sample_dat;

union LongData {
unsigned long word ;
unsigned char   byte;
};
//==========================================================================================
void delay_ms(unsigned int x)
{
    unsigned int a, b;
    for (a=0; a<x; a++)
{
            for (b=0; b<300;b++)
   ;
}
}
static void delay1()
{
      ;
}
/**********************************************************
*函数名:unsigned char CS5530_Read(void)
*功能:CS5530读8位数据
*说明:
**********************************************************/
unsigned char CS5530_Read(void)
{
unsigned char i;
unsigned char dat=0;
CS5530_SDI=0;
for(i=0;i<8;i++)
{
dat <<= 1;
cs5530_clk_h;
delay1();
cs5530_clk_l;
delay1();
if(CS5530_SDO!= 0)
   dat++;

}

return dat;
}
/**********************************************************
*函数名:unsigned long CS5530_Read_Dword (void)
*功能:CS5530读32位数据
*说明:
**********************************************************/
unsigned long CS5530_Read_Dword(void)
{
    unsigned long return_data;
    return_data=CS5530_Read();
    return_data<<=8;
    return_data+=CS5530_Read();
    return_data<<=8;
    return_data+=CS5530_Read();
    return_data<<=8;
    return_data+=CS5530_Read();
    return_data=return_data>>9;            
    return (return_data);
}
/**********************************************************
*函数名:void CS5530_Write(unsigned char Write_data)
*功能:写8位数据
*说明:unsigned char Write_data:需发送的数据
**********************************************************/
void CS5530_Write(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
         
if(dat & 0x80)
    CS5530_SDI=1;
else
    CS5530_SDI=0;
   cs5530_clk_l;
   delay1();
   cs5530_clk_h;
   delay1();
dat <<= 1;
    }
}
/**********************************************************
*函数名:void CS5530_Write_Dword(unsigned long Write_data)
*功能:写32位数据
*说明:unsigned char Write_data:需发送的数据
**********************************************************/
void CS5530_Write_Dword(unsigned long dat)
{
    union type1
    {
      unsigned char ch;
      unsigned long lon;
    };                                    //定义用于将32位整数转为4个字节的联合体数据结构
    union type1 temp;
    temp.lon= dat;               
    CS5530_Write (temp.ch);            //逐个字节发送数据
    CS5530_Write (temp.ch);
    CS5530_Write (temp.ch);
    CS5530_Write (temp.ch);
}
/**********************************************************
*函数名:void CS5530_Serial_Reset(void)
*功能:
*说明:
**********************************************************/
void CS5530_Serial_Reset(void) //1/
{
    unsigned char i = 18;
    while(i-- )
    {
         CS5530_Write(SYNC1) ;
    }
         CS5530_Write(SYNC0) ;
}

/**********************************************************
*函数名:void CS5530_Set(void)
*功能:CS5530初始化
*说明:
**********************************************************/
void CS5530_Set(void)
{
    unsigned long dat;
    unsigned char read_data;
    unsigned char CS5530_rst;
    delay_ms(100);
    CS5530_Serial_Reset();
    CS5530_Write(Write_CONFIG);      //写配置寄存器
    CS5530_Write_Dword(SYSTEM_RESET) ; //初始化 0x20000000
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    CS5530_Write(Write_CONFIG);      //写配置寄存器
    CS5530_Write_Dword(0x00000000) ; //初始化 0x20000000
    CS5530_Write(Read_CONFIG);
    read_data = CS5530_Read();
    CS5530_rst = read_data;          //配置寄存器有32位,RV在D28位上
    read_data = CS5530_Read();       //后面三个字节不用管
    read_data = CS5530_Read();
    read_data = CS5530_Read();
disp_data_buff_write(1,1,0,16,0);
disp();
    while(CS5530_rst & 0x10)      //如果RV位为1表明复位成功,读配置寄存器后RV自动清0
    {                               //重新读取RV位确保它已经清0
      CS5530_Write(Read_CONFIG);//发读配置寄存器命令
      read_data = CS5530_Read();
      CS5530_rst = read_data;
      read_data = CS5530_Read();
      read_data = CS5530_Read();
      read_data = CS5530_Read();
disp_data_buff_write(2,1,0,16,0);
disp();
    }
   
CS5530_Write(Write_CONFIG);          //发"写配置寄存器"命令
    CS5530_Write_Dword(NORMAL_MODE);    //写配置寄存器清除RS位(CFG_REG=0x00000000),退出复位状态
    _nop_();
    _nop_();
disp_data_buff_write(3,1,0,16,0);
disp();
    CS5530_Write(Write_CONFIG); //写配置寄存器
    CS5530_Write_Dword( NORMAL_MODE + VREF_HIGH + CR_A0_0 + CR_A1_0 + SHORT_INPUTS + LINE_FREQ_60 +DATARATE_200 + BIPOLAR_MODE + TURN_OFF_300NA ) ;
    CS5530_Write(START_CONTINUOUS);    //开始连续转换START_SINGLE
    while(CS5530_SDO == 1);
disp_data_buff_write(4,1,0,16,0);
disp();
    CS5530_SDI = 0;
    CS5530_Write(0x00); //写入空指令,
    dat = CS5530_Read_Dword();
}   

//读取cs5530模数转换结果
unsigned long CS5530_Result (void)
{
    CS5530_Write(NULL_BYTE) ;                   //发出8个时钟信号来清除SDO标志(数据就绪标志?)
    return (unsigned long)(CS5530_Read_Dword());//读取并返回32位结果(24位ADC转换结果加上1个溢出标志和7个无意义的0位)
}

以上是我根据网上的代码综合的,现在程序在CS5530_Set()函数中出不来了,我在里面加上了显示的程序,现在数码管上显示的是“3”,说明程序是卡在了while(CS5530_SDO == 1);    我不明白的是,我都已经设置了连续转换,手册中写道,当用户发送一个执行连续转换的命令时,转换器就会利用配置寄存器中字速率和极性设置参数开始进行连续转换。一旦命令已经发送,串口就会进入数据模式直到一次转换完成。转换完成后,SDO脚会变为低电平0,表明数据已经转换完成,但此处为什么SDO引脚不变低呢?如果是我读写函数写的有问题的话,那复位那个地方就应该卡住啊,还请用过的大侠指点下小弟,感激不尽!!!

孤独泪 发表于 2013-7-23 19:57

#define Write_OFFSET      0x01   //写偏移寄存器
#define Read_OFFSET       0x09   //读偏移寄存器
#define Write_GAIN      0x02   //写增益寄存器
#define Read_GAIN         0x0a   //读增益寄存器
#define Write_CONFIG      0x03   //写配置寄存器
#define Read_CONFIG       0x0b   //读配置寄存器
#define START_SINGLE      0x80   //单次转换
#define START_CONTINUOUS0xc0   //连续转换
#define SYSTEM_OFFSET_CAL 0x85   //执行偏移校准
#define SYSTEM_GAIN_CAL   0x86   //执行增益校准
#define SYNC1             0xff   //串行口初始化序列命令之一
#define SYNC0             0xfe   //串行口初始化序列结束命令
#define NULL_BYTE         0x00   //用来清除端口标志位使得转换器保持在连续转换模式
// Configuration Register
#define STANDBY_MODE      0x00000000   //待机模式
#define SLEEP_MODE      (0x01L<<31)//休眠模式
#define POWER_SAVE_MODE   (0x01L<<30)//节电模式
#define NORMAL_MODE       (0x00L<<29)//正常操作
#define SYSTEM_RESET      (0x01L<<29)//激活一个复位周期 复位后自动清0
#define RESET_STATUS      (0x01L<<28)//复位有效 系统已复位 只读
#define SHORT_INPUTS      (0x00L<<27)//输入正常输入 个通道输入不断接
#define VREF_HIGH         (0x00L<<25)//参考电压 2.5~((VA+)-(VA-))V
#define VREF_LOW          (0x01L<<25)//参考电压 1~2.5V
#define CR_A1_0         (0x00L<<24)
#define CR_A1_1         (0x01L<<24)
#define CR_A0_0         (0x00L<<23)
#define CR_A0_1         (0x01L<<23)
#define LINE_FREQ_60      (0x00L<<19)//滤波数率选择 缺省输入字
#define LINE_FREQ_50      (0x01L<<19)//输出字数率及相应滤波器特性乘以系数5/6
#define DATARATE_100      (0x00L<<11)//字数率 不同位就不同
#define DATARATE_50       (0x01L<<11)
#define DATARATE_25       (0x02L<<11)
#define DATARATE_12P5   (0x03L<<11)
#define DATARATE_6P25   (0x04L<<11)
#define DATARATE_3200   (0x08L<<11)
#define DATARATE_1600   (0x09L<<11)
#define DATARATE_800      (0x0aL<<11)
#define DATARATE_400      (0x0bL<<11)
#define DATARATE_200      (0x0cL<<11)
#define BIPOLAR_MODE      (0x00L<<10)//极性选择双极性模式
#define UNIPOLAR_MODE   (0x01L<<10)//极性选择单极性模式
#define TURN_OFF_300NA    (0x00L<<9)   //不激活电流源
#define TURN_ON_300NA   (0x01L<<9)   //激活电流源300ma
//===========================================================================================
sbit CS5530_CLK=P1^2;               //时钟脚
sbit CS5530_CS=P0^0;                  //片选脚
sbit CS5530_SDO=P1^1;               //数据输出脚
sbit CS5530_SDI=P1^0;               //数据输入脚
#define cs5530_clk_h    CS5530_CLK=1//时钟线拉高
#define cs5530_clk_l    CS5530_CLK=0; //时钟线拉低
#define cs5530_cs_h   CS5530_CS=1   //片选拉高(禁止器件)
#define cs5530_cs_l   CS5530_CS=0   //片选拉低(选中器件)
#define cs5530_in_h   CS5530_SDI=1//MOSI输出1
#define cs5530_in_l   CS5530_SDI=0//MOSI输出0
#define cs5530_out      CS5530_SDO    //读CS5530的输出数据位

bitb_HasGetNewADDat;
bitb_ad_err;
bitb_fangdian;
signed long idata ad_sample_dat;

union LongData {
unsigned long word ;
unsigned char   byte;
};
//==========================================================================================
void delay_ms(unsigned int x)
{
    unsigned int a, b;
    for (a=0; a<x; a++)
{
            for (b=0; b<300;b++)
   ;
}
}
static void delay1()
{
      ;
}
/**********************************************************
*函数名:unsigned char CS5530_Read(void)
*功能:CS5530读8位数据
*说明:
**********************************************************/
unsigned char CS5530_Read(void)
{
unsigned char i;
unsigned char dat=0;
CS5530_SDI=0;
for(i=0;i<8;i++)
{
dat <<= 1;
cs5530_clk_h;
delay1();
cs5530_clk_l;
delay1();
if(CS5530_SDO!= 0)
   dat++;

}

return dat;
}
/**********************************************************
*函数名:unsigned long CS5530_Read_Dword (void)
*功能:CS5530读32位数据
*说明:
**********************************************************/
unsigned long CS5530_Read_Dword(void)
{
    unsigned long return_data;
    return_data=CS5530_Read();
    return_data<<=8;
    return_data+=CS5530_Read();
    return_data<<=8;
    return_data+=CS5530_Read();
    return_data<<=8;
    return_data+=CS5530_Read();
    return_data=return_data>>9;            
    return (return_data);
}
/**********************************************************
*函数名:void CS5530_Write(unsigned char Write_data)
*功能:写8位数据
*说明:unsigned char Write_data:需发送的数据
**********************************************************/
void CS5530_Write(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
         
if(dat & 0x80)
    CS5530_SDI=1;
else
    CS5530_SDI=0;
   cs5530_clk_l;
   delay1();
   cs5530_clk_h;
   delay1();
dat <<= 1;
    }
}
/**********************************************************
*函数名:void CS5530_Write_Dword(unsigned long Write_data)
*功能:写32位数据
*说明:unsigned char Write_data:需发送的数据
**********************************************************/
void CS5530_Write_Dword(unsigned long dat)
{
    union type1
    {
      unsigned char ch;
      unsigned long lon;
    };                                    //定义用于将32位整数转为4个字节的联合体数据结构
    union type1 temp;
    temp.lon= dat;               
    CS5530_Write (temp.ch);            //逐个字节发送数据
    CS5530_Write (temp.ch);
    CS5530_Write (temp.ch);
    CS5530_Write (temp.ch);
}
/**********************************************************
*函数名:void CS5530_Serial_Reset(void)
*功能:
*说明:
**********************************************************/
void CS5530_Serial_Reset(void) //1/
{
    unsigned char i = 18;
//此处复位给n个高电平,建议15,31,
    while(i-- )
    {
         CS5530_Write(SYNC1) ;
    }
         CS5530_Write(SYNC0) ;
}

/**********************************************************
*函数名:void CS5530_Set(void)
*功能:CS5530初始化
*说明:
**********************************************************/
void CS5530_Set(void)
{
    unsigned long dat;
    unsigned char read_data;
    unsigned char CS5530_rst;
    delay_ms(100);
//不知道哪儿调用这个程序,clk脚要开始是低电平,之后cs脚低电平
    CS5530_Serial_Reset();
//这里要加几个ms延时

    CS5530_Write(Write_CONFIG);      //写配置寄存器
    CS5530_Write_Dword(SYSTEM_RESET) ; //初始化 0x20000000
//复位之后要加入延时,几个Nop太少
    _nop_();
    _nop_();
    _nop_();
    _nop_();
    CS5530_Write(Write_CONFIG);      //写配置寄存器
    CS5530_Write_Dword(0x00000000) ; //初始化 0x20000000
    CS5530_Write(Read_CONFIG);
    read_data = CS5530_Read();
    CS5530_rst = read_data;          //配置寄存器有32位,RV在D28位上
    read_data = CS5530_Read();       //后面三个字节不用管
    read_data = CS5530_Read();
    read_data = CS5530_Read();
disp_data_buff_write(1,1,0,16,0);
disp();
    while(CS5530_rst & 0x10)      //如果RV位为1表明复位成功,读配置寄存器后RV自动清0
    {                               //重新读取RV位确保它已经清0
      CS5530_Write(Read_CONFIG);//发读配置寄存器命令
      read_data = CS5530_Read();
      CS5530_rst = read_data;
      read_data = CS5530_Read();
      read_data = CS5530_Read();
      read_data = CS5530_Read();
disp_data_buff_write(2,1,0,16,0);
disp();
    }
   
CS5530_Write(Write_CONFIG);          //发"写配置寄存器"命令
    CS5530_Write_Dword(NORMAL_MODE);    //写配置寄存器清除RS位(CFG_REG=0x00000000),退出复位状态
    _nop_();
    _nop_();
disp_data_buff_write(3,1,0,16,0);
disp();
    CS5530_Write(Write_CONFIG); //写配置寄存器
    CS5530_Write_Dword( NORMAL_MODE + VREF_HIGH + CR_A0_0 + CR_A1_0 + SHORT_INPUTS + LINE_FREQ_60 +DATARATE_200 + BIPOLAR_MODE + TURN_OFF_300NA ) ;
    CS5530_Write(START_CONTINUOUS);    //开始连续转换START_SINGLE
    while(CS5530_SDO == 1);
disp_data_buff_write(4,1,0,16,0);
disp();
    CS5530_SDI = 0;
    CS5530_Write(0x00); //写入空指令,
    dat = CS5530_Read_Dword();
}   

//读取cs5530模数转换结果
unsigned long CS5530_Result (void)
{
    CS5530_Write(NULL_BYTE) ;                   //发出8个时钟信号来清除SDO标志(数据就绪标志?)
    return (unsigned long)(CS5530_Read_Dword());//读取并返回32位结果(24位ADC转换结果加上1个溢出标志和7个无意义的0位)
}


先出去散步,回来在看

孤独泪 发表于 2013-7-23 20:54

初始化之后连续转换,你就一直去判断SDO脚,我没有这样尝试过。
我一般结构是
main()
{
AdSet();
while(TRUE)
{
   sdo = 1;
   nop; //若干个
   if (sdo==0)
   {
    WriteByteToCs5530(0x00);   
    da = ReadWordFromCs5530();
   }   
}
}

huzhiyang 发表于 2013-7-23 21:12

孤独泪 发表于 2013-7-23 20:54 static/image/common/back.gif
初始化之后连续转换,你就一直去判断SDO脚,我没有这样尝试过。
我一般结构是
main()


根据手册里写到,复位后芯片寄存器的复位值默认值为:
配置寄存器: 00000000(H)
偏移寄存器: 00000000(H)
增益寄存器: 01000000(H)
我现在在程序中加入了如下代码:
CS5530_Write(Read_GAIN);          //读增益寄存器
GAIN = CS5530_Read_Dword();
_nop_();
disp_data_buff_write(GAIN,1,0,16,0);
disp();
delay_ms(5000);

CS5530_Write(Read_OFFSET);      //读偏移寄存器
OFFSET = CS5530_Read_Dword();
_nop_();
disp_data_buff_write(OFFSET,1,0,16,0);
disp();
delay_ms(5000);

CS5530_Write(Write_CONFIG);          //发"写配置寄存器"命令
    CS5530_Write_Dword(NORMAL_MODE);    //写配置寄存器清除RS位(CFG_REG=0x00000000),退出复位状态
    _nop_();
    _nop_();
disp_data_buff_write(3,1,0,16,0);
disp();

但是显示的结果是: 0000FFFFFF(H)
不知道这是什么问题

huzhiyang 发表于 2013-7-23 22:35

孤独泪 发表于 2013-7-23 20:54 static/image/common/back.gif
初始化之后连续转换,你就一直去判断SDO脚,我没有这样尝试过。
我一般结构是
main()


我看数据手册里面26面有一个转换数据输出描述, 这个像是一个寄存器,请问是一个寄存器吗?我们在读转换完的数据时,都是到哪里去读的呢?
手册上只写了先发送0x00,再去读,却没说去哪里读?

zhangjc101 发表于 2013-7-24 11:26

串行口初始化是发15个0xFF和1个0xFE,初始化完成后等芯片内部复位完成后,发送命令要求按单次转换或连续转换,然后等SDO变低,发送8位全零,接收四个字节32位转换结果,看一下芯片的说明吧,单次转换命令是0x80,转换转换命令是0xC0 ,内部增益等其它功能按默认,先运行起来,然后再说。

zhangjc101 发表于 2013-7-24 11:33

当然复位后应该先设定配置寄存器中的输出字速率(AD转换频率)和极性设置参数,然后发送开始转换命令。是单次或者是连续。判断SDO是否为低采用while方式没错,错的可能是设置配置寄存器和转换命令,你的代码太长,无法仔细阅读,只给出我的看法,仅供参考。

889 发表于 2014-5-30 11:31

有没有写好的完整的程序发给我修改用一下

lucky4457 发表于 2015-8-6 10:46

我也遇到了同样的问题,楼主解决了吗?

奋斗青春 发表于 2017-5-10 16:59

SPI时序、检测SPI口的问题

liuningzhuag 发表于 2019-11-20 23:30

楼主解决了吗,我这卡在这里了

huzhiyang 发表于 2020-5-21 13:58

不好意思,我后来从那家公司离职了,就没更新帖子了。
页: [1]
查看完整版本: CS5530程序,卡在了while(CS5530_SDO == 1);