title
收藏本站
联系站长
关于本站
首页 信息发布 产品宣传 论坛交流 学习文章 技术人生 项目源码 技术资料 人才收录
 今天是: 2010年7月10日 星期 六
欢迎光临!单片机群号:25930265(新) 71062262 21829895 64584393 26583231(只限加一群)  
热门文章推荐


当前位置:首页>>>单片机学习文章>> 16位自校正AD芯片AD7705驱动源码
16位自校正AD芯片AD7705驱动源码
作者:md9给他留言 [转载] 字体:
发表于:
2009-08-14 22:48:36
   AD7705应用注意要点: 
   (1) DRDY逻辑不要搞反,高电平时等待转换状态,低电平为可以读取转换数据 
   (2) 系统校准时输入信号要大于所选量程的4/5,否则校准不到32767。 
   (3) 校准时要等待一定的时间,读取数据也一样,不能超过转换速率。 
   (4) 一般的应用只要内部校准,这个很简单,只要初始化就可以。如果测量范围不是芯片的范围,可以通过系统校准来实现,满量程校准电压要大于量程的4/5 

#include <util/delay.h> 
#include <avr/eeprom.h> 
#include "ad7705.h" 
#include "main.h" 
#include "crc16.h" 
#include "Usart.h" 

//针对四个量程的设置寄存器的设置内容 
//(1)对于单极性V级别输入0-5V、0-20mA、0-10V这三个量程,输入范围为0-2V,无极性,增益为1,缓冲模式--0-2V 
//(2)对于双极性V级别输入+-2.5V、+-5V这两个量程,输入范围为+-1V,双极性,增益为2,缓冲模式--+-2V 
//(3)对于双精度mV级别输入+-500mV,增益为4,双极性,缓冲模式--+-2V 
//(4)对双精度mV级别+-50mV,增益为32,双极性,缓冲模式--+-1.6V 
//------MD1(0)   MD0(0)   G2(0)   G1(0)   G0(0)   B/U(0)   BUF(0)   FSYNC(0)--------------------------//    
const unsigned char text_of_setup[4]={0X04,0X08,0X10,0X28}; //非缓冲模式,数字滤波同步 
//const unsigned char text_of_setup[4]={0X06,0X0A,0X12,0X2A}; //缓冲模式,数字滤波同步 

extern volatile unsigned char  command[7];   //校准命令全局数组 
extern volatile unsigned char  scale;        //记录系统量程 
extern volatile unsigned char  NO_CALI_TYPE; //未校准类型 
extern volatile unsigned long  int ZS,GS;   //当前量程的校准系数 
extern volatile unsigned char  time_count;   //超时标志 

//---------------------------------------------------------------------------- 
//函数:reset_AD7705 
//功能:AD7705串行接口失步后将其复位。复位后要延时500us再访问 
//参数:无 
//返回:无 
//变量:无 
//备注:无 
//---------------------------------------------------------------------------- 
void reset_AD7705(void) 

 unsigned char i; 
  
 AD_DIN1; 
 for( i=0; i<36; i++ ) 
 { 
 AD_CLK0; 
 asm("nop"); 
 asm("nop"); 
                      asm("nop");   
 AD_CLK1; 
 asm("nop"); 
 asm("nop"); 
                       asm("nop");   
 } 
  
 _delay_ms(1); 


//------------------------------------------------------------------------------------------ 
//函数:read_AD7705_byte 
//功能:从AD7705读一个字节的数据 
//参数:无 
//返回:读到的一字节数据 
//变量:无 
//备注:无 
//------------------------------------------------------------------------------------------ 
unsigned char read_AD7705_byte(void) 

 unsigned char data = 0; 
 unsigned char i = 0; 
  
 for( i=0; i<8; i++ ) 
 { 
 data <<= 1; 
 AD_CLK0;   
 asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 if(AD_DOUT) 
 { 
   data++; 
 } 
                      AD_CLK1;   
 asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 } 
  
 return data; 


//------------------------------------------------------------------------------------------ 
//函数:read_AD7705_word 
//功能:从AD7705读一个字的数据,共16bit 
//参数:无 
//返回:读到的一字节数据 
//变量:无 
//备注:无 
//------------------------------------------------------------------------------------------ 
unsigned int read_AD7705_word(void) 

 unsigned int data = 0; 
 unsigned char i = 0; 
  
 for( i=0; i<16; i++ ) 
 { 
 data <<= 1; 
 AD_CLK0;   
 asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 if(AD_DOUT) 
 { 
    data++; 
 } 
                      AD_CLK1;   
 asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 }      
  
 return data; 



//------------------------------------------------------------------------------------------ 
//函数:read_AD7705_dword 
//功能:从AD7705读一个24的数据 
//参数:无 
//返回:读到的一字节数据 
//变量:无 
//备注:AD7705是一个24位AD,选定刷新频率在16.7HZ下,有效位是19位,暂时读出全部24位数据 
//------------------------------------------------------------------------------------------ 
unsigned long int read_AD7705_dword(void) 

 unsigned long data = 0; 
 unsigned char i = 0; 
  
 for( i=0; i<24; i++ ) 
 { 
 data <<= 1; 
 AD_CLK0;   
 asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 if(AD_DOUT) 
 { 
    data++; 
 } 
                      AD_CLK1;   
 asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 } 
      
 return data; 



