2.2.2 设置寄存器配置(RS2=0,RS1=0,RS0=1)
配置一个设置寄存器步骤如下:
- 想要配置设置寄存器就必须先在通信寄存器中RS2----RS0三位中进行选择,根据标题已经给出如何设置通用寄存器这里先配置通信寄存器。2进制写发为 00010000,16进制写法为 0x10
- 前面通过通信寄存器选择了写入设置寄存器中,那么接下来才是正式的配置设置寄存器。可以看到设置寄存器是一个8位寄存器。MD1—MD0可以根据自己想要的模式进行选择,这里是选择自校准模式,这两位位 01
- G2—G0为增益位,可以根据自己的需求,设置增益位,这选择增益为2,即为 001
- B/U 位:这里根据自己的需求选择单双极性工作,这里选择单极性配置位为 1
- BUF位: 这里选择无缓冲即配置位为 0
- FSYNC位:根据表可以看到1处于复位时,0为数据处理,即这里配置位为 0
- 综合上面的8位配置2进制写法为 01001100,16进制写法为 0x4c,这样一个设置寄存器才算正式配置完成。
2.3 时钟寄存器
时钟寄存器是一个可以读/写数据的 8 位寄存器。
2.3.1 时钟寄存器手册说明
英文手册
中文手册
[tr]名称功能[/tr]
ZERO | 必须在这些位上写零,以确保 AD7705/7706 正确操作。否则,会导致器件的非指定操作。 |
CLKDIV | 主时钟禁止位。逻辑“1”表示阻止主时钟在 MCLKOUT 引脚上输出。禁止时,MCLKOUT 输出引脚处于低电平。这种特性使用户可以灵活地使用 MCLKOUT 引脚,例如可将 MCLKOUT 做为系统内其它器件的时钟源,也可关掉 MCLKOUT,使器件具有省电性能。当在 MCLKIN 上连一个外部主时钟,AD7705/7706 继续保持内部时钟,并在CLKDIS 位有效时仍能进行正常转换。当在 MCLKIN 和 MCLKOUT 之间接一个晶体振荡器或一个陶瓷谐振器,则当 CLKDIS 位有效时,AD7705/7706 时钟将会停止,也不进行模数转换。 |
CLK | 时钟位。CLK 位应根据 AD7705/7706 的工作频率而设置。如果转换器的主时钟频率为2.4576MHz(CLKDIV=0)或为 4.9152MHz(CLKDIV=1),CLK 应置“1” 。如果器件的主时钟频率为 1MHz(CLKDIV=0)或 2MHz (CLKDIV=1),则该位应置“0”。该位为给定的工作频率设置适当的标度电流,并且也(与 FS1 和 FS0 一起)选择器件的输出更新率。如果 CLK 没有按照主时钟频率进行正确的设置,则AD7705/7706 的工作将不能达到指标。 |
FS1–FS0 | 滤波器选择位,它与 CLK 一起决定器件的输出更新率。表 12 显示了滤波器的第一陷波和-3dB 频率。片内数字滤波器产生 sinc3(或 sinx/x3)滤波器响应。与增益选择一起,它也决定了器件的输出噪声。改变了滤波器的陷波以及选定的增益将影响分辨率。表 1 至表 4 示出了滤波器的陷波频率和增益对输出噪声和器件分辨率的影响.器件的输出数据率(或有效转换时间)等于由滤波器的第一个陷波选定的频率。例如,如果滤波器的第一个陷波选在 50Hz,则每个字的输出率为 50Hz,即每2ms 输出一个新字。当这些位改变后,必须进行一次校准。达到满标度步进输入的滤波器的稳定时间,在最坏的情况下是 4×(1/输出数据率)。例如,滤波器的第一个陷波在 50Hz,则达到满标度步进输入的滤波器的稳定时间是 80ms(最大)。如果第一个陷波在 500Hz,则稳定时间为 8ms(最大)。通过对步进输入的同步,这个稳定时间可以减少到 3×(1/输出数据率)。换句话说,如果在 FSYNC 位为高时发生步进输入,则在 FSYNC位返回低后 3×(1/输出数据率)时间内达到稳定。-3dB 频率取决于可编程的第一个陷波频率,按照以下关系式:滤波器-3dB 频率=0.262×滤波器第一个陷波频率
|
注意: 有许多中文手册中CLK这里是翻译错误的,在这里用高亮将错误标记出来。大家也可以去看看英文手册中的正确描述(用了两个高亮框将正确的圈出来了)。
2.3.2 时钟寄存器配置(RS2=0,RS1=1,RS0=0)
配置一个时钟寄存器步骤如下:
- 与之前配置设置寄存器方法相同, 还是先要在通信寄存器中的RS2—RS0三位中选择,这里三位为010,即通讯寄存器16进制配置为 0x20.
- 配置完时通信寄存器,再来看时钟寄存器手册。ZERO位:根据手册提示写0
- CLKDIV位:需要根据模块上晶振进行判断,这里使用的AD7705模块的晶振为4.9152MHz,再根据手册提示这里写 1
- CLK位:根据上面的晶振这位写 1
- FS1—FS0位:前面CLK位写1,这里只有四个方式选择,这里选择500Hz,所以两位写11。(为什么选择500Hz我参考了这位大神指点 链接)
- 注意 时钟寄存器一旦配置出错一定会出现问题,不要问作者为什么知道。在配置前懒得写代码,白嫖网上的代码时发现一直不出效果,找了许久没发现问题出现在哪。之后还是老老实实的翻了翻了英文手册才找出问题,没有认真看手册的血的教训,之前看的还是中文手册,所以建议还是少看一些中文手册多看看原版的英文手册还是有好处的。
2.4 数据寄存器(RS2=0,RS1=1,RS0=1)
数据寄存器是一个 16 位只读寄存器,它包含了来自 AD7705/7706 最新的转换结果。如果通信寄存器将器件设置成对该寄存器写操作,则必定会实际上发生一次写操作以使器件返回到准备对通信寄存器的写操作,但是向器件写入的 16 位数字将被 AD7705/7706 忽略。
2.5 测试寄存器 (RS2=1,RS1=0,RS0=0)
测试寄存器用于测试器件时。建议用户不要改变测试寄存器的任何位的默认值(上电或复位时自动置入全 0),否则当器件处于测试模式时,不能正确运行。
2.6 零标度校准寄存器(RS2=1,RS1=1,RS0=0)
AD7705/7706 包含几组独立的零标度寄存器,每个零标度寄存器负责一个输入通道。它们皆为 24 位读/写寄存器,24 位数据必须被写之后才能传送到零标度校准寄存器。零标度寄存器和满标度寄存器连在一起使用,组成一个寄存器对。每个寄存器对对应一对通道,见表 7。当器件被设置成允许通过数字接口访问这些寄存器时,器件本身不再访问寄存器系数以使输出数据具有正确的尺度。结果,在访问校准寄存器(无论是读/写操作)后,从器件读得的第一个输出数据可能包含不正确的数据。此外,数据校准期间,校准寄存器不能进行写操作。这类事件可以通过以下方法避免:在校准寄存器开始工作前,将模式寄存器的 FSYNC 位置为高电平,任务结束后,又将其置为低电平。
2.7 满标度校准寄存器(RS2=1,RS1=0,RS0=1)
3. STM32F10x驱动程序
AD7705采用的SPI通讯协议,这里默认大家已经会C语言,SPI通讯协议了这里不细讲,头文件写法也不讲。
如果有同学还不清楚SPI的话这里我给出正点原子的B站视频网站:视频
3.1 SPI 代码
3.1.1 SPI与STM32引脚连接图
3.1.2 SPI.H代码
#ifndef __SPI_H
#define __SPI_H
#include "sys.h"
#include "stm32f10x_spi.h"
#define CLK Pin5
#define DOUT Pin6
#define Din Pin7
#define DRDY Pin8
#define CS_ADC_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4)
#define CS_ADC_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4)
void SPI1_Init(void);
u8 SPIx_ReadWriteByte(u8 TxData);
#endif
3.1.3 SPI.C代码
#include "spi.h"
#include "delay.h"
/* 复用功能 SPI1_REMAP = 0
SPI1_NSS PA4 CS
SPI1_SCK PA5 CLK
SPI1_MISO PA6 DOUT
SPI1_MOSI PA7 DIN
PC4 DRDY
*/
SPI_InitTypeDef SPI_InitStructure;
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_SPI1|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;// AdDrdy
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;//PC4配置成上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SPI CS
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
/* Configure SPI1 pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SPI_Cmd(SPI1, DISABLE); //失能能SPI外设
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //选择了串行时钟的稳态:时钟悬空高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第二个时钟
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
CS_ADC_LOW();
SPIx_ReadWriteByte(0xff);//启动传输
CS_ADC_HIGH();
}
//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPIx_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
}
3.2 AD7705程序
3.2.1 AD7705.H
#ifndef __AD7705_H
#define __AD7705_H
#include "spi.h"
void AD7705_WriteByte(u8 Dst_Addr);
void Init_AD7705(u8 chnanel);
u16 GetData7705_CH1(void);
u16 GetData7705_CH2(void);
void ADC_7705(void);
void ADC_7705_double(void);
#endif
3.2.1 AD7705.C
#include "ad7705.h"
#include "spi.h"
#include "oled.h"
#include "usart.h"
#include "math.h"
#include "delay.h"
#include "beep.h"
//写数据
void AD7705_WriteByte(u8 Dst_Addr)
{
CS_ADC_LOW();//使能器件
delay_us(20);
SPIx_ReadWriteByte(Dst_Addr);
delay_us(100);
CS_ADC_HIGH();//使能器件
}
/********AD7705初始化函数***********/
void Init_AD7705(u8 chnanel)
{
u8 i;
for(i=0;i<150;i++)/* 多于连续32个 DIN=1 使串口复位 */
{
AD7705_WriteByte(0xff);//持续DIN高电平写操作,恢复AD7705接口
}
delay_ms(1);
switch(chnanel)
{
case 1:
AD7705_WriteByte(0x20); /* 写时钟寄存器选中ch1*/
AD7705_WriteByte(0x0f); /* 4.9152MHz时钟,250Hz数据更新速率 */
AD7705_WriteByte(0x10); /*选择设置寄存器,使用chnanel 1*/
AD7705_WriteByte(0x4c); //写设置寄存器 ,设置成双极性、无缓冲、增益为2、滤波器工作、自校准
break;
/*有更改,时钟寄存器设为0x0a,4.9152MHz时钟,500Hz数据更新速率,*/
case 2:
AD7705_WriteByte(0x21); /* 写时钟寄存器选中ch2 */
AD7705_WriteByte(0x0f); /* 4.9152MHz时钟,500Hz数据更新速率 */
AD7705_WriteByte(0x11); /*选择设置寄存器,使用chnane 2*/
AD7705_WriteByte(0x4c); //写设置寄存器,设置成双极性、无缓冲、增益为2、滤波器工作、自校准
break;
default:
break;
}
}
/* 读AD7705转换数据 输入通道channel */
u16 GetData7705_CH1(void)
{
u16 temp1 = 0;
u16 DataL = 0;
u16 DataH = 0;
Init_AD7705(1); //初始化通道1
delay_ms(1);
AD7705_WriteByte(0x39); //选中CH1数据寄存器读
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4==1)){}//待数据准备好AdDrdy=0
CS_ADC_LOW(); //使能器件
delay_us(20);
DataH = SPIx_ReadWriteByte(0xff);
DataL = SPIx_ReadWriteByte(0xff);
delay_us(100);
CS_ADC_HIGH(); //取消片选
DataH = DataH << 8;
temp1 = DataH | DataL;
return temp1;
}
/* 读AD7705转换数据 输入通道channel */
u16 GetData7705_CH2(void)
{
u16 temp2 = 0;
u16 DataL = 0;
u16 DataH = 0;
Init_AD7705(2); //初始化通道2
delay_ms(1);
AD7705_WriteByte(0x38); //选中CH2数据寄存器读
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4==1)); //待数据准备好AdDrdy=0
CS_ADC_LOW(); //使能器件
delay_us(20);
DataH = SPIx_ReadWriteByte(0xff);
DataL = SPIx_ReadWriteByte(0xff);
delay_us(100);
CS_ADC_HIGH(); //取消片选
DataH = DataH << 8;
temp2 = DataH | DataL;
return temp2;
}
//数据处理
extern u8 num1[];
extern u32 l_ncm1;
extern u8 num2[];
extern u32 l_ncm2;
void ADC_7705(void)
{
u16 RCH1_16bit,RCH2_16bit;
RCH1_16bit = GetData7705_CH1();
l_ncm1 = (u32)(RCH1_16bit*(25000.0/65535)); //算出通道1电压
RCH2_16bit = GetData7705_CH2();
l_ncm2 = (u32)(RCH2_16bit*(25000.0/65535)); //算出通道2电压
num1[0] = l_ncm1/10000+'0';
num1[2] = (l_ncm1%10000)/1000+'0';
num1[3] = (l_ncm1%1000)/100+'0';
num1[4] = (l_ncm1%100)/10+'0';
num1[5] = l_ncm1%10+'0';
num2[0] = l_ncm2/10000+'0';
num2[2] = (l_ncm2%10000)/1000+'0';
num2[3] = (l_ncm2%1000)/100+'0';
num2[4] = (l_ncm2%100)/10+'0';
num2[5] = l_ncm2%10+'0';
if(l_ncm2>8500|l_ncm2<8200)
{
BEEP=!BEEP;
delay_ms(10);
l_ncm2=0;
}
else
{
BEEP=0;
}
}
2.2.2 设置寄存器配置(RS2=0,RS1=0,RS0=1)
配置一个设置寄存器步骤如下:
- 想要配置设置寄存器就必须先在通信寄存器中RS2----RS0三位中进行选择,根据标题已经给出如何设置通用寄存器这里先配置通信寄存器。2进制写发为 00010000,16进制写法为 0x10
- 前面通过通信寄存器选择了写入设置寄存器中,那么接下来才是正式的配置设置寄存器。可以看到设置寄存器是一个8位寄存器。MD1—MD0可以根据自己想要的模式进行选择,这里是选择自校准模式,这两位位 01
- G2—G0为增益位,可以根据自己的需求,设置增益位,这选择增益为2,即为 001
- B/U 位:这里根据自己的需求选择单双极性工作,这里选择单极性配置位为 1
- BUF位: 这里选择无缓冲即配置位为 0
- FSYNC位:根据表可以看到1处于复位时,0为数据处理,即这里配置位为 0
- 综合上面的8位配置2进制写法为 01001100,16进制写法为 0x4c,这样一个设置寄存器才算正式配置完成。
2.3 时钟寄存器
时钟寄存器是一个可以读/写数据的 8 位寄存器。
2.3.1 时钟寄存器手册说明
英文手册
中文手册
[tr]名称功能[/tr]
ZERO | 必须在这些位上写零,以确保 AD7705/7706 正确操作。否则,会导致器件的非指定操作。 |
CLKDIV | 主时钟禁止位。逻辑“1”表示阻止主时钟在 MCLKOUT 引脚上输出。禁止时,MCLKOUT 输出引脚处于低电平。这种特性使用户可以灵活地使用 MCLKOUT 引脚,例如可将 MCLKOUT 做为系统内其它器件的时钟源,也可关掉 MCLKOUT,使器件具有省电性能。当在 MCLKIN 上连一个外部主时钟,AD7705/7706 继续保持内部时钟,并在CLKDIS 位有效时仍能进行正常转换。当在 MCLKIN 和 MCLKOUT 之间接一个晶体振荡器或一个陶瓷谐振器,则当 CLKDIS 位有效时,AD7705/7706 时钟将会停止,也不进行模数转换。 |
CLK | 时钟位。CLK 位应根据 AD7705/7706 的工作频率而设置。如果转换器的主时钟频率为2.4576MHz(CLKDIV=0)或为 4.9152MHz(CLKDIV=1),CLK 应置“1” 。如果器件的主时钟频率为 1MHz(CLKDIV=0)或 2MHz (CLKDIV=1),则该位应置“0”。该位为给定的工作频率设置适当的标度电流,并且也(与 FS1 和 FS0 一起)选择器件的输出更新率。如果 CLK 没有按照主时钟频率进行正确的设置,则AD7705/7706 的工作将不能达到指标。 |
FS1–FS0 | 滤波器选择位,它与 CLK 一起决定器件的输出更新率。表 12 显示了滤波器的第一陷波和-3dB 频率。片内数字滤波器产生 sinc3(或 sinx/x3)滤波器响应。与增益选择一起,它也决定了器件的输出噪声。改变了滤波器的陷波以及选定的增益将影响分辨率。表 1 至表 4 示出了滤波器的陷波频率和增益对输出噪声和器件分辨率的影响.器件的输出数据率(或有效转换时间)等于由滤波器的第一个陷波选定的频率。例如,如果滤波器的第一个陷波选在 50Hz,则每个字的输出率为 50Hz,即每2ms 输出一个新字。当这些位改变后,必须进行一次校准。达到满标度步进输入的滤波器的稳定时间,在最坏的情况下是 4×(1/输出数据率)。例如,滤波器的第一个陷波在 50Hz,则达到满标度步进输入的滤波器的稳定时间是 80ms(最大)。如果第一个陷波在 500Hz,则稳定时间为 8ms(最大)。通过对步进输入的同步,这个稳定时间可以减少到 3×(1/输出数据率)。换句话说,如果在 FSYNC 位为高时发生步进输入,则在 FSYNC位返回低后 3×(1/输出数据率)时间内达到稳定。-3dB 频率取决于可编程的第一个陷波频率,按照以下关系式:滤波器-3dB 频率=0.262×滤波器第一个陷波频率
|
注意: 有许多中文手册中CLK这里是翻译错误的,在这里用高亮将错误标记出来。大家也可以去看看英文手册中的正确描述(用了两个高亮框将正确的圈出来了)。
2.3.2 时钟寄存器配置(RS2=0,RS1=1,RS0=0)
配置一个时钟寄存器步骤如下:
- 与之前配置设置寄存器方法相同, 还是先要在通信寄存器中的RS2—RS0三位中选择,这里三位为010,即通讯寄存器16进制配置为 0x20.
- 配置完时通信寄存器,再来看时钟寄存器手册。ZERO位:根据手册提示写0
- CLKDIV位:需要根据模块上晶振进行判断,这里使用的AD7705模块的晶振为4.9152MHz,再根据手册提示这里写 1
- CLK位:根据上面的晶振这位写 1
- FS1—FS0位:前面CLK位写1,这里只有四个方式选择,这里选择500Hz,所以两位写11。(为什么选择500Hz我参考了这位大神指点 链接)
- 注意 时钟寄存器一旦配置出错一定会出现问题,不要问作者为什么知道。在配置前懒得写代码,白嫖网上的代码时发现一直不出效果,找了许久没发现问题出现在哪。之后还是老老实实的翻了翻了英文手册才找出问题,没有认真看手册的血的教训,之前看的还是中文手册,所以建议还是少看一些中文手册多看看原版的英文手册还是有好处的。
2.4 数据寄存器(RS2=0,RS1=1,RS0=1)
数据寄存器是一个 16 位只读寄存器,它包含了来自 AD7705/7706 最新的转换结果。如果通信寄存器将器件设置成对该寄存器写操作,则必定会实际上发生一次写操作以使器件返回到准备对通信寄存器的写操作,但是向器件写入的 16 位数字将被 AD7705/7706 忽略。
2.5 测试寄存器 (RS2=1,RS1=0,RS0=0)
测试寄存器用于测试器件时。建议用户不要改变测试寄存器的任何位的默认值(上电或复位时自动置入全 0),否则当器件处于测试模式时,不能正确运行。
2.6 零标度校准寄存器(RS2=1,RS1=1,RS0=0)
AD7705/7706 包含几组独立的零标度寄存器,每个零标度寄存器负责一个输入通道。它们皆为 24 位读/写寄存器,24 位数据必须被写之后才能传送到零标度校准寄存器。零标度寄存器和满标度寄存器连在一起使用,组成一个寄存器对。每个寄存器对对应一对通道,见表 7。当器件被设置成允许通过数字接口访问这些寄存器时,器件本身不再访问寄存器系数以使输出数据具有正确的尺度。结果,在访问校准寄存器(无论是读/写操作)后,从器件读得的第一个输出数据可能包含不正确的数据。此外,数据校准期间,校准寄存器不能进行写操作。这类事件可以通过以下方法避免:在校准寄存器开始工作前,将模式寄存器的 FSYNC 位置为高电平,任务结束后,又将其置为低电平。
2.7 满标度校准寄存器(RS2=1,RS1=0,RS0=1)
3. STM32F10x驱动程序
AD7705采用的SPI通讯协议,这里默认大家已经会C语言,SPI通讯协议了这里不细讲,头文件写法也不讲。
如果有同学还不清楚SPI的话这里我给出正点原子的B站视频网站:视频
3.1 SPI 代码
3.1.1 SPI与STM32引脚连接图
3.1.2 SPI.H代码
#ifndef __SPI_H
#define __SPI_H
#include "sys.h"
#include "stm32f10x_spi.h"
#define CLK Pin5
#define DOUT Pin6
#define Din Pin7
#define DRDY Pin8
#define CS_ADC_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4)
#define CS_ADC_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4)
void SPI1_Init(void);
u8 SPIx_ReadWriteByte(u8 TxData);
#endif
3.1.3 SPI.C代码
#include "spi.h"
#include "delay.h"
/* 复用功能 SPI1_REMAP = 0
SPI1_NSS PA4 CS
SPI1_SCK PA5 CLK
SPI1_MISO PA6 DOUT
SPI1_MOSI PA7 DIN
PC4 DRDY
*/
SPI_InitTypeDef SPI_InitStructure;
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_SPI1|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;// AdDrdy
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;//PC4配置成上拉输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SPI CS
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOA,GPIO_Pin_4);
/* Configure SPI1 pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SPI_Cmd(SPI1, DISABLE); //失能能SPI外设
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //选择了串行时钟的稳态:时钟悬空高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第二个时钟
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
CS_ADC_LOW();
SPIx_ReadWriteByte(0xff);//启动传输
CS_ADC_HIGH();
}
//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPIx_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //检查指定的SPI标志位设置与否:接受缓存非空标志位
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
}
3.2 AD7705程序
3.2.1 AD7705.H
#ifndef __AD7705_H
#define __AD7705_H
#include "spi.h"
void AD7705_WriteByte(u8 Dst_Addr);
void Init_AD7705(u8 chnanel);
u16 GetData7705_CH1(void);
u16 GetData7705_CH2(void);
void ADC_7705(void);
void ADC_7705_double(void);
#endif
3.2.1 AD7705.C
#include "ad7705.h"
#include "spi.h"
#include "oled.h"
#include "usart.h"
#include "math.h"
#include "delay.h"
#include "beep.h"
//写数据
void AD7705_WriteByte(u8 Dst_Addr)
{
CS_ADC_LOW();//使能器件
delay_us(20);
SPIx_ReadWriteByte(Dst_Addr);
delay_us(100);
CS_ADC_HIGH();//使能器件
}
/********AD7705初始化函数***********/
void Init_AD7705(u8 chnanel)
{
u8 i;
for(i=0;i<150;i++)/* 多于连续32个 DIN=1 使串口复位 */
{
AD7705_WriteByte(0xff);//持续DIN高电平写操作,恢复AD7705接口
}
delay_ms(1);
switch(chnanel)
{
case 1:
AD7705_WriteByte(0x20); /* 写时钟寄存器选中ch1*/
AD7705_WriteByte(0x0f); /* 4.9152MHz时钟,250Hz数据更新速率 */
AD7705_WriteByte(0x10); /*选择设置寄存器,使用chnanel 1*/
AD7705_WriteByte(0x4c); //写设置寄存器 ,设置成双极性、无缓冲、增益为2、滤波器工作、自校准
break;
/*有更改,时钟寄存器设为0x0a,4.9152MHz时钟,500Hz数据更新速率,*/
case 2:
AD7705_WriteByte(0x21); /* 写时钟寄存器选中ch2 */
AD7705_WriteByte(0x0f); /* 4.9152MHz时钟,500Hz数据更新速率 */
AD7705_WriteByte(0x11); /*选择设置寄存器,使用chnane 2*/
AD7705_WriteByte(0x4c); //写设置寄存器,设置成双极性、无缓冲、增益为2、滤波器工作、自校准
break;
default:
break;
}
}
/* 读AD7705转换数据 输入通道channel */
u16 GetData7705_CH1(void)
{
u16 temp1 = 0;
u16 DataL = 0;
u16 DataH = 0;
Init_AD7705(1); //初始化通道1
delay_ms(1);
AD7705_WriteByte(0x39); //选中CH1数据寄存器读
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4==1)){}//待数据准备好AdDrdy=0
CS_ADC_LOW(); //使能器件
delay_us(20);
DataH = SPIx_ReadWriteByte(0xff);
DataL = SPIx_ReadWriteByte(0xff);
delay_us(100);
CS_ADC_HIGH(); //取消片选
DataH = DataH << 8;
temp1 = DataH | DataL;
return temp1;
}
/* 读AD7705转换数据 输入通道channel */
u16 GetData7705_CH2(void)
{
u16 temp2 = 0;
u16 DataL = 0;
u16 DataH = 0;
Init_AD7705(2); //初始化通道2
delay_ms(1);
AD7705_WriteByte(0x38); //选中CH2数据寄存器读
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4==1)); //待数据准备好AdDrdy=0
CS_ADC_LOW(); //使能器件
delay_us(20);
DataH = SPIx_ReadWriteByte(0xff);
DataL = SPIx_ReadWriteByte(0xff);
delay_us(100);
CS_ADC_HIGH(); //取消片选
DataH = DataH << 8;
temp2 = DataH | DataL;
return temp2;
}
//数据处理
extern u8 num1[];
extern u32 l_ncm1;
extern u8 num2[];
extern u32 l_ncm2;
void ADC_7705(void)
{
u16 RCH1_16bit,RCH2_16bit;
RCH1_16bit = GetData7705_CH1();
l_ncm1 = (u32)(RCH1_16bit*(25000.0/65535)); //算出通道1电压
RCH2_16bit = GetData7705_CH2();
l_ncm2 = (u32)(RCH2_16bit*(25000.0/65535)); //算出通道2电压
num1[0] = l_ncm1/10000+'0';
num1[2] = (l_ncm1%10000)/1000+'0';
num1[3] = (l_ncm1%1000)/100+'0';
num1[4] = (l_ncm1%100)/10+'0';
num1[5] = l_ncm1%10+'0';
num2[0] = l_ncm2/10000+'0';
num2[2] = (l_ncm2%10000)/1000+'0';
num2[3] = (l_ncm2%1000)/100+'0';
num2[4] = (l_ncm2%100)/10+'0';
num2[5] = l_ncm2%10+'0';
if(l_ncm2>8500|l_ncm2<8200)
{
BEEP=!BEEP;
delay_ms(10);
l_ncm2=0;
}
else
{
BEEP=0;
}
}
举报