CELIS/SYSTEM/adc.c
2024-08-09 14:24:48 +08:00

546 lines
14 KiB
C
Raw 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 "adc.h"
#include "usart.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_dma.h"
#include "GUNDiscriminate.h"
#define SIZE 10
#define debug 1
// 定义一个名为MovingAverage的结构体用于存储队列的信息,未使用
typedef struct {
float queue[SIZE]; // 存储队列元素的数组
int front; // 队列的前端索引
int rear; // 队列的后端索引
int itemCount; // 队列中的元素数量
float sum; // 队列中所有元素的总和
float min; // 队列中的最小元素
float max; // 队列中的最大元素
} MovingAverage;
// 初始化队列
MovingAverage ma = {.front = 0, .rear = -1, .itemCount = 0, .sum = 0, .min = 3.4e+38f, .max = 1.2e-38f};
static uint32_t GetR_ValueNew(float AD_Value);
typedef struct
{
int count;
int count_DC;
int count_AC;
int filter_adc;
float container;
int mode;
double Res;
}ADCMode;
ADCMode Sadcmode={0,0,0,0,0,0,0};
__IO uint16_t AD_Value[AD_NUM];
static void enqueue(float data);
static double findAverage() ;
static double calculateMovingAverage(float new_value) ;
work_mode ADCtoMode(void);
work_mode GUNCheck = Normal_operation;
void Adc_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStruct;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能MDA1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO,ENABLE); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //GPIO设置为模拟输入
GPIO_Init(GPIOC, &GPIO_InitStructure);
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//连续转换
ADC_InitStruct.ADC_NbrOfChannel = AD_NUM;
ADC_InitStruct.ADC_ScanConvMode = ENABLE;//多通道
ADC_Init(ADC1,&ADC_InitStruct);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 2, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 3, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 4, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设存储器地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//半字
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//地址不自增
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;//转移地址
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//半字
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//地址自增
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向外设-SRAM
DMA_InitStructure.DMA_BufferSize = AD_NUM;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//自动重装载值
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//硬件触发
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//优先级
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);//使能通道一
ADC_DMACmd(ADC1, ENABLE);//使能ADC的DMA
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
const TempRes_TypeDef Temp_R_List[] =
{
{-40,318.406},{-39,298.823},{-38,280.326},{-37,262.967},
{-36,246.740},{-35,231.604},{-34,217.500},{-33,204.359},
{-32,192.109},{-31,180.684},{-30,170.017},{-29,160.049},
{-28,150.727},{-27,142.001},{-26,133.827},{-25,126.165},
{-24,118.980},{-23,112.237},{-22,105.909},{-21,99.9666},
{-20,94.3861},{-19,89.1441},{-18,84.2191},{-17,79.5912},
{-16,75.2417},{-15,71.1534},{-14,67.3099},{-13,63.6959},
{-12,60.2969},{-11,57.0996},{-10,54.0912},{-9 ,51.2599},
{-8 ,48.5945},{-7, 46.0844},{-6 ,43.7200},{-5 ,41.4919},
{-4 ,39.3916},{-3 ,37.4110},{-2 ,35.5426},{-1, 33.7793},
{0 ,32.1146},{1 ,30.5423},{2 ,29.0568},{3 ,27.6525},
{4 ,26.3247},{5 ,25.0685},{6 ,23.8798},{7 ,22.7543},
{8 ,21.6884},{9 ,20.6785},{10 ,19.7213},{11 ,18.8137},
{12 ,17.9529},{13 ,17.1362},{14 ,16.3611},{15 ,15.6251},
{16 ,14.9262},{17 ,14.2623},{18 ,13.6313},{19 ,13.0316},
{20 ,12.4613},{21 ,11.9190},{22 ,11.4031},{23 ,10.9121},
{24 ,10.4449},{25 ,10.0000},{26 ,9.57638},{27 ,9.17289},
{28 ,8.78847},{29 ,8.42215},{30 ,8.07300},{31 ,7.74013},
{32 ,7.42271},{33 ,7.11995},{34 ,6.83113},{35 ,6.55553},
{36 ,6.29249},{37 ,6.04139},{38 ,5.80162},{39 ,5.57263},
{40 ,5.35389},{41 ,5.14488},{42 ,4.94514},{43 ,4.75421},
{44 ,4.57166},{45 ,4.39708},{46 ,4.23009},{47 ,4.07032},
{48 ,3.91743},{49 ,3.77108},{50 ,3.63097},{51 ,3.49680},
{52 ,3.36829},{53 ,3.24517},{54 ,3.12719},{55 ,3.01411},
{56 ,2.90571},{57 ,2.80175},{58 ,2.70205},{59 ,2.60641},
{60 ,2.51463},{61 ,2.42655},{62 ,2.34200},{63 ,2.26081},
{64 ,2.18285},{65 ,2.10795},{66 ,2.03600},{67 ,1.96685},
{68 ,1.90039},{69 ,1.83649},{70 ,1.77506},{71 ,1.71597},
{72 ,1.65913},{73 ,1.60444},{74 ,1.55181},{75 ,1.50116},
{76 ,1.45240},{77 ,1.40544},{78 ,1.36023},{79 ,1.31667},
{80 ,1.27472},{81 ,1.23429},{82 ,1.19533},{83 ,1.15778},
{84 ,1.12158},{85 ,1.08667},{86 ,1.05301},{87 ,1.02055},
{88 ,0.98923},{89 ,0.95901},{90 ,0.92986},{91 ,0.90172},
{92 ,0.87456},{93 ,0.84834},{94 ,0.82303},{95 ,0.79859},
{96 ,0.77498},{97 ,0.75218},{98 ,0.73015},{99 ,0.70886},
{100,0.68830},{101,0.66842},{102,0.64921},{103,0.63064},
{104,0.61269},{105,0.59533},{106,0.57854},{107,0.56230},
{108,0.54659},{109,0.53139},{110,0.51669},{111,0.50246},
{112,0.48869},{113,0.47536},{114,0.46246},{115,0.44997},
{116,0.43787},{117,0.42616},{118,0.41481},{119,0.40382},
{120,0.39317},{121,0.38286},{122,0.37286},{123,0.36317},
{124,0.35377},{125,0.34467},
} ;
static uint16_t Temp_R_Num = sizeof(Temp_R_List) / sizeof(TempRes_TypeDef);
int16_t FindTemperature(float r_value)
{
uint16_t high = Temp_R_Num-1;
uint16_t low = 0,mid =0;
if( (r_value < Temp_R_List[high].R_Value) || (r_value > Temp_R_List[low].R_Value) )
return 0xFFF; //
while (low <= high)
{
mid = (low + high)/2;
if (r_value > Temp_R_List[mid].R_Value)
{
high = mid - 1; //降序
//low = mid+1; //升序
}
else if (r_value < Temp_R_List[mid].R_Value)
{
low = mid+1;
//high = mid - 1;
}
else
{
return Temp_R_List[mid].TemperatureValue;
}
}
return Temp_R_List[low].TemperatureValue;
}
Volt_sampldata Volt_SamplData;
Filter_variable Filter_Variable[AD_NUM];
void CC_Voltage_Sampl(void);
void TEMP1_Voltage_Sampl(void);
void GUN_TEMP_Sampl(void);
void KL30_Voltage_Sampl(void);
int16_t Get_TEMP1(void);
int16_t Get_GUN_TEMP(void);
float Get_KL30_Volt(void);
work_mode Get_WorkMode(void);
get_sampl_data Get_Sampl_Data = {
.Resistance_Value=0,
.TEMP1=Get_TEMP1,
.GUN_TEMP=Get_GUN_TEMP,
.KL30_Volt=Get_KL30_Volt,
.WorkMode=Get_WorkMode,
};
sampl_funtion Sampl_Funtion = {
.CC_Voltag=CC_Voltage_Sampl,
.TEMP1_Voltage=TEMP1_Voltage_Sampl,
.GUN_TEMP=GUN_TEMP_Sampl,
.KL30_Voltage=KL30_Voltage_Sampl,
};
void Voltage_Filter(uint16_t AD_Value,uint8_t sub,float *data)
{
if(Filter_Variable[sub].Flag)
{
if(Filter_Variable[sub].Sum!=0)
{
Filter_Variable[sub].Sum/=20;
Filter_Variable[sub].volt_data=Filter_Variable[sub].Sum*3.3/4096;
*data=Filter_Variable[sub].volt_data;
}
Filter_Variable[sub].Sum=0;
Filter_Variable[sub].Flag=0;
}
else
{
Filter_Variable[sub].Count++;
Filter_Variable[sub].Sum+=AD_Value;
if(Filter_Variable[sub].Count==20)
{
Filter_Variable[sub].Flag=1;
Filter_Variable[sub].Count=0;
}
}
}
void TEMP1_Voltage_Sampl()
{
static float data;
uint16_t value=AD_Value[ADC_TEMP1];
Voltage_Filter(value,ADC_TEMP1,&data);
Volt_SamplData.TEMP1_Data=FindTemperature(4.9/data-1);
}
void KL30_Voltage_Sampl()
{
static float data;
uint16_t value=AD_Value[VIN_AD];
Voltage_Filter(value,CC_AD,&data);
Volt_SamplData.KL30_Volt = data*11+0.25f;
}
void GUN_TEMP_Sampl()
{
static float data;
uint16_t value=AD_Value[TEMPL_AD];
Voltage_Filter(value,TEMPL_AD,&data);
Volt_SamplData.GUN_TempData=FindTemperature(4.9/data-1);
}
static uint32_t value1_z;
static uint32_t value1_v;
static uint32_t value1_flg;
static uint32_t value1_sum;
static float r;
static int mode = 0;
static int flag = 0;
void CC_Voltage_Sampl()
{
static float data;
uint16_t value=AD_Value[CC_AD];
uint16_t value1,sum;
value1 = AD_Value[CC_AD];
// printf("value1=%d\r\n",value1);
if(value1_flg)
{
value1_z = value1_z /60;
value1_v = 33000 / 4096 * value1_z;
Volt_SamplData.CC_Volt = (float)value1_v / 10000;
// printf("R %f\r\n",Volt_SamplData.CC_Volt);
// r = (7.0f*Volt_SamplData.CC_Volt*1.022/(20.0f-7.0f*Volt_SamplData.CC_Volt*1.022))*0.9414226;
// GUNCheck = ADCtoMode();
// printf("value=%.5f r=%.5f mode=%d\r\n",Volt_SamplData.CC_Volt,r,mode);
value1_flg = 0;
value1_z = 0;
value1_v = 0;
}
else
{
if(value1_sum < 60)
{
value1_z += value1;
value1_sum++;
}
else
{
value1_sum = 0;
value1_flg = 1;
}
}
}
int16_t Get_TEMP1()
{
return Volt_SamplData.TEMP1_Data;
}
int16_t Get_GUN_TEMP()
{
return Volt_SamplData.GUN_TempData;
}
float Get_KL30_Volt()
{
return Volt_SamplData.KL30_Volt;//ADS1015采样
}
work_mode last_Stat_work = Normal_operation;
work_mode This_State_work = Normal_operation;
enum GUNState SUMStateLast = NO_GUN;
work_mode Get_WorkMode()
{
return This_State_work;
}
void Scan_work(void)
{
static uint32_t GUNFLAGCount = 0;
enum GUNState GUNState= Get_R_GUNState(Get_R_Value());
work_mode SUMState = Normal_operation;
if( GUNState == AC_GUN)
{
SUMState = AC_Charging;
}
else if( (GUNState == DC_adapter)|| (GUNState == DC_GUN))
{
SUMState = DC_Charging;
}
else
{
SUMState = Normal_operation;
}
if(SUMState != last_Stat_work)
{
GUNFLAGCount = 0;
last_Stat_work = SUMState;
}
else if(SUMState == This_State_work)
{
GUNFLAGCount = 0;
}
else
{
GUNFLAGCount++;
if(GUNFLAGCount >= 2)
{
This_State_work = last_Stat_work;
SUMStateLast = GUNState;
GUNFLAGCount = 0;
}
}
}
/*函数名ADCtoMode
返回值:枚举类型 work_mode0交流 1直流 3其他
函数流程过滤前40个adc采样2.335V下拉5Ω电压以上为一个区间2.3080~2.3354.5~5Ω为一个区间
其他为一个区间进行分区计算阻值来减小电源影响,然后将计算出的阻值进行判断;
判断区间有3个0-2.1为交流4.54.3-5.15.2)为直流,<0或者2.1-4.54.3)或者>5.15.2)为未插枪
判定交直流模式*/
work_mode ADCtoMode(void)
{
if(Volt_SamplData.CC_Volt>2.335)
{
// r = (7.0f*Volt_SamplData.CC_Volt*1.0256/(20.0f-7.0f*Volt_SamplData.CC_Volt*1.0256))*0.9523809;
r = (7.0f*Volt_SamplData.CC_Volt/(20.0f-7.0f*Volt_SamplData.CC_Volt))*0.9523809;
}
else if(Volt_SamplData.CC_Volt>2.3080 &&Volt_SamplData.CC_Volt<2.335)
{
// r = (7.0f*Volt_SamplData.CC_Volt*1.022/(20.0f-7.0f*Volt_SamplData.CC_Volt*1.022))*0.9414226;
r = (7.0f*Volt_SamplData.CC_Volt/(20.0f-7.0f*Volt_SamplData.CC_Volt))*0.9414226;
}
else
{
r = (7.0f*Volt_SamplData.CC_Volt/(20.0f-7.0f*Volt_SamplData.CC_Volt));
}
Get_Sampl_Data.Resistance_Value = r;
// Sadcmode.Res = calculateMovingAverage(r);
if(r>4.3&&r<=5.5)
{
Sadcmode.count_DC++;
Sadcmode.count_AC = 0;
}
else if(r<=2.1&&r>=0.05)
{
Sadcmode.count_AC++;
Sadcmode.count_DC = 0;
}
if((r>2.1&&r<4.0)||r>5.2||r<0.05)
{
mode = 0;
return Normal_operation ;
}
if(Sadcmode.count_DC > 20 || Sadcmode.count_AC > 20)
{
if(Sadcmode.count_DC > 20)
{
Sadcmode.count_DC = 0;
mode = 2;
return DC_Charging ;
}
if(Sadcmode.count_AC > 20)
{
Sadcmode.count_AC = 0;
mode = 1;
return AC_Charging ;
}
}
return Normal_operation ;
}
float Get_R_Value(void)
{
float CC_CC2Vol = Volt_SamplData.CC_Volt;
CC_CC2Vol = (Volt_SamplData.CC_Volt*5.1f)/(5.0f-Volt_SamplData.CC_Volt);
CC_CC2Vol = (10.0*CC_CC2Vol)/(10.0-CC_CC2Vol);
Get_Sampl_Data.Resistance_Value = CC_CC2Vol;
return CC_CC2Vol;
}
/*取平均滤值算法,未使用*/
// 将新元素添加到队列中的函数
void enqueue(float data) {
// 如果队列已满
if(ma.itemCount == SIZE){
// 从总和中减去队列前端的元素
ma.sum -= ma.queue[ma.front];
// 如果队列前端的元素是最小值或最大值,则重置最小值和最大值
if(ma.queue[ma.front] == ma.min) {
ma.min = 3.4e+38f;
}
if(ma.queue[ma.front] == ma.max) {
ma.max = 1.2e-38f;
}
// 前端索引向前移动一位
ma.front++;
// 如果前端索引到达队列的末尾则将其重置为0
if(ma.front == SIZE) {
ma.front = 0;
}
// 元素数量减1
ma.itemCount--;
}
// 将新元素添加到队列的后端
ma.queue[ma.rear] = data;
// 将新元素添加到总和中
ma.sum += data;
// 如果新元素小于最小值,则更新最小值
if(data < ma.min) {
ma.min = data;
}
// 如果新元素大于最大值,则更新最大值
if(data > ma.max) {
ma.max = data;
}
// 后端索引向后移动一位
ma.rear++;
// 如果后端索引到达队列的末尾则将其重置为0
if(ma.rear == SIZE) {
ma.rear = 0;
}
// 元素数量加1
ma.itemCount++;
}
// 计算队列中元素的平均值的函数
double findAverage() {
// 如果队列中的元素数量小于等于2则返回-1因为我们需要去除最大值和最小值后再计算平均值
if(ma.itemCount <= 2) {
return -1;
}
// 返回去除最大值和最小值后的平均值
return (double)((ma.sum - ma.min - ma.max) / (ma.itemCount - 3));
}
// 添加新元素并计算平均值的函数
double calculateMovingAverage(float new_value) {
enqueue(new_value);
// 只有当队列满时,才计算平均值
if(ma.itemCount == SIZE) {
return findAverage();
}
// 如果队列未满,返回-1
return -1;
}
static uint32_t GetR_ValueNew(float AD_Value)
{
float R = (5.1f*AD_Value)/(5.0f-AD_Value);
return (uint32_t)R;
}