This repository has been archived on 2024-12-31. You can view files and clone it, but cannot push or open issues or pull requests.
mfps/App/Src/ads1220.c

395 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ads1220.h"
#include "app.h"
unsigned char PolarFlag;
unsigned char Init_Config[4],channel0[8],channel1[8],channel2[8],channel3[8];
unsigned char i;
/***************************************************************************
接线顺序
*************************************************************************/
//PB0 DRDY
//PA7 MISO
#define DIN_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET); //PA7 MOSI
#define DIN_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET); //PA7 MOSI
#define SCK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET); //PA5 SCK
#define SCK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET); //PA5 SCK
#define CS_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET); //PA4 CS1
#define CS_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET); //PA4 CS1
#define ADS1220_MISO HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)
#define ADS1220_DRDY HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_4)
#define DALAY_CNT 1000
void ADS1220_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_5|GPIO_PIN_7; //PA5 PA7 端口配置 MOSI&SCLK
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; //IO口速度为50MHz
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5|GPIO_PIN_6,GPIO_PIN_SET);
GPIO_InitStructure.Pin = GPIO_PIN_6; //端口配置 PA6 MISO
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; //上拉输入
GPIO_InitStructure.Pull = GPIO_PULLUP ;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); //
GPIO_InitStructure.Pin = GPIO_PIN_4; //端口配置 PC4 DRDY
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; //上拉输入
GPIO_InitStructure.Pull = GPIO_PULLUP; //IO口速度为50MHz
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_4; //端口配置 PA4 CS
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; //IO口速度为50MHz
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/***************************************************************************
函数名称:WriteOneByte(unsigned char 命令)
用途:写入一个字节到ADS1220
*************************************************************************/
void WriteOneByte(unsigned char command)
{
unsigned char i;
for(i = 0; i < 8;i++)
{
if(command&0x80)
{
DIN_H;//ADS1220_DIN = 1
}
else
{
DIN_L;//ADS1220_DIN = 0;/
}
command <<= 1;
delay_us(10);
SCK_H;//ADS1220_SCK = 1;
delay_us(10);
SCK_L;//ADS1220_SCK = 0;
delay_us(10);
}
}
/***************************************************************************
*函数名称:ReadOneByte()
*用途:从ADS1220读取一个字节
*************************************************************************/
unsigned char ReadOneByte(void)
{
unsigned char result,i;
SCK_L;//SCLK_L;
for(i = 0;i<8; i++)
{
SCK_H;
delay_ns(1);
result <<= 0x01;
if(ADS1220_MISO)
result |= 0X01;
SCK_L;
delay_ns(1);
}
return result;
}
/***************************************************************************
*函数名称:ReadData()
*用途:从ADS1220读取数据
*************************************************************************/
unsigned long ReadData(void)
{
unsigned long adval;
unsigned char a,b,c;
CS_L;
delay_ns(10);
WriteOneByte(RDATA);
a = ReadOneByte();
b = ReadOneByte();
c = ReadOneByte();
adval = a;
adval = (adval<<8) | b;
adval = (adval<<8) | c;
delay_ns(10);
CS_H;
return adval;
}
/***************************************************************************
*函数名称:ADReset()
*用途:复位ADS1220
*************************************************************************/
void ADReset(void)
{
CS_L;
delay_ns(1);
WriteOneByte(RESET);
CS_H;
}
/***************************************************************************
函数名称:ADS1220_Init()
*用途:ADS120初始化
*************************************************************************/
void ADS1220_Init(void)
{
CS_H;
SCK_H;
DIN_H;
ADReset();
}
/***************************************************************************
*函数名称:关闭电源()
*************************************************************************/
void ADPowerDown(void)
{
CS_L;
WriteOneByte(POWERDOWN);
CS_H;
}
/***************************************************************************
*函数名称:ADStartConversion()
*用途:开始转换
*参数:
*************************************************************************/
void ADStartConversion(void)
{
CS_L;
WriteOneByte(START);
CS_H;
}
/***************************************************************************
*函数名称:ReadRegister()
*用途:从寄存器中读取数据
*参数:数据
*************************************************************************/
void ReadRegister(void)
{
unsigned char i;
unsigned long Data;
CS_L;
WriteOneByte(RREG|0x03);
for (i=0; i< 4; i++)
{
Data += ReadOneByte();
}
CS_H;
}
/***************************************************************************
*函数名:WriteRegister(unsigned char StartAddress, unsigned char NumRegs, unsigned char * pData)
*用途:向寄存器写入数据
*步骤:写地址2。写入数据
* Params NumRegs-----寄存器的数字
*************************************************************************/
void WriteRegister(unsigned char StartAddress, unsigned char NumRegs, unsigned char * pData)
{
unsigned char i;
CS_L;
WriteOneByte(WREG | (((StartAddress<<2) & 0x0c) |((NumRegs-1)&0x03)));
for (i=0; i< NumRegs; i++)
{
WriteOneByte(*pData);
pData++;
}
CS_H;
}
/***************************************************************************
函数名称:CofigAD(unsigned char channel)
*用途:设置采样通道
*参数:
*************************************************************************/
void CofigAD(unsigned char channel)
{
switch(channel)
{
case 0: Init_Config[0] = MUX_8 | PGA_0 | PGA_BYPASS_Disable;//单端模式选择通道AINP = AIN0AINN = AVSS ,PGA = 1,禁用PGA
break;
case 1: Init_Config[0] = MUX_9 | PGA_0 | PGA_BYPASS_Disable;//单端模式选择通道AINP = AIN1AINN = AVSS ,PGA = 1,禁用PGA
break;
case 2: Init_Config[0] = MUX_10 | PGA_0 | PGA_BYPASS_Disable;//单端模式选择通道AINP = AIN2AINN = AVSS,PGA = 1,禁用PGA
break;
case 3: Init_Config[0] = MUX_11 | PGA_0 | PGA_BYPASS_Disable;//单端模式选择通道AINP = AIN3AINN = AVSS,PGA = 1,禁用PGA
break;
case 4: Init_Config[0] = MUX_0 | PGA_0 | PGA_BYPASS_Disable;//差分模式选择通道AINP = AIN0AINN = AIN1默认设置,PGA = 1,禁用PGA
break;
}
Init_Config[1] = 0XC0;
Init_Config[2] = 0X00;
Init_Config[3] = 0X00;
WriteRegister(0x00,0x04,Init_Config);
ReadRegister();
}
/***************************************************************************
*函数名:GetAD(unsigned char channel)
*目的:得到结果
*************************************************************************/
float GetAD(unsigned char channel)
{
float Result_f;
unsigned long Result;
unsigned long delay_cnt = 0;
CofigAD(channel);
ADStartConversion();
while(ADS1220_DRDY)
{
delay_cnt++;
if(delay_cnt > DALAY_CNT)
{
break;
}
}
Result = ReadData();
ADPowerDown();
if(Result & 0x800000)
{
PolarFlag = 1;
Result = ~Result;
Result = Result&0xffffff;
Result = Result+1;
}
else PolarFlag =0;
// Result_f = (float)Result*1000*2.5/(1048575);//20位精度
Result_f = (float) (2.5 / 0x7fffff) * Result*1000;
Result_f =Result_f *2033/2488;
return Result_f;
}
#define DEEPTH 100
float X_ads1220_temp[DEEPTH] = {0},X_ads1220_temp_fl[DEEPTH] = {0},filter_result = 0;
char X_ads1220_cnt = 0,full_flag = 0;
float Xads1220_filter(char head, char tail) //对20维的数组进行中值滤波
{
if(full_flag == 0) return 0;
// float t = 0;
char i = 0;//,j = 0;
filter_result = 0;
for(i = 0 ;i < DEEPTH ;i++) X_ads1220_temp_fl[i] = X_ads1220_temp[i];
// for( i = 0 ;i < 19 ;i++) //对此时的20个数据进行升序排序
// {
// for(j = i+1;j < 20;j++)
// {
// if( X_ads1220_temp_fl[i] > X_ads1220_temp_fl[j] )
// {
// t = X_ads1220_temp_fl[i];
// X_ads1220_temp_fl[i] = X_ads1220_temp_fl[j];
// X_ads1220_temp_fl[j] = t;
// }
// }
// }
QuickSort(X_ads1220_temp_fl, 0, DEEPTH - 1);
for( i = head - 1;i < tail;i++) //对 head - tail 之间的数取均值
{
filter_result += X_ads1220_temp_fl[i];
}
filter_result /= (tail - head + 1);
return filter_result;
}
void Xads1220_record(void)
{
if(it_1ms_flag == 1) //每隔Xms记录一次ADC值,100维数组循环记录
{
it_1ms_flag = 0;
X_ads1220_cnt *= (X_ads1220_cnt < DEEPTH);
X_ads1220_temp[X_ads1220_cnt] = GetAD(4);
X_ads1220_cnt++;
}
if(X_ads1220_cnt == 100) full_flag = 1;
}
/*************************快速排序*************************/
void Swap(float* pa, float* pb) {
float tmp = *pa;
*pa = *pb;
*pb = tmp;
}
//hoare单趟排序 --- 左边做key
int PartSort(float* a, int left, int right) {
int keyi = left; //左边做key保存的是key的下标
while (left < right) {
//右边先走,找小
//为什么用等于呢如果keyi和right位置的值相等那么就会出现死循环
//为什么要加一个 left<right的条件呢如果数组本身就是有序的比如 1 2 3 4 5那么right就会一直向左移动并且会越界
while (left < right && a[right] >= a[keyi]) {
--right;
}
//左边后走,找大
while (left < right && a[left] <= a[keyi]) {
++left;
}
//然后交换左右
Swap(&a[left], &a[right]);
}
//当left == right的时候跳出循环交换和keyi的值
Swap(&a[keyi], &a[left]);
//返回相遇位置的下标
return left;
}
//快速排序递归实现的主框架
void QuickSort(float* a, int begin, int end) {
//子区间相等只有一个值,或者不存在,那么就是递归结束的子问题
if (begin >= end) {
return;
}
int keyi = PartSort(a, begin, end);
//递归左区间 [begin, keyi-1]
QuickSort(a, begin, keyi - 1);
//递归右区间 [keyi+1, end]
QuickSort(a, keyi + 1, end);
}
/*************************快速排序*************************/