//------------------------------------------------------------------------------------------ 
//函数:write_AD7705_byte 
//功能:往AD7705写8位数据 
//参数:IN - uint8_t  data,要写入AD7705的数据 
//返回:无 
//变量:无 
//备注:无 
//------------------------------------------------------------------------------------------ 
void write_AD7705_byte(unsigned char data) 

 for(unsigned char i=0; i<8; i++) 
 { 
 AD_CLK0; 
 if(data&0x80) 
 AD_DIN1; 
 else 
 AD_DIN0;   
                      asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 AD_CLK1;   
 asm("nop"); 
                      asm("nop"); 
 asm("nop"); 
 data <<= 1; 
 } 
  
 AD_DIN1;   


//------------------------------------------------------------------------------------------ 
//函数:write_AD7705_dword 
//功能:往AD7705写24位数据,因为AD7705是24位的器件 
//参数:IN - int32_t  data,要写入AD7705的数据 
//返回:无 
//变量:无 
//备注:无 
//------------------------------------------------------------------------------------------ 
void write_AD7705_dword(unsigned long int data) 

for(unsigned char i = 0; i<24; i++) 

 AD_CLK0; 
 if(data&0x800000) 
 AD_DIN1; 
 else 
 AD_DIN0;   
                      asm("nop"); 
 asm("nop"); 
 asm("nop"); 
 AD_CLK1;   
 asm("nop"); 
                       asm("nop"); 
 asm("nop"); 
 data <<= 1; 
 } 
  
 AD_DIN1; 


//-------------------------------------------------------------------------- 
//-------------------------读取AD7705转换数据函数-------------------------- 
//入口参数:指向main()主函数定义的ad_data变量的常量指针 
//-------------------------------------------------------------------------- 
void ReadData7705(unsigned int *const pdata) 

     unsigned int data=0, fiter[5]={0}; 
 unsigned long int temp=0; 
 unsigned char i=0, sort_flag=1; 
      
 AD_CS0; 
 _delay_us(5); 
  
 start_AD7705(); 
  
 for( i=0; i<5; i++ ) 
 { 
               start_timer0(); 
     _delay_ms(2); 
     while( AD_DRDY ) 
     { 
     if( time_count >= time_read_data ) 
     { 
     stop_timer0(); 
     AD_CS1; 
     return; 
     } 
 } 
     stop_timer0(); 
  
               write_AD7705_byte( RD_DATA_REG ); 
               fiter[i] = read_AD7705_word(); 
 }   
 AD_CS1; 
  
 sort_flag = 1; 
 while( sort_flag ) 
 { 
     sort_flag = 0; 
     for( i=0; i<4; i++ ) 
 { 
     if( fiter[i] > fiter[i+1] ) 
 { 
     data = fiter[i]; 
 fiter[i] = fiter[i+1]; 
 fiter[i+1] = data; 
 sort_flag = 1; 
 } 
 }   
 } 
  
 temp = ( (unsigned long int)fiter[1] + (unsigned long int)fiter[2]  
          + (unsigned long int)fiter[3] )/3; 
  
 data = (unsigned int)temp; 
      
           if( (data<0xfff0) && (data&0x000f)>0x0008 ) 
 { 
     data >>= 4; 
 data++; 
 } 
 else 
 { 
     data >>= 4; 
 } 
  
     if( 1 != scale ) 
     {    
 data -= 0x0800;   
     } 
   
     *pdata = data & 0x0fff;   


//--------------------------------------------------------------------------------------- 
//校准命令格式     
//STX Data Long Command Code Parameter CheckSum ETX 
//0x55 数据长度(2) 量程指示 00H/01H     CRC16(2) 0x0D 

