STM32_HAL_SPI_ADS1256调试记录

9 篇文章 0 订阅

1. 硬件电路

##1. 官方设计
在这里插入图片描述

因为芯片输出有两个模式,一个是输出寄存器的值,一个是直接输出ADC数据的值。

1. 1 访问寄存器通讯

寄存器的表格以及各个地址位的作用,详情可以参考数据手册

RREG:从寄存器读取
描述:从命令中指定的寄存器地址开始,输出最多 11 个寄存器的数据。读取的寄存器数将是命令的第二个字节加上 1。 如果计数超过剩余寄存器,地址将回绕到开头。
第一个命令字节:0001 rrrr 其中 rrrr 是要读取的第一个寄存器的地址。
第二个命令字节:0000 nnnn,其中 nnnn 是要读取的字节数 – 1. 有关 RREG 命令结束和 DOUT 上数据移位开始之间所需延迟的时间,请参阅时序特性:t6

在这里插入图片描述

从寄存器 01h(多路复用器)开始读取两个寄存器。第一个字符发送了0x01的地址,第二个字符发送了需要读取的两个数据。

WREG:写入寄存器
说明: 写入以命令中指定的寄存器开头的寄存器。 将被写入的寄存器数量是命令中第二个字节的值加一。
第一个命令字节:0101 rrrr 其中 rrrr 是要写入的第一个寄存器的地址。
第二个命令字节:0000 nnnn 其中 nnnn 是要写入的字节数 – 1。
数据字节:要写入寄存器的数据。

在这里插入图片描述

从03的位置写入两个数据,可以参考其中计算的方式。

1.2 读取ADC的值

在这里插入图片描述

读取数据的执行顺序如下

  1. 在可以读的时候会先有哦DRDY信号的拉低,
  2. 如果需要改变读的ADC通道,则需要通过写寄存器改换通道
  3. 监测到拉低之后发送读的指令,图上的0x03就是读ADC的指令
  4. 主机接收信号

PS:ADC的通道设置有两个模式,差分和单通道,所以需要根据不一样的使用,进行设置。

2. 软件设计

关于ADC值的计算
因为是24位的,然后1/2^24 大概计算得到 0.000000596,在代入计算ADC测量的值也大概准确

ADC 函数,总共写了三个函数,一个读寄存器
ADS1256_Read:读寄存器
ADS1256_Write:写寄存器
ADS1256_Read_ADC_data:读取ADC的数据

2. 1 ads1256.C

#include <stdio.h>
#include "main.h"
#include "ADS1256.h"

extern SPI_HandleTypeDef hspi3;
/*
功能:读取寄存器中的数值
address: start address
size ; 读多少位
recv_buf ; 数据的地址
*/
void ADS1256_Read(uint8_t address, uint8_t size,uint8_t *recv_buf )
{
	address = 0x10 + address;
    uint8_t send_data[2] = {address,size-1};   //待发送数据,命令+地址
	//CS
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);//low
	if (HAL_OK == HAL_SPI_Transmit(&hspi3, send_data, 2, 100))
	{
			if(HAL_OK ==  HAL_SPI_Receive(&hspi3, recv_buf, size, 100))
			{}
	}
	//CS
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);//high
}
/*写寄存器*/
void ADS1256_Write(uint8_t address,uint8_t number)
{
    uint8_t send_data[4] = {0x50+address,0x00,number};   
	while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0);
	//CS
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);//low
		
	if (HAL_OK == HAL_SPI_Transmit(&hspi3, send_data, 3, 100))
	{		}
	while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0);
	//CS
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);//high
}

/*
功能:读取ADC的值
*/
void ADS1256_Read_ADC_data(uint8_t COMMAND ,uint8_t *recv_buf)
{
    uint8_t send_data[1] = {0X01};   //待发送数据,命令+地址
		//等待准备好
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0);
		
	//CS
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);//low
	if (HAL_OK == HAL_SPI_Transmit(&hspi3, send_data, 1, 100))
	{
			if(HAL_OK ==  HAL_SPI_Receive(&hspi3, recv_buf, 0x03, 100))
			{
			}
	}
		
	//CS
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);//high

}





2.2 ads1256.h

#ifndef __ADS1256_H_
#define	__ADS1256_H_

#include "main.h"


void ADS1256_Init(void);   //初始化ADS1256

void ADS1256_Read(uint8_t address, uint8_t size,uint8_t *recv_buf );


void ADS1256_Write(uint8_t address,uint8_t number);
void ADS1256_Read_ADC_data(uint8_t COMMAND,uint8_t *recv_buf);
#endif



main.c

大概主函数使用的代码就是如下,可以参考其中的逻辑


#include <stdio.h>

