标题:
STM32实现ADS1256进行数据电压采集程序
[打印本页]
作者:
大笨钟361
时间:
2019-3-12 15:53
标题:
STM32实现ADS1256进行数据电压采集程序
通过cubeMX配置STM32RCT6的IO口与ads1256ADC模块的连接IO口工作模式SPI,还有接受中断接受状态引脚,最终ADC采集数据经过卡尔曼滤波器滤波输出,详情请见附件
单片机源程序如下:
#include "ads1256.h"
int32_t adcVaule = 0x00;
float voltage = 0x00;
float filterVoltage = 0.0;
float filterVoltage2 = 0.0;
void delayXus(uint16_t us) {
uint16_t diff = 0xffff - 5 - us;
//设置定时器的计数值
__HAL_TIM_SET_COUNTER(&htim6, diff);
//启动定时器计数
HAL_TIM_Base_Start(&htim6);
//判定计数结束
while(diff < 0xffff - 5) {
diff = __HAL_TIM_GET_COUNTER(&htim6);
}
//延时完成关闭定时器计数
HAL_TIM_Base_Stop(&htim6);
}
/*
* 功 能:实现SPI协议总线发送一个字节的数据信息
* 参 数:待发送的数据信息
* 返回值:无
*/
void spiWriteByte(uint8_t txData) {
uint8_t tempData = 0x00;
HAL_SPI_TransmitReceive(&hspi1, &txData, &tempData, 1, 100);
}
/*
* 功 能:实现SPI协议总监接受一个字节的数据信息
* 参 数:无
* 返回值:接受到的数据信息
*/
uint8_t spiReadByte(void) {
uint8_t tempDataT = 0xff;
uint8_t tempData = 0x00;
HAL_SPI_TransmitReceive(&hspi1, &tempDataT, &tempData, 1, 100);
return tempData;
}
/*
* 功 能:向ads1256寄存器中写入一个字节的数据
* 参 数:regAdd寄存器地址 regData待写入的数据信息
* 返回值:无
*/
void spiWriteRegData(uint8_t regAdd, uint8_t regData) {
//拉低SPI协议的CS引脚
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
//等待RDY的引脚变低
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
//写入寄存地地址
spiWriteByte(WREG | (regAdd & 0x0F));
//写入即将写入数据的个数
spiWriteByte(0x00);
//写入数据信息
spiWriteByte(regData);
//拉高SPI协议的CS引脚
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
}
/*
* 功 能:初始化ads1256
* 参 数:无
* 返回值:无
*/
void ads1256Init(void) {
disableInterrupt();
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
//开启芯片的自校准
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
spiWriteByte(SELFCAL);
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
//设置ads1256的状态寄存器
spiWriteRegData(STATUS, 0x06); //数据发送高位在前 自动校准 启用buf
spiWriteRegData(MUX, MUXP_AIN0 | MUXN_AIN1); //单端模式
//设置ads1256的增益
spiWriteRegData(ADCON, GAIN_1);
//设置ads采样速率
spiWriteRegData(DRATE, RATE_30000);
//设置IO状态
spiWriteRegData(IO, 0x00);
//再次进行校准
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
//开启芯片的自校准
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
spiWriteByte(SELFCAL);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
enableInterrupt();
}
/*
* 功 能:从ads1256中读取出相关数据信息
* 参 数:下一次转换通道
* 返回值:读取到的数据信息
*/
int32_t ads1256ReadValue(uint8_t channel) {
int32_t sum = 0;
//等待准备好信号变低
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
//设置下次转换的通道
spiWriteRegData(MUX, channel);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
spiWriteByte(SYNC); //发送同步命令
delayXus(5);
spiWriteByte(WAKEUP); //发送唤醒命令
delayXus(5); //延时一下
spiWriteByte(RDATA); //发送读数据命令
delayXus(25);
sum |= (spiReadByte() << 16);
sum |= (spiReadByte() << 8);
sum |= (spiReadByte());
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
if(sum > 0x7fffff)
sum -= 0x1000000;
adcVaule = sum;
voltage = (float)(adcVaule * 5.0 / 8388607); //计算电压
printf("ADC采集数据:%0x,%f\n", adcVaule, voltage);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
return sum;
}
/*
* 功 能:实现ads的增益设置
*/
void setGain(uint8_t gain) {
disableInterrupt();
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
switch(gain) {
case 0:
spiWriteRegData(ADCON, GAIN_1);
break;
case 1:
spiWriteRegData(ADCON, GAIN_2);
break;
default:
break;
}
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
enableInterrupt();
}
/*
* 功 能:设置ads1256的采集速率
*/
void setRate(uint8_t rate) {
disableInterrupt();
while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4));
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
switch(rate) {
case 0:
spiWriteRegData(DRATE, RATE_2_5);
break;
case 1:
spiWriteRegData(DRATE, RATE_10);
break;
default:
break;
}
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
enableInterrupt();
}
/*
* 功 能:实现屏蔽所有中断函数
*/
void disableInterrupt(void) {
__set_PRIMASK(1);
}
/*
* 功 能:开启全局中断
*/
void enableInterrupt(void) {
__set_PRIMASK(0);
}
/*
* 功 能:实现外部中断回调函数
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
int32_t sum = 0x00;
disableInterrupt();
if((GPIO_Pin == GPIO_PIN_4) && (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4) == GPIO_PIN_RESET)) {
//设置下次转换的通道
spiWriteRegData(MUX, MUXP_AIN0 | MUXN_AINCOM);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET);
spiWriteByte(SYNC); //发送同步命令
delayXus(5);
spiWriteByte(WAKEUP); //发送唤醒命令
delayXus(5); //延时一下
spiWriteByte(RDATA); //发送读数据命令
delayXus(25);
sum |= (spiReadByte() << 16);
sum |= (spiReadByte() << 8);
sum |= (spiReadByte());
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);
if(sum > 0x7fffff)
sum -= 0x1000000;
adcVaule = sum;
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
}
enableInterrupt();
}
float filterlowerpass(float adc) {
//y(n) = qX(n)+(1-q)Y(n-1)
float filterVaule = 0;
static float adcold = 0;
filterVaule = 0.5 * adc + 0.5 * adcold;
adcold = adc;
return filterVaule;
}
float kalman_filter(float ADC_Value) {
float x_k1_k1, x_k_k1;
static float ADC_OLD_Value;
float Z_k;
static float P_k1_k1;
static float Q = 0.0001;
static float R = 5;
static float Kg = 0;
static float P_k_k1 = 1;
float kalman_adc;
static float kalman_adc_old = 0;
Z_k = ADC_Value;
if (abs(kalman_adc_old - ADC_Value) >= 10) {
x_k1_k1 = ADC_Value * 0.382 + kalman_adc_old * 0.618;
} else {
x_k1_k1 = kalman_adc_old;
}
x_k_k1 = x_k1_k1;
P_k_k1 = P_k1_k1 + Q;
Kg = P_k_k1 / (P_k_k1 + R);
kalman_adc = x_k_k1 + Kg * (Z_k - kalman_adc_old);
P_k1_k1 = (1 - Kg) * P_k_k1;
P_k_k1 = P_k1_k1;
ADC_OLD_Value = ADC_Value;
kalman_adc_old = kalman_adc;
return kalman_adc;
}
复制代码
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ads1256.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void) {
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM6_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
ads1256Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
voltage = (float)(adcVaule * 5.0 / 8388607); //计算电压
//filterVoltage = filterlowerpass(voltage); //低通滤波
filterVoltage2 = kalman_filter(voltage); //卡尔玛滤波
//printf("voltage:%f\n\t", voltage);
//printf("filterVoltage:%f\n\t", filterVoltage2);
//HAL_Delay(5);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100);
return ch;
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void) {
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
ADS1256_INT.7z
(268.5 KB, 下载次数: 467)
2019-3-12 18:13 上传
点击文件名下载附件
中断模式
下载积分: 黑币 -5
作者:
hylinzhi
时间:
2019-3-13 09:16
好东西,用用
作者:
ds1998
时间:
2019-3-13 12:04
感谢,试试看
作者:
yyjzd0414
时间:
2019-4-17 12:49
谢谢分享,下载下来学习下
作者:
GuTouii
时间:
2019-5-6 20:10
最近正好遇到中断的问题,看看怎么样
作者:
H823603932
时间:
2019-7-25 17:52
学习学习
作者:
icanfly0000
时间:
2020-2-29 16:46
尝试HAL驱动ADS1256一直没有成功,谢谢分享!
作者:
cnc2020
时间:
2020-2-29 22:33
good,
作者:
mcuee
时间:
2020-4-19 10:02
谢谢分享!
作者:
ZHAOMINGHUA
时间:
2020-7-16 13:32
感谢分享 驱动一直未成功
作者:
25Hzzz
时间:
2020-9-24 21:56
很棒的资料
作者:
zhouyg
时间:
2021-1-13 22:23
很好的资料,已经下载。实验下,作者很辛苦,写的代码直接对 iO操作,可移植性还是不强。
作者:
fenfafei
时间:
2021-3-22 15:08
这份源码可以使用吗
作者:
源稚雨
时间:
2021-3-28 20:32
怎么找不到io对应的端口呐
作者:
Lin_sudo
时间:
2021-7-16 15:31
很好的资料。j就是要硬件SPI
作者:
yhx'
时间:
2021-7-23 10:42
这个好用吗,为啥我用完数据只有零啊,不采集数据
作者:
多和人
时间:
2021-7-26 15:19
请问如何接线
作者:
m24
时间:
2021-7-30 14:45
能用吗?
作者:
timeabcd
时间:
2021-10-2 01:43
不知道可以移植滤波程序吗?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1