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

560 lines
16 KiB
C
Raw Normal View History

2024-07-29 10:32:25 +08:00
////////////////////////////////////////////////////////////////////////////////
/// @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);
}
/// @}
/// @}
/// @}