STM32-SPI3控制MCP3201、MCP3202(Sigma-Delta-ADC芯片)

STM32-SPI3控制MCP3201、MCP3202(Sigma-Delta-ADC芯片)

  • 原理图
  • 手册说明
  • 功能方框图
  • 引脚功能
  • 数字输出编码与实值的转换
    • 分辨率设置与LSB
    • 最小和最大输出代码(注)
  • 正负符号寄存器位MSB
    • 数字输出编码
    • 数据转换的LSB值
  • 将设备输出编码转换为输入信号电压计算
  • 片内寄存器
    • 配置寄存器
  • 采样与转换过程
  • 应用实例
    • 电压测量
    • 电流测量
  • 代码部分

原理图

在这里插入图片描述

手册说明

MCP3421是一个单通道低噪声、高精度的ΔΣA/D转换器,具有差分输入和高达18位的分辨率,在一个小型的SOT-23-6包中。机载精度2.048V参考电压使输入范围为±2.048V的差异(Δ电压= 4.096V)。该设备使用一个双线I2C兼容的串行接口,并操作从一个2.7V到5.5V的电源。
MCP3421设备以每秒3.75、15、60或240个样本(SPS)的速率执行转换,这取决于使用双线I2C串行接口的用户可控配置位设置。该装置具有一个机载可编程增益放大器(PGA)。用户可以在进行模数转换之前选择x1、x2、x4或x8的PGA增益。这允许MCP3421设备以高分辨率转换较小的输入信号。该设备有两种转换模式: (a)连续模式和(b)单次模式。在单次模式模式下,设备在单次转换后自动进入低电流待机模式。这大大减少了在空闲期间的电流消耗。

功能方框图

在这里插入图片描述

引脚功能

在这里插入图片描述

数字输出编码与实值的转换

分辨率设置与LSB

在这里插入图片描述
内部参考电压为2.048V

最小和最大输出代码(注)

在这里插入图片描述
最大n位编码 = 在这里插入图片描述
最小n位编码 = 在这里插入图片描述

正负符号寄存器位MSB

当MSB是逻辑“0”时,输入为正。当MSB是一个逻辑“1”时,输入是负的。
在这里插入图片描述
注:
1.MSB是一个符号寄存器位: 0:正输入(VIN+>VIN-)1:负输入(VIN+<VIN-)。
2.输出数据格式是二进制二的补充。

数字输出编码

在这里插入图片描述
ADC芯片输出的编码二进制数据,翻转计算可算出Vin

数据转换的LSB值

在这里插入图片描述
用户可编程位分辨率:12、14、16或18

将设备输出编码转换为输入信号电压计算

如果符号指示位(MSB)为“0”,则输入电压通过将输出码与LSB乘以,并除以PGA设置得到输入电压。如果符号指示器位(MSB)是“1”,则输出代码需要转换为2的补码,然后再乘以LSB并除以PGA设置。表4-4显示了将设备输出代码转换为输入电压的示例。
在这里插入图片描述
在这里插入图片描述
公式需结合数字输出编码数据转换的LSB值进行验算

片内寄存器

配置寄存器

开机后的默认配置
在这里插入图片描述
文字说明

这一位是数据准备就绪的标志。在读取模式下,此位表示输出寄存器是否已用最新的转换结果更新。在一次性转换模式下,将此位写入“1”将启动一个新的转换

如果在读取数据字节后(即在18位转换模式下的第5个字节之后)通过连续时钟重复读取配置字节,则RDY位的状态指示设备是否准备好了新的转换结果。当主服务器发现RDY位被清除时,它可以发送一个不承认(NAK)位和一个停止位来退出当前的读操作,并为最新的转换数据发送一个新的读命令。一旦读取了转换数据,准备位将切换到“1”,直到下一个新的转换数据准备就绪。每次完成新的转换时,输出寄存器中的转换数据将被覆盖。图5-3和图5-4显示了读取转换数据的示例。用户可以随时为一个新的设置重写配置字节。表5-1和表5-2给出了配置位操作的示例。

采样与转换过程

也就是说采样时间为1.5倍的CLK周期。在采样的过程中,器件内部的采样保持电容会收集输入通道的电荷,采样的模型图如下:

在这里插入图片描述

如上图所示,信号源阻抗Rss与MCP3201内部采样开关的阻抗Rs将直接影响给电容CSAMPLE充电所需的时间。因此,较大的信号源阻抗会增加转换的失调误差、增益误差和积分线性误差。

当采样结束后,打开转换器的输入开关,MCP3202将开始把内部采样保持电容收集的电荷产生一个12位的串行数字输出编码。MCP3202每收到一个时钟脉冲,就转换一位,共收到12个脉冲,刚好输出一个12位的输出编码值。

