STM32-SPI1控制AD7705(Sigma-Delta-ADC芯片)
- 原理图
- 手册说明
- 功能方框图
- 引脚功能
- 片内寄存器
- 通信寄存器(RS2、RS1、RS0=0、0、0)
- 设置寄存器
- 时钟寄存器
- 数据寄存器(RS2、RS1、RS0=0、1、1)
- 测试寄存器(RS2、RS1、RS0=1、0、0);上电/复位状态:00Hex
- 零标度校准寄存器(RS2、RS1、RS0=1、1、0);上电/复位状态:1F4000Hex
- 满标度校准寄存器(RS2、RS1、RS0=1、1、1);上电/复位状态:5761ABHex
- 校准过程
- 代码部分
原理图
该芯片需要晶振(Y2)和参考电源电压(U3)
手册说明
AD7705与国产TM7705型号差不多,也就是可以参考国产的手册。
AD7705利用 Σ-Δ 转换技术实现了 16 位无丢失代码性能。选定的输入信号被送到一个基于模拟调制器的增益可编程专用前端。片内数字滤波器处理调制器的输出信号。通过片内控制寄存器可调节滤波器的截止点和输出更新速率,从而对数字滤波器的第一个陷波进行编程。
TM7705 是双通道全差分模拟输入,带有一个差分基准输入。当电源电压为 5V、基准电压为 2.5V 时,该器件都可将输入信号范围从 0~+20mV 到 0~+2.5V 的信号进行处理。还可处理±20mV~±2.5V 的双极性输入信号,对于 TM7705 是以 AIN(-)输入端为参考点。
功能方框图
引脚功能
片内寄存器
通信寄存器(RS2、RS1、RS0=0、0、0)
设置寄存器
时钟寄存器
数据寄存器(RS2、RS1、RS0=0、1、1)
测试寄存器(RS2、RS1、RS0=1、0、0);上电/复位状态:00Hex
零标度校准寄存器(RS2、RS1、RS0=1、1、0);上电/复位状态:1F4000Hex
满标度校准寄存器(RS2、RS1、RS0=1、1、1);上电/复位状态:5761ABHex
校准过程
代码部分
以STM32F103和标准库作为底板
main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "bsp_spi.h"
#define CS_ADC_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4)
#define CS_ADC_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4)
/************************************************
ALIENTEK精英STM32开发板实验4
串口 实验
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
u8 num1[6];
float l_ncm1;
u8 num2[6];
float l_ncm2;
//写数据
void AD7705_WriteByte(u8 Dst_Addr)
{
CS_ADC_LOW();//使能器件
delay_us(20);
Spi1_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(0x0C); /* 4.9152MHz时钟,250Hz数据更新速率 */
AD7705_WriteByte(0x10); /*选择设置寄存器,使用chnanel 1*/
AD7705_WriteByte(0x47); //写设置寄存器 ,设置成双极性、无缓冲、增益为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(0x46); //写设置寄存器,设置成双极性、无缓冲、增益为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(GPIOA, GPIO_Pin_2==0)){}//待数据准备好AdDrdy=0
CS_ADC_LOW(); //使能器件
delay_us(20);
DataH = Spi1_readwritebyte(0xff);
DataL = Spi1_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(GPIOA, GPIO_Pin_2==0)); //待数据准备好AdDrdy=0
CS_ADC_LOW(); //使能器件
delay_us(20);
DataH = Spi1_readwritebyte(0xff);
DataL = Spi1_readwritebyte(0xff);
delay_us(100);
CS_ADC_HIGH(); //取消片选
DataH = DataH << 8;
temp2 = DataH | DataL;
return temp2;
}
//数据处理
void ADC_7705(void)
{
u16 RCH1_16bit,RCH2_16bit;
RCH1_16bit = GetData7705_CH1();
l_ncm1 = (float)(RCH1_16bit*(2.5/65535)); //算出通道1电压
RCH2_16bit = GetData7705_CH2();
l_ncm2 = (float)(RCH2_16bit*(2.5/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';
printf("buff1:%f\n",l_ncm1);
printf("buff2:%f\n",l_ncm2);
if(l_ncm2>8500|l_ncm2<8200)
{
delay_ms(10);
l_ncm2=0;
}
else
{
}
}
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化与按键连接的硬件接口
Spi1_init(); //SPI 初始化
GPIO_SetBits(GPIOA,GPIO_Pin_0);
Init_AD7705(1);
delay_ms(250);
Init_AD7705(2);
while(1)
{
// Spi1_readwritebyte(0xAA);
// printf("buff1:%X\n",GetData7705_CH1());
// delay_ms(100);
// printf("buff2:%X\n",GetData7705_CH2());
ADC_7705();
delay_ms(250);
}
}
bsp_spi.c
#include "bsp_spi.h"
/**
* 函数功能: SPI 读写一个字节
* 输入参数: 要写入的字节
* 返 回 值: 读取到的字节
* 说 明:无
*/
void Spi1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* 使能GPIO和SPI时钟 */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTB时钟使能
RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );//SPI2时钟使能
/* 配置SPI功能引脚:SCK 时钟引脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
/* 配置SPI功能引脚:MISO 主机输出从机输入引脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置SPI功能引脚:MOSI 主机输入从机输出引脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* SPI外设配置 --NSS 引脚由软件控制以及 MSB 先行模式*/
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功能引脚:CS 串行Flash片选引脚 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置SPI所用的引脚:默认高电平 */
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
/* RES */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
/* CS */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
/* DRDY */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO
GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_4|GPIO_Pin_2);
}
/**
* 函数功能: SPI 速度设置函数
* 输入参数:
SPI_BaudRatePrescaler_2 2分频
SPI_BaudRatePrescaler_8 8分频
SPI_BaudRatePrescaler_16 16分频
SPI_BaudRatePrescaler_256 256分频
* 返 回 值: 无
* 说 明:
*/
void Spi1_SetSpeed(u8 Spi_baudrateprescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
SPI1->CR1&=0XFFC7;
SPI1->CR1|=Spi_baudrateprescaler; //设置SPI1速度
SPI_Cmd(SPI1,ENABLE);
}
/**
* 函数功能: SPI 读写一个字节
* 输入参数: 要写入的字节
* 返 回 值: 读取到的字节
* 说 明:无
*/
u8 Spi1_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最近接收的数据
}