当前位置:首页 > 单片机 > 单片机
[导读]------------AD7705头文件开始-------------------#ifndef _AD7705_H #define _AD7705_H //通讯寄存器地址定义 #define WR_SETUP_REG 0x10 //选中写设置寄存器 #define RD_SETUP

------------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
#include

#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();
}

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

关注、星标公众号,直达精彩内容整理:李肖遥Qt许可证Qt有两个许可证:LGPL和商业协议。这两个协议在现在的Qt版本中的代码是完全一致的(潜在含义是,Qt的早期版本,商业版的Qt通常包含有一些开源版本所没有的库,比如Qt...

关键字: 开源 源程序

曾经参与过公司的bpp项目,就是bluetooth print profile。 由于使用了hpijs的开源包,但是是C++的。 由于C++解释器比C语言解释器占用的存储空间要大500k左右。 为了节省有限的存储空间,降...

关键字: C语言 源程序

C++解释器比C语言解释器占用的存储空间要大,想要在某些特定场合兼容C++代码,同时为了节省有限的存储空间,降低成本,也为了提高效率,将用C++语言写的源程序用C语言改写是很有必要的。 C++与C区别最大的就是C++中的...

关键字: C语言 源程序 C++

网站安全性是网站运营的基础,现在很多企业在建站的时候会使用到快源程序,开源程序的好处是方便快捷、简单易上手,弊端也很明显,那就是网站的安全性很难得到保障,如何在建站的时候保证网站的安全性呢?

关键字: 代码 源程序 源码 开源系统

(文章来源:百家号) 网站安全性是网站运营的基础,现在很多企业在建站的时候会使用到快源程序,开源程序的好处是方便快捷、简单易上手,弊端也很明显,那就是网站的安全性很难得到保障,如何在建站

关键字: 代码 源程序 源码 开源系统

(文章来源:中国西部数码) 云服务器会中毒吗?有可能会,云服务器是提供计算服务的设备,为网站提供各类计算服务,对网站的发展影响非常大。但在服务器运行过程中,我们可能会遇到服务器中毒的情况

关键字: 云服务器 网络 源程序 控制

上一讲中我们学习了如何建立工程、汇编、连接工程,并获得目标代码,但是做到这一 步仅仅代表你的源程序没有语法错误,至于源程序中存在着的其它错误,必须通过调试才能 发现并解决。

关键字: keil 源程序 调试命令

******************************************************************/ #define Wait1us _nop_(); #define Wait2us...

关键字: 源程序 tlc1543
关闭
关闭