值得注意的是,如果时钟速率太慢,采样电容将在转换过程中释放电荷。在85度(最差条件)下,器件能保持采样电容在采样周期结束后至少1.2ms内不会释放电荷。也就是说,从采样周期结束到所有12个数据位都输出之间的时间不能超出1.2ms,即时钟频率要大于10KHz。若此条件得不到满足,就会导致线性误差超出额定规范值。

在整个转换周期内,只要满足时序上的时间最小值要求,对于时钟是否恒定和占空比并没有要求。

应用实例

电压测量

测量电池电压的电路如下图所示
在这里插入图片描述
对于微弱电压,可以使用内部可编程电路放大增益放大器(PGA)进行放大处理,增益高达到8。

测量的模拟输入电压,计算公式
在这里插入图片描述

电流测量

测量电流的电路如下图所示
在这里插入图片描述
测量电流,计算公式
在这里插入图片描述

代码部分

以STM32F103和标准库作为底板
main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"#include "bsp_spi.h"/************************************************ALIENTEK精英STM32开发板实验4串口 实验   技术支持:www.openedv.com淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。广州市星翼电子科技有限公司  作者:正点原子 @ALIENTEK
************************************************/int main(void){		delay_init();	    	 //延时函数初始化	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级uart_init(115200);	 //串口初始化为115200Spi3_init();	/*实测HG-C1400激光传感器最大正数值204.0mm 对应电压为5.03V最大负数值-203.6mm 对应电压为0.003V总测试距离 204+203.6=407.6中间值为 407.6/2=203.8每0.1mm对应电压为 407.6/(4.997*0.012259) = 0.01226V分压电阻 0.01226/2=0.006129
*/while(1){printf("%f\n",(((float)Get_Adc_Average(8,255)*4.072/8191)/(0.01226))*1.9721-200.4);  //1.9721 为 分压 	200.4	为中间距离 以上通过线性回归 	 delay_ms(250);}	 }

bsp_spi.c

#include "bsp_spi.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"/*** 函数功能: SPI3_初始化* 输入参数: * 返 回 值: * 说    明:无*/
void Spi3_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef  SPI_InitStructure;/* 使能GPIO和SPI时钟 */RCC_APB2PeriphClockCmd(	SPI_SCK_CLK ,  ENABLE );//PORTB时钟使能 RCC_APB1PeriphClockCmd(	SPI_CLK ,  ENABLE );//SPI2时钟使能 	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE) ;/*将PA15弄成普通IO   */	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  			//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_15);//使能器件  /* 配置SPI功能引脚:SCK 时钟引脚 */	GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN;;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  			 //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SPI_SCK_PORT, &GPIO_InitStructure);         				 //初始化GPIO/* 配置SPI功能引脚:MISO 主机输出从机输入引脚 */	GPIO_InitStructure.GPIO_Pin = SPI_MISO_PIN;;GPIO_Init(SPI_SCK_PORT, &GPIO_InitStructure);/* 配置SPI功能引脚:MOSI 主机输入从机输出引脚 */	GPIO_InitStructure.GPIO_Pin = SPI_MOSI_PIN;;GPIO_Init(SPI_SCK_PORT, &GPIO_InitStructure);/* SPI外设配置 --NSS 引脚由软件控制以及 MSB 先行模式*/SPI_Cmd(SPI3, DISABLE); //失能能SPI外设SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  	//设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;													//设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;											//设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;														//串行同步时钟的空闲状态为高电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;													//串行同步时钟的第二个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;															//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;	//定义波特率预分频的值:波特率预分频值SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;										//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;															//CRC值计算的多项式SPI_Init(SPI3, &SPI_InitStructure);  																	//根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器/* 配置SPI功能引脚:CS 串行Flash片选引脚 */	GPIO_InitStructure.GPIO_Pin = SPI_CS_PIN;	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  			 							//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(SPI_SCK_PORT, &GPIO_InitStructure);/* 配置SPI所用的引脚:默认高电平 */	GPIO_SetBits(GPIOB,SPI_SCK_PIN|SPI_MISO_PIN|SPI_MOSI_PIN|SPI_CS_PIN);SPI_Cmd(SPI3, ENABLE); //使能SPI外设
}/*** 函数功能: SPI3_接收发送数据* 输入参数: * 返 回 值: * 说    明:无*/
u8 Spi3_readwritebyte(u8 Txdata)
{		u8 retry=0;				 	while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位{retry++;if(retry>200)return 0;}			  SPI_I2S_SendData(SPI3, Txdata); //通过外设SPIx发送一个数据retry=0;while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位{retry++;if(retry>200)return 0;}	  						    return SPI_I2S_ReceiveData(SPI3); //返回通过SPIx最近接收的数据					    
}/*** 函数功能: Mcp3202_接收数据* 输入参数: * 返 回 值: Mcp3202_ADC_16位数据* 说    明:*/int Mcp3202_read(void)
{u32 p;u16 Mcp3202_buffet[2]={0};CS_LOW;delay_us(5);Mcp3202_buffet[0] = Spi3_readwritebyte(0xFF);Mcp3202_buffet[1] = Spi3_readwritebyte(0xFF);CS_HIGH;p = (int)(((Mcp3202_buffet[0] << 8) | Mcp3202_buffet[1])&0xFFFF);return (p);
}/*** 函数功能: 排序取值* 输入参数: 1.要取得数值  2.要写入的排列数据多少* 返 回 值: 参数1的数组的值 * 说    明:无*/
u16 Get_Adc_Average(u8 ch,u8 times)
{unsigned char ii =0,nn=0;float adc_temp = 0;float ad_temp[255] ={0};for(ii=0;ii<times;ii++){ad_temp[ii] =(float) Mcp3202_read();}for(ii=0;ii<times;ii++){for(nn=0;nn<times;nn++){if(ad_temp[nn] > ad_temp[nn+1]){adc_temp = ad_temp[nn];ad_temp[nn] = ad_temp[nn+1];ad_temp[nn+1] = adc_temp;}}}adc_temp = 0;adc_temp = ad_temp[ch];return adc_temp;
} 

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

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

相关文章

SQL JOIN 子句:合并多个表中相关行的完整指南

SQL JOIN JOIN子句用于基于它们之间的相关列合并来自两个或更多表的行。 让我们看一下“Orders”表的一部分选择&#xff1a; OrderIDCustomerIDOrderDate1030821996-09-1810309371996-09-1910310771996-09-20 然后&#xff0c;看一下“Customers”表的一部分选择&#xff…

单片机学习5——外部中断程序

#include<reg52.h>unsigned char a; sbit lcden P3^4;void main() {lcden0;EA1;EX01;IT00;a0xF0; //点亮4位小灯while(1){P1a;} }//中断服务程序 void ext0() interrupt 0 // 0 表示的是外部中断源0 {a0x0f; // 中断处理完&#xff0c;再返回主…

2018年10月4日 Go生态洞察:参与2018年Go公司问卷调查

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

系列十八、Spring bean线程安全问题

一、概述 我们知道Spring中的bean&#xff0c;默认情况下是单例的&#xff0c;那么Spring中的bean是线程安全的吗&#xff1f;这个需要分情况考虑&#xff0c;bean中是否存在成员变量&#xff1f;bean中的成员变量是怎么处理的&#xff1f;...&#xff0c;针对bean的状态会有不…

【C++】类和对象——拷贝构造和赋值运算符重载

上一篇我们讲了构造函数&#xff0c;就是对象实例化时会自动调用&#xff0c;那么&#xff0c;我们这里的拷贝构造在形式上是构造函数的一个重载&#xff0c;拷贝构造其实也是一种构造函数&#xff0c;那么我们就可以引出这里的规则 1.拷贝构造函数的函数名必须与类名相同。 2.…

数据结构——带头循环双向链表(List)

1、带头双向循环链表介绍 在上一篇博客中我们提到了链表有三个特性&#xff0c;可以组合成为8种不同类型的链表。单链表是其中比较重要的一种&#xff0c;那么这次我们选择和带头双向循环链表会会面&#xff0c;这样我们就见识过了所有三种特性的呈现。 带头双向循环链表&#…

HONOR荣耀MagicBook 15 2021款 锐龙版R5(BMH-WFQ9HN)原厂Windows11预装OEM系统含F10智能还原

链接&#xff1a;https://pan.baidu.com/s/1faYtC5BIDC2lsV_JSMI96A?pwdj302 提取码&#xff1a;j302 原厂系统Windows11.22H2工厂模式安装包,含F10一键智能还原&#xff0c;自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、荣耀 电脑管家等预装程序 …

process control 化学工程 需要用到MATLAB的Simulink功能

process control 化学工程 需要用到MATLAB的Simulink功能 所有问题需要的matlab simulink 模型 WeChat: ye1-6688 The riser tube brings in contact the recirculating catalyst with the feed oil, which then vaporizes and splits to lighter components as it flows up th…

服务器下db(数据库)的执行

1、查看 select * from xxxx&#xff08;表名&#xff09; where xxx&#xff08;列表&#xff09;1 and.......正常写就行 2、插入 如果你想要在 SELECT INSERT INTO … SELECT 语句中将部分列保持不变,只改变一两列的值,可以在 语句中直接设置目标列的值,而其他列从源表中…

【C++】类型转换 ③ ( 重新解释类型转换 reinterpret_cast | 指针类型数据转换 )

文章目录 一、重新解释类型转换 reinterpret_cast1、指针数据类型转换 - C 语言隐式类型转换报错 ( 转换失败 )2、指针数据类型转换 - C 语言显示类型强制转换 ( 转换成功 )3、指针数据类型转换 - C 静态类型转换 static_cast ( 转换失败 )4、指针数据类型转换 - C 重新解释类型…

Simulink 的代数环

代数环, 就是由于模型的输出反馈到模块或子系统先的某个输入端, 如果这个输入是直接馈入的, 那么二者在同一个采样点内需得到求解, 但又互相依赖, 哪一方都不能完成求解过程, 使得解算器无法解算导致错误产生, 这样的情况称为代数环。 一旦 Simulink 遇到代数环, 将根据 Confi…

python环境搭建-yolo代码跑通-呕心沥血制作(告别报错no module named torch)

安装软件 安装过的可以查看有没有添加环境变量 好的! 我们发车! 如果你想方便快捷的跑通大型项目,那么必须安装以下两个软件: 1.pycharm2.anaconda对应作用: pycharm:专门用来跑通python项目的软件,相当于一个编辑器,可以debug调试,可以接受远程链接调试!anaconda:专…

2023年初中生古诗文大会复选最后6天备考策略和更新的在线模拟题

今天是2023年11月26日&#xff0c;星期日&#xff0c;距离2023年第八届上海市中学生古诗文大会复选&#xff08;复赛&#xff09;还有六天&#xff08;2023年12月2日上午举办&#xff09;&#xff0c;相信各位晋级的小学霸们正在繁忙的学业之余抓紧备考。 为了帮助孩子们更有效…

thinkphp最新开发的物业管理系统 缴费管理、停车管理、收费管理、值班管理

物业费&#xff0c;水电燃气费&#xff0c;电梯费&#xff0c;租金&#xff0c;临时收费等多种收费规则完全自定义&#xff0c;账单自动生成&#xff0c;无需人工计算 实时数据互通&#xff1a;一键报事报修&#xff0c;购买车辆月卡&#xff0c;管理家人信息&#xff0c;参加物…

idea spring initializr创建项目报错

闲来无事就想搞个项目练练手&#xff0c;没想到直接给我卡在项目创建上了&#xff0c;一个个问题最终迎刃而解。 1.上来就给我报了个maven的错 未解析的插件: ‘org.apache.maven.plugins:maven-resources-plugin:3.3.1’ 不慌&#xff0c;应该是maven的路径有问题&#xff0c…

Redis缓存淘汰策略

Redis缓存淘汰策略 1、各种面试题 生产上你们的redis内存设置多少?如何配置、修改redis的内存大小如果内存满了你怎么办&#xff1f;redis清理内存的方式?定期删除和惰性删除了解过吗&#xff1f;redis缓存淘汰策略有哪些?分别是什么?你用哪个?redis的LRU了解过吗?请手…

AMESim与MATLAB联合仿真demo

本文是AMESim与MATLAB联合仿真的demo&#xff0c;记录一下如何进行联合仿真。 AMESim与MATLAB联合仿真可以大幅度提高工作效率。 author&#xff1a;xiao黄 缓慢而坚定的生长 csdn:https://blog.csdn.net/Python_Matlab?typeblog主页传送门 博主的联合仿真环境如下&#xff…

代码随想录算法训练营 ---第四十三天

前言&#xff1a; 今天同样是01背包问题&#xff0c;今天详细学习了背包问题在各种场景下的应用。今天一道也没做出来&#xff0c;有点废。好难啊&#xff01;就是思路不太清晰&#xff0c;不知道如何去做&#xff0c;看了题解后感觉原来如此&#xff0c;但是想不出来。今天做…

leetcode9.回文数

回文数 0.题目1.WJQ的思路2.实现过程2.0 原始值怎么一个个取出来&#xff1f;2.1 取出来的数如何存到新的数字后面&#xff1f;2.2完整的反转得到新数的过程 3.完整的代码4.可运行的代码5.算法还可以优化的部分 0.题目 给你一个整数 x &#xff0c;如果 x 是一个回文整数&…

IIC驱动OLED(SSD1306) HAL库+CubeMX

一.IIC传输数据的格式 1.写操作 2.读操作 3.IIC信号 二. IIC底层驱动 1.重新初始化配置延时单元 //软件延时 void I2C_Delay(uint32_t t) {volatile uint32_t tmp t;while(tmp--); }void I2C_GPIO_ReInit(void) {/* 1. 使用结构体定义硬件GPIO对象 */GPIO_InitTypeDef GPIO…