今天在测试拉力传感器,调校后,发现拉力值还是零。查看AD采样值,结果如图:
先不去分析为啥是零,只看AD采样数据就不对,怎么会偏差这么大,而且有极大值和极小值。
驱动是同事写的,目前已经不负责这个项目了,我只能一点点来看手册调试。
一、AD7797引脚
引脚图,如下图:
注:和通信相关的就是标注的几个引脚,单个芯片(CS可以一直拉低,表示一直选中,不建议这么做)。DOUT/RDY为低表示
转换完成,数据读走或者在数据更新之前为高(数据跟新完后为低)。
时序图:
二、复位
AD7797有上电复位和软件复位。
说的很清楚了,DIN引脚保持至少32个时钟周期,则复位;复位后,经过500us间隔
才能和AD7797通信。
void reset_Ad7797(void)
{
uint8_t i=0;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
AD_DIN_HIGH;
for(i = 0; i < 36; i++)
{
AD_SCLK_LOW;
//100ns
AD_SCLK_HIGH;
//100ns
}
//AD_CS_HIGH;
//80nS
//__NOP();
)
//500us
delay(300);
}
三、读写寄存器
AD7797怎么读写寄存,怎么配置,请看数据手册,这里只讲大概思路。
(数据传输的时候,先传输高字节的高bit)
COMMUNICATION REGISTER
所以有的后续操作,都需要先操作通信寄存器。
CR7写0,可以操作本寄存器;CR6写0,代表后续是写操作;CR6写1,代表后续是读操作;RS2-RS0表示后续操作寄存器地址。
STATUS REGISTER
MODE REGISTER
转换模式有两种:单次转换模式和连续转换模式;转换完后,OUT/RDY为低;
校准模式有三种:内准基准零点校准,系统零点校准和系统满量程校准(系统校准需要硬件支持)。
CONFIGURATION REGISTER
读写时候,按着时序图:
1)写入数据:MCU低电平改变;AD7797高电平读取;
2)读取数据:AD7797电平输出;MCU高电平读取;
测试ID寄存器,发现读取是0x5A,芯片没有焊接错误,只能在时序上看:
最后一个Bit在下降沿变低,查看时序图:
最后一个Bit要求上升沿后10ns读取,反应没这么快;下降沿后80ns数据就稳定了,而读取IO需要百ns级,因此
改成下降沿读取,测试成功。
void write_8bit(uint8_t chAddress,uint8_t writedata)
{
U8 i;
union{
uint8_t chCRBD[2];
struct{
uint8_t :2;
uint8_t Cread :1;
uint8_t chRS :3;
uint8_t RW :1;
uint8_t WEN :1;
};
}tCRBD = {0};
tCRBD.chCRBD[0] = 0;
tCRBD.chCRBD[1] = writedata;
tCRBD.WEN = 0;
tCRBD.RW = 0;
tCRBD.chRS= chAddress;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
for(i = 0; i < 16; i++)
{
AD_SCLK_LOW;
//100ns
if(tCRBD.chCRBD[i>>3] & 0x80){
AD_DIN_HIGH;
}else{
AD_DIN_LOW;
}
AD_SCLK_HIGH;
//100ns
tCRBD.chCRBD[i>>3] = tCRBD.chCRBD[i>>3] << 1;
}
//AD_CS_HIGH;
//80nS
)
AD_DIN_HIGH;
}
void write_16bit(uint8_t chAddress,uint16_t writedata)
{
U8 i;
union{
uint8_t chCRBD[3];
struct{
uint8_t :2;
uint8_t Cread :1;
uint8_t chRS :3;
uint8_t RW :1;
uint8_t WEN :1;
};
}tCRBD = {0};
tCRBD.chCRBD[0] = 0;
tCRBD.chCRBD[1] = (writedata>>8) & 0x00FF;
tCRBD.chCRBD[2] = writedata & 0x00FF;
tCRBD.WEN = 0;
tCRBD.RW = 0;
tCRBD.chRS= chAddress;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
for(i = 0; i < 24; i++)
{
AD_SCLK_LOW;
//100ns
if(tCRBD.chCRBD[i>>3] & 0x80){
AD_DIN_HIGH;
}else{
AD_DIN_LOW;
}
AD_SCLK_HIGH;
//100ns
tCRBD.chCRBD[i>>3] = tCRBD.chCRBD[i>>3] << 1;
}
//AD_CS_HIGH;
//80nS
)
AD_DIN_HIGH;
}
void write_24bit(uint8_t chAddress,uint32_t writedata)
{
U8 i;
union{
uint8_t chCRBD[4];
struct{
uint8_t :2;
uint8_t Cread :1;
uint8_t chRS :3;
uint8_t RW :1;
uint8_t WEN :1;
};
}tCRBD = {0};
tCRBD.chCRBD[0] = 0;
tCRBD.chCRBD[1] = (writedata>>16) & 0x000000FF;
tCRBD.chCRBD[2] = (writedata>>8) & 0x000000FF;
tCRBD.chCRBD[3] = writedata & 0x000000FF;
tCRBD.WEN = 0;
tCRBD.RW = 0;
tCRBD.chRS= chAddress;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
for(i = 0; i < 32; i++)
{
AD_SCLK_LOW;
//100ns
if(tCRBD.chCRBD[i>>3] & 0x80){
AD_DIN_HIGH;
}else{
AD_DIN_LOW;
}
AD_SCLK_HIGH;
//100ns
tCRBD.chCRBD[i>>3] = tCRBD.chCRBD[i>>3] << 1;
}
//AD_CS_HIGH;
//80nS
)
AD_DIN_HIGH;
}
uint8_t read_8bit(uint8_t chAddress)
{
uint8_t readdata = 0;
uint8_t i;
union{
uint8_t chCRBD;
struct{
uint8_t :2;
uint8_t Cread :1;
uint8_t chRS :3;
uint8_t RW :1;
uint8_t WEN :1;
};
}tCRBD = {0};
tCRBD.chCRBD= 0;
tCRBD.WEN = 0;
tCRBD.RW = 1;
tCRBD.chRS= chAddress;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
for(i = 0; i < 8; i++)
{
AD_SCLK_LOW;
//100ns
if(tCRBD.chCRBD & 0x80){
AD_DIN_HIGH;
}else{
AD_DIN_LOW;
}
AD_SCLK_HIGH;
//100ns
tCRBD.chCRBD = tCRBD.chCRBD<<1;
}
AD_DIN_HIGH;
for(i = 0; i < 8; i++)
{
AD_SCLK_LOW;
//100ns
readdata = readdata << 1;
if(AD_DOUT){
readdata += 1;
}
AD_SCLK_HIGH;
//100ns
}
//AD_CS_HIGH;
//80nS
)
return readdata;
}
uint16_t read_16bit(uint8_t chAddress)
{
uint16_t readdata = 0;
uint8_t i;
union{
uint8_t chCRBD;
struct{
uint8_t :2;
uint8_t Cread :1;
uint8_t chRS :3;
uint8_t RW :1;
uint8_t WEN :1;
};
}tCRBD = {0};
tCRBD.chCRBD= 0;
tCRBD.WEN = 0;
tCRBD.RW = 1;
tCRBD.chRS= chAddress;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
for(i = 0; i < 8; i++)
{
AD_SCLK_LOW;
//100ns
if(tCRBD.chCRBD & 0x80){
AD_DIN_HIGH;
}else{
AD_DIN_LOW;
}
AD_SCLK_HIGH;
//100ns
tCRBD.chCRBD = tCRBD.chCRBD<<1;
}
AD_DIN_HIGH;
for(i = 0; i < 16; i++)
{
AD_SCLK_LOW;
//100ns
readdata = readdata << 1;
if(AD_DOUT){
readdata += 1;
}
AD_SCLK_HIGH;
//100ns
}
//AD_CS_HIGH;
//80nS
)
return readdata;
}
uint32_t read_24bit(uint8_t chAddress)
{
uint32_t readdata = 0;
uint8_t i;
union{
uint8_t chCRBD;
struct{
uint8_t :2;
uint8_t Cread :1;
uint8_t chRS :3;
uint8_t RW :1;
uint8_t WEN :1;
};
}tCRBD = {0};
tCRBD.chCRBD= 0;
tCRBD.WEN = 0;
tCRBD.RW = 1;
tCRBD.chRS= chAddress;
SAFE_ATOM_CODE(
//AD_CS_LOW;
//80nS
for(i = 0; i < 8; i++)
{
AD_SCLK_LOW;
//100ns
if(tCRBD.chCRBD & 0x80){
AD_DIN_HIGH;
}else{
AD_DIN_LOW;
}
AD_SCLK_HIGH;
//100ns
tCRBD.chCRBD = tCRBD.chCRBD<<1;
}
AD_DIN_HIGH;
for(i = 0; i < 24; i++)
{
AD_SCLK_LOW;
//100ns
readdata = readdata << 1;
if(AD_DOUT){
readdata += 1;
}
AD_SCLK_HIGH;
//100ns
}
//AD_CS_HIGH;
//80nS
)
return readdata;
}
四、读取数据
1、初始化
void Init_ad7797(void)
{
unsigned char id = 0;
unsigned int con= 0;
//复位
reset_Ad7797();
//读取复位状态
while(1){
if(0x08 == (read_8bit(AD7797_SR) & 0x08)){
break;
}
}
//校准
sys_calibration();
//读取ID
while(1){
if(0x5B == read_8bit(AD7797_IDR)){
break;
}
}
//设置模式
Ad7797_Ini();
}
校准:
void sys_calibration(void)
{
//内部零点校准
write_16bit(AD7797_MR,0x8009);
while(0x00 != (read_8bit(AD7797_SR) & 0x80));
//系统零点校准
//write_16bit(AD7797_MR,0xC009);
//系统满量程校准
//write_16bit(AD7797_MR,0xE009);
}
设置模式:
void Ad7797_Ini(void)
{
// write_16bit(AD7797_MR,0x0710);
// while(1){
// if(0x0710 == read_16bit(AD7797_MR)){
// break;
// }
// }
while(1){
write_16bit(AD7797_MR,0x200A);
if(0x200A == read_16bit(AD7797_MR)){
break;
}
}
}
读取数据流程:
单词模式:
write_16bit(AD7797_MR,0x200A);//启动转换(每次转换完成后,都要从新启动)
等待转换完成,DOUT/RDY引脚边变低
读取数据:
read_24bit(AD7797_DR)
连续模式:
write_16bit(AD7797_MR,0x000A);//配置模式(启动一次就行)
等待转换完成,DOUT/RDY引脚边变低
读取数据:
read_24bit(AD7797_DR)
采样数据:
2021.04.30
昨天把CS一直使能的驱动调试没有问题了,同事说不建议这样用,还是要启用CS,于是今天又把CS使能了,但是发现一个奇怪的问题,
就是AD一直读取不到数据,查看是读取不到DOUT/RDY拉低,肯定不是驱动函数的事,只能从时序着手了。查看单词读取时序:
启动转换后,等待转换期间,CS要保持低电平,修改逻辑后,测试OK。
下图是连续转换模式,需要CS一直使能: