395 lines
10 KiB
C
395 lines
10 KiB
C
#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 = AIN0,AINN = AVSS ,PGA = 1,禁用PGA
|
||
break;
|
||
case 1: Init_Config[0] = MUX_9 | PGA_0 | PGA_BYPASS_Disable;//单端模式,选择通道AINP = AIN1,AINN = AVSS ,PGA = 1,禁用PGA
|
||
break;
|
||
case 2: Init_Config[0] = MUX_10 | PGA_0 | PGA_BYPASS_Disable;//单端模式,选择通道AINP = AIN2,AINN = AVSS,PGA = 1,禁用PGA
|
||
break;
|
||
case 3: Init_Config[0] = MUX_11 | PGA_0 | PGA_BYPASS_Disable;//单端模式,选择通道AINP = AIN3,AINN = AVSS,PGA = 1,禁用PGA
|
||
break;
|
||
case 4: Init_Config[0] = MUX_0 | PGA_0 | PGA_BYPASS_Disable;//差分模式,选择通道AINP = AIN0,AINN = 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);
|
||
}
|
||
/*************************快速排序*************************/
|
||
|
||
|
||
|
||
|