【STM32H7教程】第93章 STM32H7的SPI总线应用之驱动ADS1256(8通道24bit ADC, 增益可编程)
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980
第93章 STM32H7的SPI总线应用之驱动ADS1256(8通道24bit ADC, 增益可编程)
本章节为大家讲解8通道24bit ADC芯片驱动实现。
93.1 初学者重要提示
93.2 ADC结构分类
93.3 ADS1256硬件设计
93.4 ADS1256关键知识点整理(重要)
93.5 ADS1256驱动设计
93.6 ADS1256板级支持包(bsp_spi_ads1256)
93.7 ADS1256实际测试效果(10uV抖动)
93.8 ADS1256驱动移植和使用
93.9 实验例程设计框架
93.10 实验例程说明(MDK)
93.11 实验例程说明(IAR)
93.12 总结
93.1 初学者重要提示
- ADS1256的模拟部分供电5V,SPI数字接口电平3.3V。
- ADS1256的PGA可以编程增益支持: 1、2、4、8、16、32、64。
- ADS1256支持自动校准 (当设置了PGA,BUF使能、数据采样率时,会启动自校准)。
- ADS1256支持8通道单端ADC采集或者4通道差分采集。
- ADS1256支持正负5V差分采集,但不支持负压,使用时要注意。
- ADS1256时序操作稍有点特殊,所以本章是采用的模拟SPI控制。
- ADS1256数据手册,模块原理图(通用版)和接线图都已经放到本章教程配置例子的Doc文件里。
- ADC 的专业术语诠释文档,推荐大家看看:http://www.armbbs.cn/forum.php?mod=viewthread&tid=89414 。
- 测试时,务必使用外置电源为开发板供电,因为ADS1256需要5V供电电压。板子上插入ADS1256模块时,注意对齐。
93.2 ADC结构分类
这里将六种DAC结构为大家做个普及。注,这些知识翻译自美信和TI的英文技术手册。
93.2.1 SAR ADC(逐次逼近型)
逐次逼近型ADC通常是中高分辨率的首选架构,采样速率通常低于5Msps。SAR ADC最常见的分辨率范围是8位到20位,并具有低功耗和小尺寸的特点。这种组合使其非常适合各种应用,例如自动测试设备,电池供电的设备,数据采集系统,医疗仪器,电机和过程控制,工业自动化,电信,测试和测量,便携式系统,高速闭环系统和窄带接收器。
93.2.2 Sigma-Delta ADC
Sigma-delta ADC主要用于低速应用中,该应用需要通过过采样来权衡速度和分辨率,然后进行滤波以降低噪声。24位sigma-delta转换器用于自动化测试设备,高精度便携式传感器,医疗和科学仪器以及地震数据采集等应用中。
93.2.3 Integrating ADC
集成ADC提供高分辨率,并且可以提供良好的线路频率和噪声抑制。集成架构提供了一种新颖且直接的方法,可将低带宽模拟信号转换为数字表示形式。这些类型的转换器通常包括用于LCD或LED显示器的内置驱动器,并且在许多便携式仪器应用中都可以找到,包括数字面板表和数字万用表。
93.2.4 FLASH ADC
Flash ADC是将模拟信号转换为数字信号的最快方法。它们适用于需要非常大带宽的应用。然而,闪存转换器功率高,具有相对较低的分辨率,并且可能非常昂贵。这将它们限制在通常无法以其他任何方式解决的高频应用中。示例包括数据采集,卫星通信,雷达处理,示波器和高密度磁盘驱动器。
93.2.5 Pipelined ADC
流水线ADC已成为最受欢迎的ADC体系结构,其采样率从每秒几兆采样(MS / s)到最高100MS / s +,分辨率为8至16位。它们提供的分辨率和采样率,可覆盖各种应用,包括CCD成像,超声医学成像,数字接收器,基站,数字视频(例如HDTV),xDSL,电缆调制解调器和快速以太网。
93.2.6 Two Step ADC
两步ADC也称为子范围转换器,有时也称为多步或half flash(比Flash架构慢)。这是Flash ADC和流水线ADC的交叉点。与Flash ADC相比,可以实现更高的分辨率或更小的裸片尺寸。
93.3 ADS1256硬件设计
这里将开发板上的ADS1256硬件接口,ADS1256模块为大家做个说明。
ADS1256的原理图论坛下载:
http://www.armbbs.cn/forum.php?mod=viewthread&tid=97547 。
93.3.1 ADS1256硬件接口
V7板子上ADS1256模块的插座的原理图如下:
实际对应开发板的位置如下:
为了方便大家更好的理解接线,下面是框图:
93.3.2 ADS1256模块
产品规格:
1、 单电源5.0V DC供电,提供正负5V信号采样功能。
2、 MCU接口:SPI。
3、 主ADC芯片:ADS1256 (全新进口原装正品)。
4、 电压基准,之前采用的LM285-2.5,现在采用的REF5025(全新进口原装正品)。
5、 输入电路带分压电阻和R-C滤波,方便客户自己变更增益范围。
6、 芯片内带可编程增益放大器,增益范围:1-64倍。
7、 芯片内部输入带缓冲放大器,可以直接连接传感器。
正面:
反面:
接线图:
93.4 ADS1256关键知识点整理(重要)
驱动ADS1256需要对下面这些知识点有个认识。
93.4.1 ADS1256基础信息
ADS1256是TI公司推出的微功耗、高精度、8通道、 24位△-∑型高性能模数转换器(ADC)。该器件提供高达23比特的无噪声精度、数据速率高达30kSPS(次采样/秒)、0.0010%非线性特性(最大值)以及众多的板上外设(输入模拟多路开关、输入缓冲器、可编程增益放大器和可编程数字滤波器等),可为设计人员带来完整而高分辨率的量测解决方案。
- 24位无数据丢失;
- 高达23比特的无噪声精度;
- 低非线性度: ±0.0010% ;
- 数据采样率可达30kSPS ;
- 采用单周期转换模式;
- 带有模拟多路开关,具有传感器接口(可配置为4路差动输入或8路单极输入) ;
- 带有输入缓冲器( BUF) ;
- 带有串行外设接口( SPI) ;
- 内含低噪声可编程增益放大器( PGA ) ,所有的PGA均具有自校准和系统校准;
- PGA= 1时,可提供高达25.3位的有效分辨率;
- PGA = 64时,可提供高达22.5位的有效分辨率;
- 模拟输入电压为5V ,数字电压为1.8~3.6V ;
- 正常模式下功耗低至38mW ,备用模式下功耗为0.4mW。
93.4.2 ADS1256常用引脚的作用
ADS1256的封装形式:
这里把常用的几个引脚做个说明:
- AVDD
模拟电源供电。
- AGND
模拟地。
- VREFN
负参考电压输入。
- VREFP
正参考电压输入。
- AINCOM
模拟公共输入。
- AIN0 – AIN7
模拟输入通道0到通道7
- SYNC/PDWN
同步,掉电输入。
- RESET
复位引脚。
- DVDD
数字电源。
- DGND
数字地。
- XTAL1,XTAL2
晶振输入端。
- CS
片选输入端。
- DRDY
数据就绪输出信号引脚。
- DOUT
数据输出。
- DIN
数据输入。
- SCLK
时钟引脚。
- D0,D1,D2,D3
通用GPIO
93.4.3 ADS1256输出电压计算公式
ADS1256的计算公式如下:
最小单位值是2 * VREF/(PGA * (2^23 − 1))
采用二进制补码表示(其实就是24bit有符号数,我们将转换结果定义为int32_t即可)。
93.4.4 ADS1256时序图
驱动ADS1256主要是两个时序图需要了解,读写时序:
- t1:SPI时钟周期:
外部晶振频率 = 7.68MHz,
时钟频率 tCLK = 1/7.68M = 0.13uS
输出数据周期 tDATA = 1 / 30K = 0.033mS (按30Ksps计算)
对SPI的时钟速度要求:
最快 4个tCLK = 0.52uS
最慢 10个tDATA = 0.3mS (按 30Ksps 计算)
- t2H,t2L :脉冲高低电平:
SCL高电平和低电平持续时间最小 200ns。
数据读取流程:
- 第1步:ADS1256_SetChannal(g_tADS1256.Channel)切换模拟通道。
- 第2步:发送SYNC同步命令。
- 第3步:唤醒。
- 第4步:读取数据。
这个过程中特别注意读取的是上次转换的数据。
93.4.5 ADS1256的增益和测量范围问题
ADS1256的增益和测量范围关系如下:
比如增益是1时,测量范围是正负5V,增益是64时,测量范围是正负78.125mV。
93.4.6 ADS1256输入缓冲器
开关输入缓冲器时,影响到的几个参数,大家需要做个了解。
开缓冲的情况下,输入参考值噪声。
关闭缓冲时的输入参考噪声:
开缓冲的情况下,有效分辨率:
关闭缓冲时的有效位数:
打开缓冲器后的输入阻抗:
关闭缓冲器后的输入阻抗:
93.4.7 ADS1256支持的采样率
ADS1256支持的采样率如下,这里特别注意,因为切换通道和读数据耗时 123微秒, 因此扫描中断模式工作时,最大速率 = DRATE_1000SPS。
93.4.8 ADS1256的多路选择器,单端和多端输入
ADS1256的8路支持是通过多路选择器实现,8路采样时是选择相应通道进行采样:
实际应用的的8路单端采样和4路差分采样效果如下:
93.5 ADS1256驱动设计
ADS1256的程序驱动框架设计如下:
有了这个框图,程序设计就比较好理解了。
93.5.1 第1步,ADS1256所涉及到的GPIO配置
这里需要把用到的GPIO时钟、GPIO引脚配置好:
/* ADS1256模块 STM32-V7开发板(示波器接口) +5V <------ 5.0V 5V供电 GND ------- GND 地 DRDY ------> PC6 准备就绪 CS <------ PC7 SPI_CS DIN <------ PG10 SPI_MOSI DOUT ------> PA5 SPI_MISO SCLK <------ PA4 SPI时钟 GND ------- GND 地 PDWN <------ PB7 掉电控制 RST <------ PC3 复位信号 NC 空脚 NC 空脚 */ #ifdef SOFT_SPI /* 软件SPI */ /* 定义GPIO端口 */ #define SCK_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define SCK_GPIO GPIOA #define SCK_PIN GPIO_PIN_4 #define SCK_1() SCK_GPIO->BSRR = SCK_PIN #define SCK_0() SCK_GPIO->BSRR = ((uint32_t)SCK_PIN << 16U) #define DIN_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE() #define DIN_GPIO GPIOG #define DIN_PIN GPIO_PIN_10 #define DIN_1() DIN_GPIO->BSRR = DIN_PIN #define DIN_0() DIN_GPIO->BSRR = ((uint32_t)DIN_PIN << 16U) #define CS_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define CS_GPIO GPIOC #define CS_PIN GPIO_PIN_7 #define CS_1() CS_GPIO->BSRR = CS_PIN #define CS_0() CS_GPIO->BSRR = ((uint32_t)CS_PIN << 16U) #define DOUT_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define DOUT_GPIO GPIOA #define DOUT_PIN GPIO_PIN_5 #define DOUT_IS_HIGH() ((DOUT_GPIO->IDR & DOUT_PIN) != 0) #define DRDY_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define DRDY_GPIO GPIOC #define DRDY_PIN GPIO_PIN_6 #define DRDY_IS_LOW() ((DRDY_GPIO->IDR & DRDY_PIN) == 0) #define DRDY_IRQn EXTI9_5_IRQn #define DRDY_IRQHandler EXTI9_5_IRQHandler /* PDWN <------ PB7 掉电控制 */ #define PWDN_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() #define PWDN_GPIO GPIOB #define PWDN_PIN GPIO_PIN_7 #define PWDN_1() PWDN_GPIO->BSRR = PWDN_PIN #define PWDN_0() PWDN_GPIO->BSRR = ((uint32_t)PWDN_PIN << 16U) /* RST <------ PC3 复位信号 */ #define RST_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define RST_GPIO GPIOC #define RST_PIN GPIO_PIN_3 #define RST_1() RST_GPIO->BSRR = RST_PIN #define RST_0() RST_GPIO->BSRR = ((uint32_t)RST_PIN << 16U) #endif /* ********************************************************************************************************* * 函 数 名: bsp_InitADS1256 * 功能说明: 配置STM32的GPIO和SPI接口,用于连接 ADS1256 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_InitADS1256(void) { #ifdef SOFT_SPI GPIO_InitTypeDef gpio_init; RST_1(); PWDN_1(); CS_1(); SCK_0(); /* SPI总线空闲时,钟线是低电平 */ DIN_1(); /* 打开GPIO时钟 */ SCK_CLK_ENABLE(); DIN_CLK_ENABLE(); CS_CLK_ENABLE(); DOUT_CLK_ENABLE(); DRDY_CLK_ENABLE(); PWDN_CLK_ENABLE(); RST_CLK_ENABLE(); /* 配置几个推完输出IO */ gpio_init.Mode = GPIO_MODE_OUTPUT_PP; /* 设置推挽输出 */ gpio_init.Pull = GPIO_NOPULL; /* 上下拉电阻不使能 */ gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; /* GPIO速度等级 */ gpio_init.Pin = SCK_PIN; HAL_GPIO_Init(SCK_GPIO, &gpio_init); gpio_init.Pin = DIN_PIN; HAL_GPIO_Init(DIN_GPIO, &gpio_init); gpio_init.Pin = CS_PIN; HAL_GPIO_Init(CS_GPIO, &gpio_init); gpio_init.Pin = PWDN_PIN; HAL_GPIO_Init(PWDN_GPIO, &gpio_init); /* DRDY 设置为输入 */ gpio_init.Mode = GPIO_MODE_INPUT; /* 设置输入 */ gpio_init.Pull = GPIO_NOPULL; /* 上下拉电阻不使能 */ gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; /* GPIO速度等级 */ gpio_init.Pin = DRDY_PIN; HAL_GPIO_Init(DRDY_GPIO, &gpio_init); gpio_init.Pin = DOUT_PIN; HAL_GPIO_Init(DOUT_GPIO, &gpio_init); #endif }
这里重点注意DRDY转换就绪引脚的配置,DRDY_IRQn和DRDY_IRQHandler不要配置错了。
93.5.2 第2步,ADS1256的8bit读写函数实现
读写函数实现如下:
/* ********************************************************************************************************* * 函 数 名: ADS1256_Send8Bit * 功能说明: 向SPI总线发送8个bit数据。 不带CS控制。 * 形 参: _data : 数据 * 返 回 值: 无 ********************************************************************************************************* */ static void ADS1256_Send8Bit(uint8_t _data) { uint8_t i; /* 连续发送多个字节时,需要延迟一下 */ ADS1256_DelaySCLK(); ADS1256_DelaySCLK(); /* ADS1256 要求 SCL高电平和低电平持续时间最小 200ns */ for(i = 0; i < 8; i++) { if (_data & 0x80) { DIN_1(); } else { DIN_0(); } SCK_1(); ADS1256_DelaySCLK(); _data <<= 1; SCK_0(); /* <---- ADS1256 是在SCK下降沿采样DIN数据, 数据必须维持 50nS */ ADS1256_DelaySCLK(); } } /* ********************************************************************************************************* * 函 数 名: ADS1256_Recive8Bit * 功能说明: 从SPI总线接收8个bit数据。 不带CS控制。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static uint8_t ADS1256_Recive8Bit(void) { uint8_t i; uint8_t read = 0; ADS1256_DelaySCLK(); /* ADS1256 要求 SCL高电平和低电平持续时间最小 200ns */ for (i = 0; i < 8; i++) { SCK_1(); ADS1256_DelaySCLK(); read = read<<1; SCK_0(); if (DOUT_IS_HIGH()) { read++; } ADS1256_DelaySCLK(); } return read; }
读写的实现完全按照下面的时序实现:
这里主要注意时间实现:
t1:SPI时钟周期:
外部晶振频率 = 7.68MHz,
时钟频率 tCLK = 1/7.68M = 0.13uS
输出数据周期 tDATA = 1 / 30K = 0.033mS (按30Ksps计算)
对SPI的时钟速度要求:
最快 4个tCLK = 0.52uS
最慢 10个tDATA = 0.3mS (按 30Ksps 计算)
t2H,t2L :脉冲高低电平:
SCL高电平和低电平持续时间最小 200ns。
93.5.3 第3步,ADS1256的24bit ADC数据读取
实现代码如下:
/* ********************************************************************************************************* * 函 数 名: ADS1256_ReadData * 功能说明: 读ADC数据 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static int32_t ADS1256_ReadData(void) { uint32_t read = 0; CS_0(); /* SPI片选 = 0 */ ADS1256_Send8Bit(CMD_RDATA); /* 读数据的命令 */ ADS1256_DelayDATA(); /* 必须延迟才能读取芯片返回数据 */ /* 读采样结果,3个字节,高字节在前 */ read = ADS1256_Recive8Bit() << 16; read += ADS1256_Recive8Bit() << 8; read += ADS1256_Recive8Bit() << 0; CS_1(); /* SPI片选 = 1 */ /* 负数进行扩展。24位有符号数扩展为32位有符号数 */ if (read & 0x800000) { read += 0xFF000000; } return (int32_t)read; }
这段代码里面关键是24bit数据的补码处理。对负数进行扩展,24位有符号数扩展为32位有符号数。
93.5.4 第3步,ADS1256增益和采样率配置
代码如下:
/* ********************************************************************************************************* * 函 数 名: ADS1256_CfgADC * 功能说明: 配置ADC参数,增益和数据输出速率 * 形 参: _gain : 支持增益参数。 * ADS1256_GAIN_1 * ADS1256_GAIN_2 * ADS1256_GAIN_4 * ADS1256_GAIN_8 * ADS1256_GAIN_16 * ADS1256_GAIN_32 * ADS1256_GAIN_64 * * _drate : 数据输出速率,不推荐超过1000SPS * ADS1256_30000SPS * ADS1256_15000SPS * ADS1256_7500SPS * ADS1256_3750SPS * ADS1256_2000SPS * ADS1256_1000SPS * ADS1256_500SPS * ADS1256_100SPS * ADS1256_60SPS * ADS1256_50SPS * ADS1256_30SPS * ADS1256_25SPS * ADS1256_15SPS * ADS1256_10SPS * ADS1256_5SPS * ADS1256_2d5SPS * 返 回 值: 无 ********************************************************************************************************* */ void ADS1256_CfgADC(ADS1256_GAIN_E _gain, ADS1256_DRATE_E _drate) { g_tADS1256.Gain = _gain; g_tADS1256.DataRate = _drate; ADS1256_StopScan(); /* 暂停CPU中断 */ ADS1256_ResetHard(); /* 硬件复位 */ ADS1256_WaitDRDY(); { uint8_t buf[4]; /* 暂存ADS1256 寄存器配置参数,之后连续写4个寄存器 */ buf[0] = (0 << 3) | (1 << 2) | (1 << 1); buf[1] = 0x08; /* 高四位0表示AINP接 AIN0, 低四位8表示 AINN 固定接 AINCOM */ buf[2] = (0 << 5) | (0 << 2) | (_gain << 1); /* 因为切换通道和读数据耗时 123uS, 因此扫描中断模式工作时,最大速率 = DRATE_1000SPS */ buf[3] = s_tabDataRate[_drate]; // DRATE_10SPS; /* 选择数据输出速率 */ CS_0(); /* SPI片选 = 0 */ ADS1256_Send8Bit(CMD_WREG | 0); /* 写寄存器的命令, 并发送寄存器地址 */ ADS1256_Send8Bit(0x03); /* 寄存器个数 - 1, 此处3表示写4个寄存器 */ ADS1256_Send8Bit(buf[0]); /* 设置状态寄存器 */ ADS1256_Send8Bit(buf[1]); /* 设置输入通道参数 */ ADS1256_Send8Bit(buf[2]); /* 设置ADCON控制寄存器,增益 */ ADS1256_Send8Bit(buf[3]); /* 设置输出数据速率 */ CS_1(); /* SPI片选 = 1 */ } bsp_DelayUS(50); }
这个函数主要配置了4个ADS1256寄存器。
- 设置状态寄存器:
程序中的配置为:buf[0] = (0 << 3) | (1 << 2) | (1 << 1) ,意思是LSB传输,自动校准,使能模拟输入缓冲。
- 设置输入通道参数
程序中的配置为:buf[1] = 0x08, 高四位0表示AINp接通的 AIN0, 低四位8表示 AINn接通的 AINCOM。AINp和AINn表示当前的多路选择器选通的AIN0:
- 设置ADCON控制寄存器,主要用于增益设置
程序中的配置为:buf[2] = (0 << 5) | (0 << 2) | (_gain << 1), 意思是关闭CLKOUT引脚输出,关闭传感器检测,设置增益为形参_gain。
- 设置ADC采样率
程序中的配置为:buf[3] = s_tabDataRate[_drate],用于设置波特率:
static const uint8_t s_tabDataRate[ADS1256_DRATE_MAX] = { 0xF0, /* 复位时缺省值 */ 0xE0, 0xD0, 0xC0, 0xB0, 0xA1, 0x92, 0x82, 0x72, 0x63, 0x53, 0x43, 0x33, 0x20, 0x13, 0x03 }; typedef enum { ADS1256_30000SPS = 0, ADS1256_15000SPS, ADS1256_7500SPS, ADS1256_3750SPS, ADS1256_2000SPS, ADS1256_1000SPS, ADS1256_500SPS, ADS1256_100SPS, ADS1256_60SPS, ADS1256_50SPS, ADS1256_30SPS, ADS1256_25SPS, ADS1256_15SPS, ADS1256_10SPS, ADS1256_5SPS, ADS1256_2d5SPS, ADS1256_DRATE_MAX }ADS1256_DRATE_E;
93.5.5 第4步,ADS1256启动采样
代码实现如下
/* ********************************************************************************************************* * 函 数 名: ADS1256_StartScan * 功能说明: 将 DRDY引脚 (PC6 )配置成外部中断触发方式, 中断服务程序中扫描8个通道的数据。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void ADS1256_StartScan(void) { /* PC6 外部中断,BUSY 配置 BUSY 作为中断输入口,下降沿触发 */ { GPIO_InitTypeDef GPIO_InitStructure; DRDY_CLK_ENABLE(); /* 打开GPIO时钟 */ GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Pin = DRDY_PIN; HAL_GPIO_Init(DRDY_GPIO, &GPIO_InitStructure); HAL_NVIC_SetPriority(DRDY_IRQn, 2, 0); HAL_NVIC_EnableIRQ(DRDY_IRQn); } /* 开始扫描前, 清零结果缓冲区 */ { uint8_t i; g_tADS1256.Channel = 0; for (i = 0; i < 8; i++) { g_tADS1256.AdcNow[i] = 0; } } }
代码比较简单,主要是配置PC6的EXTI外部中断,并初始化变量。
93.5.6 第5步,ADS1256的中断处理(8通道数据读取)
代码如下:
/* ********************************************************************************************************* * 函 数 名: EXTI9_5_IRQHandler * 功能说明: 外部中断服务程序. 此程序执行时间约 123uS * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ #ifdef EXTI9_5_ISR_MOVE_OUT /* bsp.h 中定义此行,表示本函数移到 stam32f4xx_it.c。 避免重复定义 */ void EXTI9_5_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); } /* ********************************************************************************************************* * 函 数 名: EXTI9_5_IRQHandler * 功能说明: 外部中断服务程序入口。PI6 / AD7606_BUSY 下降沿中断触发 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_6) { ADS1256_ISR(); } } #endif /* ********************************************************************************************************* * 函 数 名: ADS1256_ISR * 功能说明: 定时采集中断服务程序 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void ADS1256_ISR(void) { /* 读取采集结构,保存在全局变量 */ ADS1256_SetChannal(g_tADS1256.Channel); /* 切换模拟通道 */ bsp_DelayUS(5); ADS1256_WriteCmd(CMD_SYNC); bsp_DelayUS(5); ADS1256_WriteCmd(CMD_WAKEUP); bsp_DelayUS(25); if (g_tADS1256.Channel == 0) { g_tADS1256.AdcNow[7] = ADS1256_ReadData(); /* 注意保存的是上一个通道的数据 */ } else { g_tADS1256.AdcNow[g_tADS1256.Channel-1] = ADS1256_ReadData(); /* 注意保存的是上一个通道的数据 */ } if (++g_tADS1256.Channel >= 8) { g_tADS1256.Channel = 0; } }
中断服务程序的代码完全是按照下面的时序时序:
- 第1步:ADS1256_SetChannal(g_tADS1256.Channel)切换模拟通道。
- 第2步:发送SYNC同步命令。
- 第3步:唤醒。
- 第4步:读取数据。
这个过程中特别注意读取的是上次转换的数据。
93.6 ADS1256板级支持包(bsp_spi_ads1256.c)
ADS1256驱动文件bsp_spi_ads1256.c主要实现了如下几个API供用户调用:
- bsp_InitADS1256
- ADS1256_CfgADC
- ADS1256_StartScan
- ADS1256_SetChannal
- ADS1256_SetDiffChannal
93.6.1 函数bsp_InitADS1256
函数原型:
void bsp_InitADS1256(void)
函数描述:
主要用于ADS1256的初始化。
93.6.2 函数ADS1256_CfgADC
函数原型:
void ADS1256_CfgADC(ADS1256_GAIN_E _gain, ADS1256_DRATE_E _drate)
函数描述:
用于配置ADS1256的增益和采样率。
函数参数:
- 第1个参数用于设置增益,支持的参数如下:
ADS1256_GAIN_1
ADS1256_GAIN_2
ADS1256_GAIN_4
ADS1256_GAIN_8
ADS1256_GAIN_16
ADS1256_GAIN_32
ADS1256_GAIN_64
- 第2个参数用于设置采样率,支持的参数如下:
ADS1256_30000SPS
ADS1256_15000SPS
ADS1256_7500SPS
ADS1256_3750SPS
ADS1256_2000SPS
ADS1256_1000SPS
ADS1256_500SPS
ADS1256_100SPS
ADS1256_60SPS
ADS1256_50SPS
ADS1256_30SPS
ADS1256_25SPS
ADS1256_15SPS
ADS1256_10SPS
ADS1256_5SPS
ADS1256_2d5SPS
93.6.3 函数ADS1256_StartScan
函数原型:
void ADS1256_StartScan(void)
函数描述:
此函数用于启动扫描,采样的中断方式。
93.6.4 函数ADS1256_SetChannal
函数原型:
static void ADS1256_SetChannal(uint8_t _ch)
函数描述:
此函数用于设置单端采样的通道。
函数参数:
- 第1个参数支持0到7,0表示采样的通道0, 1表示采样的通道1,依次类推,范围0-7,共8个通道。
93.7 ADS1256实际测量效果(10uV抖动)
测试LM285-2.5V稳压效果,抖动40uV:
测试干电池效果,抖动10uV左右,注意,这个级别的抖动容易受环境温度的影响,特别是开关空调,最明显。
93.8 ADS1256驱动移植和使用
移植步骤如下:
- 第1步:复制bsp_spi_ads1256.c和bsp_spi_ads1256.h到自己的工程目录,并添加到工程里面。
- 第2步:根据使用的SPI引脚,DRDY就绪引脚,RST复位引脚,修改bsp_spi_ads1256.c开头的宏定义。
/* 定义GPIO端口 */ #define SCK_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define SCK_GPIO GPIOA #define SCK_PIN GPIO_PIN_4 #define SCK_1() SCK_GPIO->BSRR = SCK_PIN #define SCK_0() SCK_GPIO->BSRR = ((uint32_t)SCK_PIN << 16U) #define DIN_CLK_ENABLE() __HAL_RCC_GPIOG_CLK_ENABLE() #define DIN_GPIO GPIOG #define DIN_PIN GPIO_PIN_10 #define DIN_1() DIN_GPIO->BSRR = DIN_PIN #define DIN_0() DIN_GPIO->BSRR = ((uint32_t)DIN_PIN << 16U) #define CS_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define CS_GPIO GPIOC #define CS_PIN GPIO_PIN_7 #define CS_1() CS_GPIO->BSRR = CS_PIN #define CS_0() CS_GPIO->BSRR = ((uint32_t)CS_PIN << 16U) #define DOUT_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define DOUT_GPIO GPIOA #define DOUT_PIN GPIO_PIN_5 #define DOUT_IS_HIGH() ((DOUT_GPIO->IDR & DOUT_PIN) != 0) #define DRDY_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define DRDY_GPIO GPIOC #define DRDY_PIN GPIO_PIN_6 #define DRDY_IS_LOW() ((DRDY_GPIO->IDR & DRDY_PIN) == 0) #define DRDY_IRQn EXTI9_5_IRQn #define DRDY_IRQHandler EXTI9_5_IRQHandler /* PDWN <------ PB7 掉电控制 */ #define PWDN_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE() #define PWDN_GPIO GPIOB #define PWDN_PIN GPIO_PIN_7 #define PWDN_1() PWDN_GPIO->BSRR = PWDN_PIN #define PWDN_0() PWDN_GPIO->BSRR = ((uint32_t)PWDN_PIN << 16U) /* RST <------ PC3 复位信号 */ #define RST_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() #define RST_GPIO GPIOC #define RST_PIN GPIO_PIN_3 #define RST_1() RST_GPIO->BSRR = RST_PIN #define RST_0() RST_GPIO->BSRR = ((uint32_t)RST_PIN << 16U)
- 第3步:特别注意中断服务程序的入口要根据使用的DRDY引脚修改。
/* ********************************************************************************************************* * 函 数 名: EXTI9_5_IRQHandler * 功能说明: 外部中断服务程序. 此程序执行时间约 123uS * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ #ifdef EXTI9_5_ISR_MOVE_OUT /* bsp.h 中定义此行,表示本函数移到 stam32f4xx_it.c。 避免重复定义 */ void EXTI9_5_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6); } /* ********************************************************************************************************* * 函 数 名: EXTI9_5_IRQHandler * 功能说明: 外部中断服务程序入口。PI6 / AD7606_BUSY 下降沿中断触发 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_6) { ADS1256_ISR(); } } #endif
- 第4步:应用方法看本章节配套例子即可。
93.9 实验例程设计框架
通过程序设计框架,让大家先对配套例程有一个全面的认识,然后再理解细节,本次实验例程的设计框架如下:
第1阶段,上电启动阶段:
- 这部分在第14章进行了详细说明。
第2阶段,进入main函数:
- 第1部分,硬件初始化,主要是MPU,Cache,HAL库,系统时钟,滴答定时器和LED。
- 第2部分,应用程序设计部分,测试ADS1256。
93.10 实验例程说明(MDK)
配套例子:
V7-068_ADS1256(8通道带PGA的24位ADC)
实验目的:
- 学习ADS1256, 8通道带PGA的24bit ADC。
重要提示:
- 开发板请使用外置电源供电。
实验内容:
- 启动一个自动重装软件定时器,每100ms翻转一次LED2。
- 上电后插入ADS1256模块到右上角CN26(2*6P双排母), 程序每1秒打印一次8通道采样数据。
上电后串口打印的信息:
波特率 115200,数据位 8,奇偶校验位无,停止位 1。
模块插入位置:
程序设计:
系统栈大小分配:
RAM空间用的DTCM:
硬件外设初始化
硬件外设的初始化是在 bsp.c 文件实现:
/* ********************************************************************************************************* * 函 数 名: bsp_Init * 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_Init(void) { /* 配置MPU */ MPU_Config(); /* 使能L1 Cache */ CPU_CACHE_Enable(); /* STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟: - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。 - 设置NVIV优先级分组为4。 */ HAL_Init(); /* 配置系统时钟到400MHz - 切换使用HSE。 - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。 - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第xx章 */ #if Enable_EventRecorder == 1 /* 初始化EventRecorder并开启 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart(); #endif bsp_InitDWT(); /* 初始化DWT时钟周期计数器 */ bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */ bsp_InitTimer(); /* 初始化滴答定时器 */ bsp_InitLPUart(); /* 初始化串口 */ bsp_InitExtIO(); /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */ bsp_InitLed(); /* 初始化LED */ bsp_InitExtSDRAM(); /* 初始化SDRAM */ }
MPU配置和Cache配置:
数据Cache和指令Cache都开启。配置了AXI SRAM区(本例子未用到AXI SRAM)和FMC的扩展IO区。
/* ********************************************************************************************************* * 函 数 名: MPU_Config * 功能说明: 配置MPU * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MPU_Config( void ) { MPU_Region_InitTypeDef MPU_InitStruct; /* 禁止 MPU */ HAL_MPU_Disable(); /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x60000000; MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /*使能 MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* ********************************************************************************************************* * 函 数 名: CPU_CACHE_Enable * 功能说明: 使能L1 Cache * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void CPU_CACHE_Enable(void) { /* 使能 I-Cache */ SCB_EnableICache(); /* 使能 D-Cache */ SCB_EnableDCache(); }
每10ms调用一次按键处理:
按键处理是在滴答定时器中断里面实现,每10ms执行一次检测。
/* ********************************************************************************************************* * 函 数 名: bsp_RunPer10ms * 功能说明: 该函数每隔10ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些处理时间要求 * 不严格的任务可以放在此函数。比如:按键扫描、蜂鸣器鸣叫控制等。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_RunPer10ms(void) { bsp_KeyScan10ms(); }
主功能:
主程序实现如下操作:
- 启动一个自动重装软件定时器,每100ms翻转一次LED2。
- 上电后插入ADS1256模块到右上角CN26(2*6P双排母), 程序每1秒打印一次8通道采样数据。
/* ********************************************************************************************************* * 函 数 名: main * 功能说明: c程序入口 * 形 参: 无 * 返 回 值: 错误代码(无需处理) ********************************************************************************************************* */ int main(void) { uint8_t i; int32_t iTemp; float fTemp; bsp_Init(); /* 硬件初始化 */ PrintfLogo(); /* 打印例程信息到串口1 */ PrintfHelp(); /* 打印操作提示信息 */ bsp_DelayMS(500); /* 等待上电稳定,等基准电压电路稳定, bsp_InitADS1256() 内部会进行自校准 */ bsp_InitADS1256(); /* 初始化配置ADS1256. PGA=1, DRATE=30KSPS, BUFEN=1, 输入正负5V */ /* 打印芯片ID (通过读ID可以判断硬件接口是否正常) , 正常时状态寄存器的高4bit = 3 */ #if 0 { uint8_t id; id = ADS1256_ReadChipID(); if (id != 3) { printf("Error, ASD1256 Chip ID = 0x%X\r\n", id); } else { printf("Ok, ASD1256 Chip ID = 0x%X\r\n", id); } } #endif ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_30SPS); /* 配置ADC参数: 增益1:1, 数据输出速率 30Hz */ /* 启动中断扫描模式, 轮流采集8个通道的ADC数据. 通过 ADS1256_GetAdc() 函数来读取这些数据 */ ADS1256_StartScan(); bsp_StartAutoTimer(0, 1000); /* 启动1个100ms的自动重装的定时器 */ /* 进入主程序循环体 */ while (1) { bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */ if (bsp_CheckTimer(0)) /* 判断定时器超时时间 */ { /* 每隔1000ms 进来一次 */ bsp_LedToggle(2); /* 翻转LED的状态 */ /* 打印采集数据 */ for (i = 0; i < 8; i++) { /* 计算公式:2 * VREF/(PGA * (2^23 - 1)) ,这里VREF是2.5V,PGA = 1 */ /* 计算实际电压值(近似估算的),如需准确,请进行校准 */ iTemp = ((int64_t)g_tADS1256.AdcNow[i] * 2500000) / 4194303; fTemp = (float)iTemp / 1000000; printf("CH%d=%07d(%fV) ", i, g_tADS1256.AdcNow[i], fTemp); if(i == 3) { printf("\r\n"); } } printf("\r\n\r\n"); } } }
93.11 实验例程说明(IAR)
配套例子:
V7-068_ADS1256(8通道带PGA的24位ADC)
实验目的:
- 学习ADS1256, 8通道带PGA的24bit ADC。
重要提示:
- 开发板请使用外置电源供电。
实验内容:
- 启动一个自动重装软件定时器,每100ms翻转一次LED2。
- 上电后插入ADS1256模块到右上角CN26(2*6P双排母), 程序每1秒打印一次8通道采样数据。
上电后串口打印的信息:
波特率 115200,数据位 8,奇偶校验位无,停止位 1。
模块插入位置:
程序设计:
系统栈大小分配:
RAM空间用的DTCM:
硬件外设初始化
硬件外设的初始化是在 bsp.c 文件实现:
/* ********************************************************************************************************* * 函 数 名: bsp_Init * 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次 * 形 参:无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_Init(void) { /* 配置MPU */ MPU_Config(); /* 使能L1 Cache */ CPU_CACHE_Enable(); /* STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟: - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。 - 设置NVIV优先级分组为4。 */ HAL_Init(); /* 配置系统时钟到400MHz - 切换使用HSE。 - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。 - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第xx章 */ #if Enable_EventRecorder == 1 /* 初始化EventRecorder并开启 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart(); #endif bsp_InitDWT(); /* 初始化DWT时钟周期计数器 */ bsp_InitKey(); /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */ bsp_InitTimer(); /* 初始化滴答定时器 */ bsp_InitLPUart(); /* 初始化串口 */ bsp_InitExtIO(); /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */ bsp_InitLed(); /* 初始化LED */ bsp_InitExtSDRAM(); /* 初始化SDRAM */ /* 针对不同的应用程序,添加需要的底层驱动模块初始化函数 */ bsp_InitAD7606(); /* 配置AD7606所用的GPIO */ }
MPU配置和Cache配置:
数据Cache和指令Cache都开启。配置了AXI SRAM区(本例子未用到AXI SRAM)和FMC的扩展IO区。
/* ********************************************************************************************************* * 函 数 名: MPU_Config * 功能说明: 配置MPU * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void MPU_Config( void ) { MPU_Region_InitTypeDef MPU_InitStruct; /* 禁止 MPU */ HAL_MPU_Disable(); /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x60000000; MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /*使能 MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* ********************************************************************************************************* * 函 数 名: CPU_CACHE_Enable * 功能说明: 使能L1 Cache * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void CPU_CACHE_Enable(void) { /* 使能 I-Cache */ SCB_EnableICache(); /* 使能 D-Cache */ SCB_EnableDCache(); }
每10ms调用一次按键处理:
按键处理是在滴答定时器中断里面实现,每10ms执行一次检测。
/* ********************************************************************************************************* * 函 数 名: bsp_RunPer10ms * 功能说明: 该函数每隔10ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些处理时间要求 * 不严格的任务可以放在此函数。比如:按键扫描、蜂鸣器鸣叫控制等。 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ void bsp_RunPer10ms(void) { bsp_KeyScan10ms(); }
主功能:
主程序实现如下操作:
- 启动一个自动重装软件定时器,每100ms翻转一次LED2。
- 上电后插入ADS1256模块到右上角CN26(2*6P双排母), 程序每1秒打印一次8通道采样数据。
/* ********************************************************************************************************* * 函 数 名: main * 功能说明: c程序入口 * 形 参: 无 * 返 回 值: 错误代码(无需处理) ********************************************************************************************************* */ int main(void) { uint8_t i; int32_t iTemp; float fTemp; bsp_Init(); /* 硬件初始化 */ PrintfLogo(); /* 打印例程信息到串口1 */ PrintfHelp(); /* 打印操作提示信息 */ bsp_DelayMS(500); /* 等待上电稳定,等基准电压电路稳定, bsp_InitADS1256() 内部会进行自校准 */ bsp_InitADS1256(); /* 初始化配置ADS1256. PGA=1, DRATE=30KSPS, BUFEN=1, 输入正负5V */ /* 打印芯片ID (通过读ID可以判断硬件接口是否正常) , 正常时状态寄存器的高4bit = 3 */ #if 0 { uint8_t id; id = ADS1256_ReadChipID(); if (id != 3) { printf("Error, ASD1256 Chip ID = 0x%X\r\n", id); } else { printf("Ok, ASD1256 Chip ID = 0x%X\r\n", id); } } #endif ADS1256_CfgADC(ADS1256_GAIN_1, ADS1256_30SPS); /* 配置ADC参数: 增益1:1, 数据输出速率 30Hz */ /* 启动中断扫描模式, 轮流采集8个通道的ADC数据. 通过 ADS1256_GetAdc() 函数来读取这些数据 */ ADS1256_StartScan(); bsp_StartAutoTimer(0, 1000); /* 启动1个100ms的自动重装的定时器 */ /* 进入主程序循环体 */ while (1) { bsp_Idle(); /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */ if (bsp_CheckTimer(0)) /* 判断定时器超时时间 */ { /* 每隔1000ms 进来一次 */ bsp_LedToggle(2); /* 翻转LED的状态 */ /* 打印采集数据 */ for (i = 0; i < 8; i++) { /* 计算公式:2 * VREF/(PGA * (2^23 - 1)) ,这里VREF是2.5V,PGA = 1 */ /* 计算实际电压值(近似估算的),如需准确,请进行校准 */ iTemp = ((int64_t)g_tADS1256.AdcNow[i] * 2500000) / 4194303; fTemp = (float)iTemp / 1000000; printf("CH%d=%07d(%fV) ", i, g_tADS1256.AdcNow[i], fTemp); if(i == 3) { printf("\r\n"); } } printf("\r\n\r\n"); } } }
93.12 总结
本章节涉及到的知识点非常多,主要为大家讲解了ADS1256的常用玩法,如果实际项目中用到此芯片需要熟练运用。