#ifdef __GNUC__
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
  HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);//阻塞方式打印
  return ch;
}
//使用printf显示16进制数
//使用printf显示16进制数
void UART0_ShowHex(uint8_t *buf,uint8_t len)
{
    uint8_t i;
    printf("hex = ");
    for( i = 0; i < len; i++){
        printf(" %02X",buf[i]); //使用前导0补齐
        //printf(" %2X",buf[i]);  //使用前导空格补齐
        //printf(" %X",buf[i]);  //输出最短的16进制格式
    }
    printf( "\r\n");
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_SPI3_Init();
  MX_USART1_UART_Init();
	
	//这个init是空的,没有写,只是预留
  ADS1256_Init();
	
  while (1)
  {
		unsigned int sum=0;
		unsigned int sum1=0;
		unsigned int sum2=0;
		float Volts;
		
		
		uint8_t SPI_Buffer_Read[13] = {0};
		
		uint8_t ADC_Read[5] = {0};
		
		
		printf("start*****************************************\r\n");
	
		ADS1256_Write(0x01,0x08);//AIN0
		HAL_Delay(2);
		ADS1256_Read_ADC_data( 0x01,ADC_Read);
		sum |= (ADC_Read[0]<<16);
		sum |= (ADC_Read[1]<<8);		
		sum |= (ADC_Read[2]);	
		Volts = sum*0.000000596;
		printf("AIN0 = %.4fV  \r\n",Volts);
//		UART0_ShowHex(ADC_Read, 5);	
//		ADS1256_Read(0x00,0X0B,SPI_Buffer_Read);
//		UART0_ShowHex(SPI_Buffer_Read, 13);				

		ADS1256_Write(0x01,0x18);//AIN1
		HAL_Delay(2);
		ADS1256_Read_ADC_data( 0x01,ADC_Read);
		sum1 |= (ADC_Read[0]<<16);
		sum1 |= (ADC_Read[1]<<8);		
		sum1 |= (ADC_Read[2]);	
		Volts = sum1*0.000000596;
		printf("AIN1 = %.4fV  \r\n",Volts);
//		UART0_ShowHex(ADC_Read, 5);				
//		ADS1256_Read(0x00,0X0B,SPI_Buffer_Read);
//		UART0_ShowHex(SPI_Buffer_Read, 13);		
	
		
		
		ADS1256_Write(0x01,0x28);//AIN2
		HAL_Delay(2)	;	
		ADS1256_Read_ADC_data( 0x01,ADC_Read);
		sum2 |= (ADC_Read[0]<<16);
		sum2 |= (ADC_Read[1]<<8);		
		sum2 |= (ADC_Read[2]);	
		Volts = sum2*0.000000596;
		printf("AIN2 = %.4fV  \r\n",Volts);
//		UART0_ShowHex(ADC_Read, 5);		
//		ADS1256_Read(0x00,0X0B,SPI_Buffer_Read);
//		UART0_ShowHex(SPI_Buffer_Read, 13);		
		
		HAL_Delay(2000);

				
  }
}

PS: BUG的解决,如果测量结果不准确,需要确认在ADC的输入端加上电容,会解决部分的测量读数错误的问题,推荐容值0.1uF

  • 6
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
STM32单片机STM32F429)读写(8通道带PGA的24位ADC)ADS1256软件例程源码,可以做为你的学习设计参考。 int main(void) { uint8_t i; bsp_Init(); PrintfLogo(); /* 打印例程Logo到串口1 */ bsp_DelayMS(100); /* 等待上电稳定,等基准电压电路稳定, 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, 数据输出速率 1KHz */ ADS1256_StartScan(); /* 启动中断扫描模式, 轮流采集8个通道的ADC数据. 通过 ADS1256_GetAdc() 函数来读取这些数据 */ while (1) { bsp_Idle(); /* 空闲时执行的函数,比如喂狗. 在bsp.c中 */ /* 打印采集数据 */ for (i = 0; i < 8; i++) { int32_t iTemp; iTemp = ((int64_t)g_tADS1256.AdcNow[i] * 2500000) / 4194303; /* 计算实际电压值(近似估算的),如需准确,请进行校准 */ if (iTemp < 0) { iTemp = -iTemp; printf("%d=%6d,(-%d.%03d %03d V) ", i, g_tADS1256.AdcNow[i], iTemp /1000000, (iTemp%1000000)/1000, iTemp%1000); } else { printf("%d=%6d,( %d.%03d %03d V) ", i, g_tADS1256.AdcNow[i], iTemp/1000000, (iTemp%1000000)/1000, iTemp%1000); } } printf("\r\n"); bsp_DelayMS(500); /* 每隔500ms 输出一次数据 */ } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值