STM32-SPI1控制AD7705(Sigma-Delta-ADC芯片)

news2024/11/17 9:46:31

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最近接收的数据					    
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1250437.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EEG 脑电信号处理合集(2): 信号预处理

脑电信号在采集完以后&#xff0c;需要进行一系列的预处理操作&#xff0c;然后才能用于后续的科学研究和计算。预处理是脑电信号分析最基本且重要的一步。基于python环境MNE库。 1 使用带通滤波器&#xff0c;信号滤波&#xff0c;去噪&#xff0c;去工频干扰 data_path sam…

PyQt6运行QTDesigner生成的ui文件程序

2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计18条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~、第2讲 PyQt6库和工具库Q…

广州华锐互动:AR可视化展示昆虫让教学过程更直观生动

随着科技的不断发展&#xff0c;AR&#xff08;增强现实&#xff09;技术已经逐渐走进我们的生活。通过AR技术&#xff0c;我们可以将虚拟的信息叠加到现实世界中&#xff0c;让现实世界变得更加丰富多彩。在这篇文章中&#xff0c;我们将以昆虫为主题&#xff0c;探讨AR增强现…

人工智能教程(二):人工智能的历史以及再探矩阵

目录 前言 更多矩阵的知识 Pandas 矩阵的秩 前言 在上一章中&#xff0c;我们讨论了人工智能、机器学习、深度学习、数据科学等领域的关联和区别。我们还就整个系列将使用的编程语言、工具等做出了一些艰难的选择。最后&#xff0c;我们还介绍了一点矩阵的知识。在本文中&am…

【教3妹学编程-算法题】二叉树中的伪回文路径

3妹&#xff1a;好冷啊&#xff0c; 冻得瑟瑟发抖啦 2哥 : 又一波寒潮来袭&#xff0c; 外面风吹的呼呼的。 3妹&#xff1a;今天还有雨&#xff0c;2哥上班记得带伞。 2哥 : 好的 3妹&#xff1a;哼&#xff0c;不喜欢冬天&#xff0c;也不喜欢下雨天&#xff0c;要是我会咒语…

BUUCTF [ACTF新生赛2020]base64隐写 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。 密文&#xff1a; 下载附件&#xff0c;解压得到.zip文件&#xff0c;再次解压得到两个文件。 解题思路&#xff1a; 1、打开ComeOn!.txt文件&#xff0c;发现一大串经过Base64加…

软著项目推荐 深度学习 python opencv 火焰检测识别 火灾检测

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…

运动蓝牙耳机什么牌子好?百元蓝牙运动耳机排行榜

​跑步、骑车、健身等运动时&#xff0c;大家都需要一款专业的运动耳机来陪伴&#xff0c;它不仅可以提供高品质的音乐和佩戴舒适度&#xff0c;还可以帮助你掌握运动状态&#xff0c;让你更加专注和投入。今天我为大家推荐几款备受好评的运动耳机&#xff0c;它们都拥有不错的…

常用的Linux的指令

目录 常用指令 1、文件和目录操作&#xff1a; 2、文件查看和编辑 3、系统信息 4、进程管理 5、用户和权限 6、网络操作 7、压缩和解压 8、软件包管理 常用指令 1、文件和目录操作&#xff1a; ls&#xff1a;列出目录内容 cd&#xff1a; 切换目录 pwd&#xff1a;显…

模块的学习

模块合包的基本概念&#xff1a; 模块&#xff08;module&#xff09;&#xff1a;在python中&#xff0c;xx.py文件&#xff0c;就可以被看作模块 包&#xff08;package&#xff09;: 用来管理和存放模块的文件夹&#xff0c;就被称为包&…

系列十四、BeanFactory vs FactoryBean

一、BeanFactory IOC思想是基于IOC容器完成的&#xff0c;IOC容器的底层就是对象工厂&#xff0c;其核心接口为BeanFactory&#xff0c;BeanFactory是一个工厂类&#xff0c;负责生产和管理各种各样的bean&#xff0c;也是Spring内部的使用接口&#xff0c;不提供给开发人员使用…

bodymovin:AE动画导出为JSONforMac/win中文版下载

对于动画制作爱好者和专业设计师来说&#xff0c;Adobe After Effects&#xff08;AE&#xff09;是一个强大的工具&#xff0c;可以创造出惊人的动画效果。然而&#xff0c;将这些动画导出为可交互的格式一直是一个挑战。现在&#xff0c;有了bodymovin&#xff0c;你可以轻松…

Apache Superset数据分析平台如何实现公网实时远程访问数据【内网穿透】

文章目录 前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透&#xff0c;实现公网访问3. 设置固定连接公网地址 前言 Superset是一款由中国知名科技公司开源的“现代化的…

【2023 云栖】阿里云田奇铣:大模型驱动 DataWorks 数据开发治理平台智能化升级

云布道师 本文根据 2023 云栖大会演讲实录整理而成&#xff0c;演讲信息如下&#xff1a; 演讲人&#xff1a;田奇铣 | 阿里云 DataWorks 产品负责人 演讲主题&#xff1a;大模型驱动 DataWorks 数据开发治理平台智能化升级 随着大模型掀起 AI 技术革新浪潮&#xff0c;大数…

基于单片机的智能鱼缸(论文+源码)

1.总体设计 在本次设计中&#xff0c;其系统整个框图如下图2.1所示。其主要的核心控制模块由单片机模块&#xff0c;LCD显示模块&#xff0c;喂食模块&#xff0c;蜂鸣器模块&#xff0c;按键模块&#xff0c;复位电路&#xff0c;抽水电路&#xff0c;加热电路&#xff0c;加…

HarmonyOS4.0系列——02、汉化插件、声明式开发范式ArkTS和类web开发范式

编辑器调整 我们在每次退出编辑器后再次打开会直接进入项目文件中&#xff0c;这样在新建项目用起来很是不方便&#xff0c;所以这里跟着设置一下就好 这样下次进入就不会直接跳转到当时的文件项目中&#xff01;&#xff01; 关于汉化 settings → plugins → installe…

《大话设计模式》(持续更新中)

《大话设计模式》 序 为什么要学设计模式第0章 面向对象基础什么是对象&#xff1f;什么是类&#xff1f;什么是构造方法&#xff1f;什么是重载&#xff1f;属性与字段有什么区别&#xff1f;什么是封装&#xff1f;什么是继承&#xff1f;什么是多态&#xff1f;抽象类的目的…

篮桥云课-摆玩具

思维好题 一开始掉进了二分的陷阱&#xff0c;发现看看逐个位置的差&#xff0c;我们要分成k段就是要取消k-1个最大的逐差 然后将剩余的加起来就可以了 因为本体保证是从小到大给出的 这一点保证了答案的正确性&#xff0c;自己没想出来 还是太菜了 #include<bits/stdc.h&…

hdlbits系列verilog解答(exams/m2014_q4i)-45

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 实现以下电路&#xff1a; 二、verilog源码 module top_module (output out);assign out 1b0;endmodule三、仿真结果 转载请注明出处&#xff01;

【LeetCode】每日一题 2023_11_25 二叉树中的伪回文路径(dfs,数组/位运算)

文章目录 刷题前唠嗑题目&#xff1a;二叉树中的伪回文路径题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 这个月第一次周末早起~ 题目&#xff1a;二叉树中的伪回文路径 题目链接&#xff1a;1457. 二…