正文

AD7705的源程序2008-02-22 22:25:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/niao0311/32872.html

分享到:

------------AD7705头文件开始-------------------#ifndef _AD7705_H#define _AD7705_H//通讯寄存器地址定义#define    WR_SETUP_REG       0x10  //选中写设置寄存器#define    RD_SETUP_REG       0x18  //选中写设置寄存器#define    WR_CLOCK_REG    0x20  //选中写时钟寄存器#define RD_DATA_REG        0x38  //选中数据寄存器读#define    WR_OFFSET_REG     0x60  //选中写offset寄存器#define    RD_OFFSET_REG     0x68  //选中读offset寄存器#define    WR_FULL_REG       0x70  //选中写full scale寄存器#define    RD_FULL_REG       0x78  //选中读full scale寄存器#define    SYS_ZERO_CALI    0x80  //系统零校准模式#define    SYS_FULL_CALI    0xC0  //系统满量程校准模式#define ZERO_CALIBRATION   0x00 //系统零校准#define FULL_CALIBRATION   0x01 //系统满量程校准//CLOCK寄存器设置,无分频,50HZ输出更新速率#define CLOCK_REG_SET   0X04//函数声明void reset_AD7705(void);unsigned char read_AD7705_byte(void);unsigned int  read_AD7705_word(void);unsigned long int read_AD7705_dword(void);void write_AD7705_byte(unsigned char data);void write_AD7705_word(unsigned int data);void write_AD7705_dword(unsigned long int data);void ReadData7705(unsigned int *const pdata);void AD7705_calibration(void);void start_AD7705(void);#endif-----------AD7705主文件开始--------------#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]={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_us(30);}//------------------------------------------------------------------------------------------//函数: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是一个16位AD//------------------------------------------------------------------------------------------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_calibration//功能:根据cali_type的值对AD7705进行系统0校正或系统满量程校正,并将各校正值和校正标志存入//      EEPROM,数据保存为双备份。数据块格式为: 内部0校正值(4byte), 内部满量程校正值(4byte), //         系统0校正值(4byte), 系统满量程校正值(4byte), 系统0校正标志(1byte),系统满量程校正标志//      (1byte),CRC16校验值(2byte),共20byte。//参数:IN - uint8_t board, 0 - 对主板进行校正,1-对副板进行校正//        IN - uint8_t range, 需要校正的量程//      IN - uint8_t cali_type, 校正类型,ZERO_CALIBRATION- 0校正;//           FULL_CALIBRATION - 满量程校正//返回:返回-1表示校准失败,非0表示校正成功,并返回相应的索引值//变量:无//备注:做满量程校正前必须先做零校正//------------------------------------------------------------------------------------------//校准命令格式    //STX    Data Long    Command Code    Parameter    CheckSum    ETX//0x55    数据长度(2)    量程指示    00H/01H        CRC16(2)    0x0D////校准过程中要用到Command[]的数据,所以校准之前要关掉串口接收中断void AD7705_calibration(void){     //记录读取EEPROM的次数     unsigned char readtimes =0;          //记录上位机发送的校准量程类型     unsigned char cali_scale =0;          //读取24位校准系数的临时变量     unsigned long int temp =0;          //临时的校准系数数组,存放格式ZSL、ZSM、ZSH;GSL、GSM、GSH;CRCL、CRCH     //并在校准结束时作为参数传递给TXOUT()函数,发送校准系数给上位机     unsigned char coefficient[8] ={0}; //test[8]={0};          //16位校验和的临时变量     unsigned int crcvalue =0;          AD_CS1;          cali_scale = command[2]; //获取上位机发送的要校准的量程类型            //读取EEPROM的第一份校准系数     eeprom_busy_wait();     eeprom_read_block( &coefficient[0], (void*)(ADDR_EEPROM_1+(cali_scale-1)*10), 8 );     crcvalue = checksum( &coefficient[0], 6 ); //将6个值调用CRC校验函数得到校验     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 ); //将6个值调用CRC校验函数得到校验         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();          //CLOCK寄存器设置,无分频,50HZ输出更新速率     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 );//若将滤波器同步位FSYNC置为1,AD_DRDY信号将不会变低,这里将一直是死循环                   //读OFFSET寄存器         write_AD7705_byte( RD_OFFSET_REG );         temp = read_AD7705_dword();                   if( cali_scale == scale)         {             ZS = temp; //如果是当前量程零校准还要更新ZS             //如果是当前量程的校准,还要将NO_CALI_TYPE赋值为1表示已经经过零校准             //更新上电没有校准时readEEPROM()函数的运行状态             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] )//系统满量程校准     {                  //计算ZS,一定要作强制类型转换,否则将出现错误         temp = (unsigned long int)(coefficient[0]) + (unsigned long int)(coefficient[1])*256              + (unsigned long int)(coefficient[2])*65536;                           //将ZS写入到AD7705的OFFSET寄存器                  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 );//若将滤波器同步位FSYNC置为1,AD_DRDY信号将不会变低,这里将一直是死循环                  //读FULL寄存器         write_AD7705_byte( RD_FULL_REG );         temp = read_AD7705_dword();                  if( cali_scale == scale )         {             GS = temp; //如果是当前量程满量程校准还要更新GS             //如果是当前量程的校准,还要将NO_CALI_TYPE赋值为2表示已经经过零校准             //更新上电没有校准的情况,让readEEPROM()函数退出循环状态             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); //将6个校准值调用CRC校验函数得到校验码          coefficient[6] = (unsigned char)(crcvalue%256);//取校验值的高8位和低8位     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;     }//------------------------------------------------------------------------------------------//函数:start_AD7705//功能:先写offset寄存器,再写full scale寄存器,然后启动7705进行单次转换//参数:uint8_t channel  -- 要进行A/D转换的通道号//      uint8_t cali     -- 是第几次测量,电阻需要测量2次//返回:无//变量:无//备注://------------------------------------------------------------------------------------------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 );//读取数据延时20ms左右,     stop_timer0();}

阅读(5047) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册