求助:“CS5532发送转换命令(0x80)后,SDO不变低”的问题
各位大侠,请帮忙分析分析,不胜感激!对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--); } 有用过的朋友请指点指点,着急等待中! 这是我以前写的,调试通过的,你可以看下,如有问题,和我联系吧:hanbao0371@sina.com
/******************************************
Project :读取CS5532的数据,并在LED上显示
*******************************************/
#ifndef_CS5532_
#define_CS5532_
/*********端口定义*********/
#define CS5532_CS PD1 //定义片选端
#define CS5532_SDO PD2 //定义数据输入端
#define CS5532_SDI PD3 //定义数据输出端
#define CS5532_SCLKPD4 //定义移位脉冲端
#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_SCLKPORTD |= BIT(CS5532_SCLK) //置SCLK端为1
#define CLR_SCLKPORTD &=~BIT(CS5532_SCLK) //清SCLK端
/************全局变量定义************/
uchar CS5532_data={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=duan_ma[(uchar)tempf]; //获得整数部分
temp=(ulong)(tempi*100000); //数据放大1000000倍,便于显示小数
for(i=5;i>0;i--)
{
CS5532_data=duan_ma;
temp = temp/10;
}
CS5532_data &= 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 问题好像出现你读CS5532上,读取的时候是读取32位,而且保存的时候是后者24位的数据,
你最好用示波器看下,CS5532在初始化后,是否能观察到SDO被拉低,如果没有,说明你的初始化程序有问题。 感谢hanbao0371 朋友的帮助,有两点问题,请请教一下
1. > 读取的时候是读取32位,而且保存的时候是后者24位的数据,
现在我的问题是,发送完毕0x80(或者0xc0)转换命令之后,SDO一直不等于0,
个人感觉和“读数据的位数”有什么关系呢。
2. > 你最好用示波器看下,CS5532在初始化后,是否能观察到SDO被拉低,如果没有,说明你的初始化程序有问题。
手册上没有提到过初始化之后,SDO会拉低,应该是您个人的经验把,如果是这样子,非常感谢,我可以试试。
再次感谢您的回答。 本人程序:
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 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,这个每天都要用 问题已经解决了。给大家反馈一下结果,是硬件上电顺序问题。
解决办法:调整了上电顺序,单片机先上电,然后再给CS5532上电。
之前的问题,可能是由于CS5532上电过程中,单片机也在上电,对CS5532构成了影响,
导致上电过程过程有问题。 楼主说的问题我的也是,9楼的回答我明天调试一下试试,如果方便的话我们可以讨论一下,我qq7937298276,期待楼主的赐教 标记,CS5532驱动程序.
页:
[1]