TJ-WW03-H03/APP_smoke_N_V1.3/HARDWARE/ADC/adc_dma_multichanit.c

560 lines
16 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.

////////////////////////////////////////////////////////////////////////////////
/// @file adc_dma_multichanit.c
/// @author AE TEAM
/// @brief Multichannel sampling using DMA.The final sampling results
/// (ADCVolatge) are viewed through simulation.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////
// Define to prevent recursive inclusion
#define _ADC_DMA_MultiChanIT_C_
// Files includes
#include "adc_dma_multichanit.h"
#include "public.h"
#include "math.h"
#include "sim_eeprom.h"
#include "key.h"
#include "pid.h"
#include "tim3_pwm_output.h"
#include "fpc.h"
//#include "delay.h"
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup MM32_Hardware_Abstract_Layer
/// @{
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ADC_DMA_MULTICHANIT
/// @{
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup ADC_Exported_Functions
/// @{
vu32 adc_value = 0;
vu8 ADCflag = 0;
vu16 varADCavarage[AVERAGELEN][ADCSCANNUM];
////////////////////////////////////////////////////////////////////////////////
/// @brief Configure sampling GPIO with single conversion mode for ADC1
/// @note Note the corresponding channel selection.
/// @param ADC_Channel_x: The sampling channel
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void ADCConfig(ADCCHANNEL_TypeDef adc_channel)
{
if( ADC_Channel_0 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_0);
ADCSingleChannelInit(ADC_Channel_0);
}
else if( ADC_Channel_1 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_1);
}
else if( ADC_Channel_2 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_2);
}
else if( ADC_Channel_3 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_3);
}
else if( ADC_Channel_4 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_4);
}
else if( ADC_Channel_5 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_5);
}
else if( ADC_Channel_6 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_6);
}
else if( ADC_Channel_7 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOA, GPIO_Pin_7);
}
else if( ADC_Channel_8 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOB, GPIO_Pin_0);
}
else if( ADC_Channel_9 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOB, GPIO_Pin_1);
}
else if( ADC_Channel_11 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOB, GPIO_Pin_4);
}
else if( ADC_Channel_12 == adc_channel ) {
GPIO_PinConfigAnalog(GPIOB, GPIO_Pin_7);
}
ADCSingleChannelInit(adc_channel);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Configure the ADC1 single conversion mode to correspond to the PIN
/// @note It must be careful of the Chip Version.
/// @param GPIOn: The sampling GPIOn corresponds to the port
/// @param gpio_pin: The sampling gpio_pin corresponds to the pin.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void GPIO_PinConfigAnalog(GPIO_TypeDef* GPIOn, u16 gpio_pin)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(GPIOn == GPIOA) {
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
}
if(GPIOn == GPIOB) {
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOB, ENABLE);
}
if(GPIOn == GPIOC) {
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOC, ENABLE);
}
if(GPIOn == GPIOD) {
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOD, ENABLE);
}
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = gpio_pin;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOn, &GPIO_InitStruct);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Configure ADC1 single conversion mode<64><65>external interrupt source
/// interrupt priority
/// @note Configure parameters according to requirements.
/// @param ADC_Channel_x: The sampling channel
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void ADCInit(void)
{
ADC_InitTypeDef ADC_InitStruct;
ADC_StructInit(&ADC_InitStruct);
//Initialize PA1 to analog input mode
//Enable ADC clock
RCC_APB2PeriphClockCmd(RCC_APB2ENR_ADC1, ENABLE);
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
//ADC prescale factor
ADC_InitStruct.ADC_PRESCARE = ADC_PCLK2_PRESCARE_8;
//Set ADC mode to continuous conversion mode
ADC_InitStruct.ADC_Mode = ADC_CR_SCAN;//ADC_Mode_Continue;
//AD data right-justified
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_Init(ADC1, &ADC_InitStruct);
//Enable ADCDMA
ADC_DMACmd(ADC1, ENABLE);
//Enable AD conversion
ADC_Cmd(ADC1, ENABLE);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Configure ADC1 single conversion mode<64><65>external interrupt source
/// interrupt priority
/// @note Configure parameters according to requirements.
/// @param ADC_Channel_x: The sampling channel
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void ADCSingleChannelInit(ADCCHANNEL_TypeDef ADC_Channel_x)
{
//Enable the channel
ADC_RegularChannelConfig(ADC1, ADC_Channel_x, 0, ADC_Samctl_240_5);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief DMA and interrupt priority configuration
/// @note Configure parameters according to requirements.
/// @param None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void DMAInit(void)
{
DMA_InitTypeDef DMA_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBENR_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel1);
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_PeripheralBaseAddr = (u32) & (ADC1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)&ADCValue;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = ADCSCANNUM;
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_InitStruct.DMA_Auto_reload = DMA_Auto_Reload_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStruct);
DMA_Cmd(DMA1_Channel1, ENABLE);
//DMA interrupt initialization
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0x02;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Process values read from DMA,ADC second-order filter,
/// when the filter is completed erection filter end marker.
/// @note None.
/// @param None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
//u32 lastAD_value[ADCSCANNUM ] = {0,0,0};
//u8 last_count[ADCSCANNUM] = {0,0,0};
u8 onetimes = 0;
//修改为中值滤波
void ADCFilter(void)
{
u16 chan;
u16 cntFilter;
u32 lADCFilterValue[ADCSCANNUM] = {0,0,0,0};
for(chan = 0; chan < ADCSCANNUM; chan++)
{
for(cntFilter = 0; cntFilter < AVERAGELEN; cntFilter++)
{
lADCFilterValue[chan] += varADCavarage[cntFilter][chan];
}
ADCFilterValue[chan] = lADCFilterValue[chan] / AVERAGELEN;
//printf("\nADCFilterValue[chan]:%d\n",ADCFilterValue[chan]);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Transform the optimized data to get the final result.
/// @note None.
/// @param None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
float R_1 = 0;
float R_2 = 0 ;
float current_temp_1 = 0;
u32 current_temp_2 = 0;
u16 count = 0;
void Get_ADCVolatge(void)
{
u16 chan;
float sub_1 = 0;
float sub_2 = 0;
float T_1 = 0;
float T_2 = 0;
WWDG_SetCounter(0x7e);
for(chan = 0; chan < ADCSCANNUM; chan++)
{
ADCVolatge[chan] = ((float)ADCFilterValue[chan] / 4095) * REFVOLATGE;
//printf("\nADCVolatge[%d]:%f\n",chan, ADCVolatge[chan]);
}
//printf("\nV:%f\n", ADCVolatge[2] * 2);
sub_1 = (ADCVolatge[1] / 50 )/ 0.01f; //电流 电压/0.003欧姆电阻
// printf("\nADCVolatge[1]:%f\n",ADCVolatge[1]);
//printf("\nsub_1:%f\n", sub_1); //2024年5月8日11:13:20 0.3 误差补偿
R_1 = (ADCVolatge[2] * 2) / sub_1 - 0.01 + 0.3;//ADCVolatge[1] / sub_1;
g_work.r_value = R_1 * 1000;
//printf("\nR_1:%f\n", R_1);
//printf("\ng_work.m_set_other_hot.TCR_vlaue:%d\n",g_work.m_set_other_hot.TCR_vlaue);
if( g_work.m_work_flag._nor_stand_flag == 0 )
{
T_1 = ( R_1 - (float)g_work.m_set_other_hot.normal_R_Value/ 1000.0f) / ( (float)g_work.m_set_other_hot.TCR_vlaue / 1000000.0f *g_work.m_set_other_hot.normal_R_Value/1000.0f );
current_temp_1 = (g_work.m_set_other_hot.normal_T_Value + T_1) ;
g_work.temp_1 = current_temp_1 ;
// printf("\ng_work.m_set_other_hot.TCR_vlaue:%d\n",g_work.m_set_other_hot.TCR_vlaue);
//printf("\ng_work.temp_1:%f\n",g_work.temp_1);
}
else // 开始低温标定
{
if( g_work.work_conditon == STANDY ) // 待机模式
{
if ( g_work.m_work_flag._nor_stand_flag == 1 )
{
if(g_work.temp_delay > 1500)
{
if( R_1 > 0.7 && R_1 < 0.9 )
{
g_work.m_set_other_hot.normal_R_Value = R_1 * 1000;
send_TCR(g_work.m_set_other_hot.normal_R_Value); // 开始标定标定标志
flash_wite();
}
else
{
send_ack(2); // 标定错误;
}
}
}
}
}
if( g_work.m_work_flag._high_stand_flag == 1) //高温标定
{
flash_wite();
g_work.m_work_flag._high_stand_flag = 0;
}
if(g_work.check_info == 1)
{
send_TCR_value(g_work.m_set_other_hot.TCR_vlaue,g_work.m_set_other_hot.normal_R_Value,g_work.m_set_other_hot.normal_T_Value);
g_work.check_info = 0;
}
pid.curr = g_work.temp_1;
if(g_work.work_conditon == STANDY)
{
//由于误差问题,需要校正电压。
g_work.V_real_Value = (ADCVolatge[2]) * 100 * 2;
}
else
{
g_work.V_real_Value = (ADCVolatge[2]) * 100 * 2;
}
//printf("\ng_work.V_real_Value:%d\n",g_work.V_real_Value);
if( g_work.m_time._work_time > 500 )
{
g_work.m_time._work_time = 0;
// 电池温度 判断 以及预警
if( ADCVolatge[0] < 0.901 ) // 60 22k
{
if( ADCVolatge[0] < 0.454 ) // 80 10k
{
if( V_5_V == 0 )
{
if( g_work.power == 1 )
{
if( g_work.err_fault == NO_WARING )
{
g_work.m_time._Sleep_time = 0;
g_work.err_fault = BATT_HIG_ERR;
}
}
}
}
g_work.m_work_flag.chargeflag = NOCHARGE;
}
else if( ADCVolatge[0] > 1.240f ) // 50 33K
{
if( g_work.work_conditon == STANDY ) // 待机的情况下充电
{
g_work.m_work_flag.chargeflag = CHARGE;
}
else
{
g_work.m_work_flag.chargeflag = NOCHARGE;
}
}
if ( ADCVolatge[0] > 3.901f ) // 0 355K`
{
g_work.m_work_flag.zero_T_flag = 1;
}
else
{
g_work.m_work_flag.zero_T_flag = 0;
}
if( g_work.m_work_flag.chargeflag == CHARGE )
{
if( g_work.power == 1 )
{
Charge_ON();
}
else
{
Charge_OFF();
}
}
else
{
Charge_OFF();
}
}
}
//电量达到100%时 ,白灯长亮. 4.35
//电量为70%-99%之间时,白灯常亮
//电量为30%-69%之间时,蓝灯常亮
//电量为1-29%之间时,红灯闪烁
// 0: 白灯
// 1蓝灯
// 2红灯
// 3红灯闪
void V_Conditon() // 电压判断
{
if(g_work._write_v_ok == 1)
{
//printf("\ng_work.m_conditon.m_conditon.V_conditon:%d\n",g_work.m_conditon.m_conditon.V_conditon);
//printf("\ng_work.V_real_Value:%d\n",g_work.V_real_Value);
//printf("\nOK!\n");
switch( g_work.m_conditon.m_conditon.V_conditon )
{
case 0:
if( g_work.V_real_Value <= 410) //99-70%
{
g_work.m_conditon.m_conditon.V_conditon = 1;
Write_condtion();
}
break;
case 1:
if( g_work.V_real_Value <= 375 ) //30-70%
{
g_work.m_conditon.m_conditon.V_conditon = 2;
Write_condtion();
}
break;
case 2:
if( g_work.V_real_Value <= 350 ) // <30%
{
g_work.m_conditon.m_conditon.V_conditon = 3;
Write_condtion();
}
break;
case 3: // 3.50
break;
case 4:
break;
}
if( g_work.power == 0 )
{
//printf("123\r\n");
Write_condtion();
}
}
// }
}
////////////////////////////////////////////////////////////////////////////////
/// @brief When DMA send data, set ADCflag, PA8, clear the interrupt flag,
/// stop the conversion.
/// @note If error occurs,Simulation to see if you can enter the interrupt
/// function.
/// @param None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void DMA1_Channel1_IRQHandler(void)
{
//Stop Conversion
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
//Clear interrupt flag
DMA_ClearITPendingBit(DMA1_IT_TC1);
ADC_DMACmd(ADC1,DISABLE);
//Erected transmission complete flag
ADCflag = 1;
adc_get();
g_work.get_r_flag = 0;
}
//void get_adc
void adc_get()
{
static u16 chan, averagenumber = 0;
if(ADCflag == 1)
{
ADCflag = 0;
for(chan = 0; chan < ADCSCANNUM; chan++) {
varADCavarage[averagenumber][chan] = ADCValue[chan];
// printf("ADC_F chan %d cnt: %d __ %d ",chan,averagenumber,varADCavarage[averagenumber][chan]);
// printf("ADC_%d __ %d ",chan,ADCValue[chan]);
}
//printf("\r\n");
WWDG_SetCounter(0x7e);
//DELAY_Ms(2);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1,ENABLE);
averagenumber++;
if(averagenumber >= AVERAGELEN) {
averagenumber = 0;
ADCTrigFilterflag = 1;
}
}
}
void ADC_work()
{
// if(ADCTrigFilterflag)
// {
// ADCFilter();
// ADCTrigFilterflag = 0;
// Get_ADCVolatge_new();
// }
// //adc_get();
// //Determine whether the second-order filter is over
// if(ADCTrigFilterflag) {
// ADCFilter();
// //Clear the filter end flag
// ADCTrigFilterflag = 0;
// //Convert the filtered value to voltage
// Get_ADCVolatge();
// g_work._write_v_ok = 1;
// }
//
// //常温标定
// if(g_work.temp_delay > 5)
// {
// ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// }
//
// if(g_work.get_r_flag == 1 && g_work.adc_count > 100)
// {
// ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// ADC_DMACmd(ADC1,ENABLE);
// g_work.adc_count = 0; //定时采集
// }
// WWDG_SetCounter(0x7e);
}
/// @}
/// @}
/// @}