程序实现:
首先是对AD7708的读写寄存器函数,AD7708的每次操作都以写通信寄存器开始,通过这一步,指示下一步将进行什么操作;有关寄存器每一位的意义,参考附件(博客结尾)中的AD7708-寄存器
写入寄存器:
void AD7708WriteRegister(char addr,long dat)
{
SpiWriteData(addr); //写通信寄存器,通知下个操作:写addr寄存器
if(IsLong[addr]) //如果是16位寄存器, 7718则24位若移植要改if内语句
{
SpiWriteData(dat>>8);
}
SpiWriteData(0xFF&dat); //写入低位数据
}
寄存器地址,可以查阅datasheet或我翻译的那部分;IsLong字符数组指示对应的寄存器是8位还是16位的:
char IsLong[16] = {0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0};
读取寄存器:
long AD7708ReadRegister(char addr)
{
char h = 0,l = 0; //高低字节数据
SpiWriteData(0x40|addr); //写通信寄存器,通知下个操作:读addr寄存器
if(IsLong[addr])
{
h = SpiWriteData(0xFF);
}
l = SpiWriteData(0xFF);
return ((unsigned int)h<<8)|l;
}
SPI解释:430是SPI主机模块,当发送的时候,同时,另外一个时钟沿采样接收,所以,每次发送完成后的半个周期,均可得到读出的数据;所以SpiWriteData函数写入的同时返回同时收到的字符。发送0xFF即是为提供读取即将到来的数据提供时钟,详细可以参考上一篇的注意事项部分(刚更新的)。
读取结果数据:
long AD7708ReadResultData()
{
while((AD7708ReadRegister(0x00)&0x80)==0); //等待转换完成
return AD7708ReadRegister(0x04);
}
等待STATUS的RDY位变高(AD数据转换更新完成),读取data寄存器的内容。
校准:校准的过程在datasheet中有详细的流程图;可以参考datasheet或者附件中的AD7708-寄存器,这个子函数只完成一个通道的校准,通道地址有参数输入,方便调用:
void AD7708Cal(char channel)
{
adccon = (adccon&0x0f)|(channel<<4);
mode = (mode&0xf8)|0x04; //内部0校准
AD7708WriteRegister(0x02,adccon); //ADC控制寄存器,channel通道
AD7708WriteRegister(0x01,mode); //模式寄存器
while((AD7708ReadRegister(0x01)&0x07)!=0x01); //等待校准完成
mode = (mode&0xf8)|0x05; //内部 满标度校准
AD7708WriteRegister(0x01,mode); //模式寄存器
while((AD7708ReadRegister(0x01)&0x07)!=0x01); //等待校准完成
}
adccon是程序记录的前一次输入的ADCCON寄存器的内容,mode是程序记录的上一次输入的MODE寄存器的内容,因为串口读取需要时间,为了获取更快的速度,程序记录了这两个变量,以供使用。通道地址参考datasheet,或附件中的文档。
初始化:
void AD7708Init(char chop)
{
P3DIR|=BIT0;
P3OUT&=~BIT0; //CS选中
//主机模式,115200,8位数据位,三线模式,时钟模式1(具体见spi.c)
SpiMasterInit(115200,8,3,1); //时钟不是准确的115200(具体见spi.c)
_EINT(); //开中断,spi读写程序要需要中断
char filter;
adccon = 0x0f;
if(chop == 0)
{
filter = 0x03; //滤波寄存器设为最小值,可以更改
mode = 0x91; //斩波禁止,10通道,无缓冲,空闲模式
}
else
{
filter = 0x0D; //滤波寄存器设为最小值,可以更改
mode = 0x11; //斩波启用,10通道,无缓冲,空闲模式
}
AD7708WriteRegister(0x07,0x00); //IO寄存器,不用==
AD7708WriteRegister(0x03,filter); //滤波寄存器
AD7708WriteRegister(0x02,0x0F); //ADC控制寄存器,0通道,单极性
AD7708WriteRegister(0x01,mode); //模式寄存器
if(chop == 0)
for(int i = 0; i<5;i++)
{
//校准,因只有5个失调寄存器,多的就会覆盖之前的,只校准5个即可
AD7708Cal(5);
}
_DINT();
}
初始化制引入了斩波这一个参数,其他的均使用固定的参数:10通道伪差分、单极性、无缓冲、滤波寄存器设为斩波或禁止斩波时候的最快速度,需要的话可以自行修改。SPI初始化之后开中断,目的是向AD写内容以初始化AD。初始化完成后关中断,为了让程序库的初始化后一致,但调用这个函数后,需要开中断,才能正常使用AD采样的其它函数。
采样启动:本程序只支持了单词采样的开始,若需要连续模式的,可以自行实现(比较容易实现:只需更改寄存器的值即可):
void AD7708Start(char channel)
{
adccon = (adccon&0x0f)|(channel<<4);
mode = (mode&0xf8)|0x02;
AD7708WriteRegister(0x02,adccon);
AD7708WriteRegister(0x01,mode);
}
根据之前一次的控制寄存器和模式寄存器的设置,更改现在需要的值,写入相应寄存器即可。
到此,程序部分完成,需要扩展,可以自行添加。
3.使用说明:
使用时,只需加入AD7708.c,文件包含AD7708.h,然后就可以正常使用本程序提供的函数;具体可以参考示例工程和其中的main.c文件。
long a;
void main()
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
ClkInit();
AD7708Init(0); //禁止斩波 1时启用斩波
_EINT(); //开中断,程序需要用到SPI的中断;冲突,可以更改SPI函数
while(1) //串口测试
{
AD7708Start(0);
a = AD7708ReadResultData(); //读取AD采样后的结果
//电压计算方法:a*1.024*2.5(参考电压)/65535
a = AD7708ReadRegister(0); //去状态值,此处函数不需要用
}
}
AD7708的程序库(简化,其他需求可以自行添加:有读写寄存器的函数之后,添加其他功能比较简单)已经完成,有什么不足之处欢迎大家讨论;谢啦。
|