void AD7705_calibration(void) 

       unsigned char readtimes =0; 
  
 unsigned char cali_scale =0; 
      
  unsigned long int temp =0; 
  
  unsigned char coefficient[8] ={0}; //test[8]={0}; 
      
 //16位校验和的临时变量 
 unsigned int crcvalue =0; 
  
 AD_CS1;   
  
 cali_scale = command[2]; //获取上位机发送的要校准的量程类型 
    
      eeprom_busy_wait(); 
     eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_1+(cali_scale-1)*10), 8 ); 
     crcvalue = checksum( &coefficient[0], 6 );  
 if( (coefficient[7]*256+coefficient[6]) != crcvalue ) 
 { 
              readtimes++; 
 } 
  
 if( 1 == readtimes ) 
 { 
     eeprom_busy_wait(); 
                eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_2+(cali_scale-1)*10), 8 ); 
               crcvalue = checksum( &coefficient[0], 6 ); // 
     if( (coefficient[7]*256+coefficient[6]) != crcvalue ) 
     { 
     readtimes++;   
     } 
 } 
  
 if( 2 == readtimes ) 
 { 
     eeprom_busy_wait(); 
         eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_3+(cali_scale-1)*10), 8 );          
 } 
      
 ADDR409_MASK;    
 AD_CS0; 
           _delay_us(5); 
 reset_AD7705(); 
  
 write_AD7705_byte( WR_CLOCK_REG ); 
 write_AD7705_byte( CLOCK_REG_SET ); 
      
 if( ZERO_CALIBRATION == command[3] ) //校准命令为零校准 
 { 
     write_AD7705_byte( WR_SETUP_REG ); 
     write_AD7705_byte( text_of_setup[cali_scale-1] | SYS_ZERO_CALI); 
  
 //等待校准完成 
 start_timer0(); 
 while( time_count < time_sys_cali ); 
 stop_timer0(); 
  
 while( AD_DRDY ); 
   
 //读OFFSET寄存器 
 write_AD7705_byte( RD_OFFSET_REG ); 
 temp = read_AD7705_dword(); 
   
 if( cali_scale == scale) 
 { 
     ZS = temp;                    NO_CALI_TYPE = NO_FULL_CALIBRATION; 
 }   
  
 coefficient[0] = (unsigned char)( temp%256 ); 
 coefficient[1] = (unsigned char)( (temp/256)%256 ); 
 coefficient[2] = (unsigned char)( (temp/65536)%256 ); 
 } 
     else if( FULL_CALIBRATION == command[3] ) 
     { 
      
   temp = (unsigned long int)(coefficient[0]) + (unsigned long int)(coefficient[1])*256 
      + (unsigned long int)(coefficient[2])*65536;   
    
     write_AD7705_byte( WR_OFFSET_REG ); 
     write_AD7705_dword( temp );   
  
    write_AD7705_byte( WR_SETUP_REG ); 
     write_AD7705_byte( text_of_setup[cali_scale-1] | SYS_FULL_CALI );   
      
 //等待校准完成 
 start_timer0(); 
 while( time_count < time_sys_cali ); 
 stop_timer0(); 
  
 while( AD_DRDY );//          
 //读FULL寄存器 
 write_AD7705_byte( RD_FULL_REG ); 
 temp = read_AD7705_dword(); 
  
 if( cali_scale == scale ) 
 { 
     GS = temp;  
                          NO_CALI_TYPE = ALREADY_CALIBRATION;              
 }   
  
 coefficient[3] = (unsigned char)( temp%256 ); 
 coefficient[4] = (unsigned char)( (temp/256)%256 ); 
 coefficient[5] = (unsigned char)( (temp/65536)%256 ); 
 } 
     else 
     { 
     AD_CS1; 
 _delay_us(5); 
 return; 
 } 
  
     AD_CS1; 
 _delay_us(5); 
       
 crcvalue = checksum(&coefficient[0],6);  
 coefficient[6] = (unsigned char)(crcvalue%256);// 
            coefficient[7] = (unsigned char)(crcvalue/256);  
      
      eeprom_busy_wait(); 
     eeprom_write_block( &coefficient[0], (void*)(ADDR_EEPROM_1+(cali_scale-1)*10), 8 ); 
  
      eeprom_busy_wait(); 
     eeprom_write_block( &coefficient[0], (void*)(ADDR_EEPROM_2+(cali_scale-1)*10), 8 );   
      
 eeprom_busy_wait(); 
 eeprom_write_block( &coefficient[0], (void*)(ADDR_EEPROM_3+(cali_scale-1)*10), 8 ); 
  
     Txout( &coefficient[0] );//输出校准数据给上位机 
  
 return;   



// 
void start_AD7705(void) 

     reset_AD7705(); 
      
 //写OFFSET寄存器 
 write_AD7705_byte( WR_OFFSET_REG ); 
 write_AD7705_dword( ZS ); 
  
 //写满量程校准寄存器 
 write_AD7705_byte( WR_FULL_REG ); 
 write_AD7705_dword( GS ); 
  
 //CLOCK寄存器设置,无分频,50HZ输出更新速率 
 write_AD7705_byte( WR_CLOCK_REG ); 
 write_AD7705_byte( CLOCK_REG_SET ); 
  
 //写设置寄存器 
 write_AD7705_byte( WR_SETUP_REG ); 
 write_AD7705_byte( text_of_setup[scale-1] ); 
  
 start_timer0(); 
 while( time_count < time_read_data ); 
 stop_timer0(); 

(本文引自www.mcujl.com/article.asp?conID=432)


---------------------------------------------------------------------------------------------------
[打印文章] [关闭本页] [返回顶部]
本网站部分资料转自网上,如有侵权请来信告明,我们会尽快删除  | 网站地图
Copyright @ 2007-2010 深圳单片机交流网.版权所有
网站创办者:詹长亮,周发辉,李林盛
网站支持:zcl843@163.com QQ:380476830 13723787271詹长亮