/* * @Date: 2025-06-26 16:58:50 * @LastEditors: 路怀帅 * @LastEditTime: 2025-07-04 17:07:40 * @FilePath: \RVMDK(uv5)e:\个人项目\零距电子\安灯遥控器\Andon_Remote_Control\Andon_RTOS\User\src\bsp_bat.c */ #include "main.h" #include "FreeRTOS.h" #include "semphr.h" #include "task.h" static void BAT_Init(void); static uint8_t BAT_State_Read(void); BATClassStruct BATClass = { .Init = BAT_Init, .Read_State = BAT_State_Read}; static void BAT_Init() { /*电池检测IO初始化*/ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); } int cont = 0; static uint8_t BAT_State_Read() { cont++; uint8_t isCharging, batteryLevel; batteryLevel = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2); isCharging = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4); if ((isCharging == 0) && (batteryLevel == 1)) { if (cont >= 30) { GPIOB->BSRR = ((GPIOB->ODR & GPIO_Pin_0) << 16) | (~GPIOB->ODR & GPIO_Pin_0); cont = 0; } } else if ((isCharging == 1) && (batteryLevel == 0)) { GPIO_ResetBits(GPIOB, GPIO_Pin_0); } else { GPIO_SetBits(GPIOB, GPIO_Pin_0); } return 0; } void Power_button_init() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOA, &GPIO_InitStructure); } uint8_t Check_Power_buttun() { if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) { delay_ms(30); if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) return 0; } else if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1) { delay_ms(30); if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1) return 1; } return 0; } static void ADC1_Init(void); static uint16_t getADC1Value(uint8_t ADC_channelx); ADC1ClassStruct ADC1Class = { .Init = ADC1_Init, .GetValue = getADC1Value}; #define ADC1_DMA_CHANNEL DMA1_Channel1 #define ADC1_DMA_CLK RCC_AHBPeriph_DMA1 #define ADC1_CLK RCC_APB2Periph_ADC1 #define ADC1_A0_A7_GPIO_PORT GPIOA #define ADC1_A0_A7_GPIO_CLK RCC_APB2Periph_GPIOA #define ADC1_A0_GPIO_PIN GPIO_Pin_0 #define ADC1_A1_GPIO_PIN GPIO_Pin_1 #define ADC1_A2_GPIO_PIN GPIO_Pin_2 #define ADC1_A3_GPIO_PIN GPIO_Pin_3 #define ADC1_A4_GPIO_PIN GPIO_Pin_4 #define ADC1_A5_GPIO_PIN GPIO_Pin_5 #define ADC1_A6_GPIO_PIN GPIO_Pin_6 #define ADC1_A7_GPIO_PIN GPIO_Pin_7 #define ADC1_B0_B1_GPIO_PORT GPIOB #define ADC1_B0_B1_GPIO_CLK RCC_APB2Periph_GPIOB #define ADC1_B0_GPIO_PIN GPIO_Pin_0 #define ADC1_B1_GPIO_PIN GPIO_Pin_1 #define ADC1_A0_CHANNEL ADC_Channel_0 #define ADC1_A1_CHANNEL ADC_Channel_1 #define ADC1_A2_CHANNEL ADC_Channel_2 #define ADC1_A3_CHANNEL ADC_Channel_3 #define ADC1_A4_CHANNEL ADC_Channel_4 #define ADC1_A5_CHANNEL ADC_Channel_5 #define ADC1_A6_CHANNEL ADC_Channel_6 #define ADC1_A7_CHANNEL ADC_Channel_7 #define ADC1_B0_CHANNEL ADC_Channel_8 #define ADC1_B1_CHANNEL ADC_Channel_9 __IO uint16_t ADC_ConvertedValue[10] = {0}; /** * @brief ADC1初始化 * @param None * @retval None * @note None */ static void ADC1_Init(void) { /*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_APB2PeriphClockCmd(ADC1_A0_A7_GPIO_CLK, ENABLE); /***************************************************************/ // 1. 修改为所使用的引脚 GPIO_InitStructure.GPIO_Pin = ADC1_A5_GPIO_PIN; /***************************************************************/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(ADC1_A0_A7_GPIO_PORT, &GPIO_InitStructure); // 打开DMA时钟 RCC_AHBPeriphClockCmd(ADC1_DMA_CLK, ENABLE); // 打开ADC时钟 RCC_APB2PeriphClockCmd(ADC1_CLK, ENABLE); // 复位DMA控制器 DMA_DeInit(ADC1_DMA_CHANNEL); // 配置 DMA 初始化结构体 // 外设基址为:ADC 数据寄存器地址 DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(ADC1->DR)); // 存储器地址 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue; // 数据源来自外设 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; /***************************************************************/ // 2.缓存数量 使用1个ADC引脚就是1 使用2个ADC引脚就是2 DMA_InitStructure.DMA_BufferSize = 1; /***************************************************************/ // 外设寄存器只有一个,地址不用递增 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 存储器地址递增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 内存数据大小也为半字,跟外设数据大小相同 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 循环传输模式 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响 DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 禁止存储器到存储器模式,因为是从外设到存储器 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 初始化DMA DMA_Init(ADC1_DMA_CHANNEL, &DMA_InitStructure); // 使能 DMA 通道 DMA_Cmd(ADC1_DMA_CHANNEL, ENABLE); // ADC 模式配置 // 只使用一个ADC,属于单模式 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 扫描模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 连续转换模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 不用外部触发转换,软件开启即可 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 转换结果右对齐 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /***************************************************************/ // 3.转换通道个数 使用1个ADC引脚就是1 使用2个ADC引脚就是2 ADC_InitStructure.ADC_NbrOfChannel = 1; /***************************************************************/ // 初始化ADC ADC_Init(ADC1, &ADC_InitStructure); // 配置ADC时钟N狿CLK2的8分频,即9MHz RCC_ADCCLKConfig(RCC_PCLK2_Div8); /***************************************************************/ // 4.配置ADC通道的转换顺序和采样时间 将所使用的所有引脚按自定义顺序填写 ADC_RegularChannelConfig(ADC1, ADC1_A5_CHANNEL, 1, ADC_SampleTime_55Cycles5); // ADC_RegularChannelConfig(ADC1, ADC1_A2_CHANNEL, 2, ADC_SampleTime_55Cycles5); /***************************************************************/ // 使能ADC DMA 请求 ADC_DMACmd(ADC1, ENABLE); // 开启ADC ,并开始转换 ADC_Cmd(ADC1, ENABLE); // 初始化ADC 校准寄存器 ADC_ResetCalibration(ADC1); // 等待校准寄存器初始化完成 while (ADC_GetResetCalibrationStatus(ADC1)) ; // ADC开始校准 ADC_StartCalibration(ADC1); // 等待校准完成 while (ADC_GetCalibrationStatus(ADC1)) ; // 由于没有采用外部触发,所以使用软件触发ADC转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); } /* 0-9对应第四步中的ADC引脚通道顺序 例如顺序为ADC1_A3 ADC1_A4 则A3引脚对应0 A4引脚对应1*/ static uint16_t getADC1Value(uint8_t ADC_channelx) { uint16_t ADCTemp = 0; switch (ADC_channelx) { case 0: ADCTemp = (float)ADC_ConvertedValue[0] * 3.3 * 100 / 4096; break; case 1: ADCTemp = (float)ADC_ConvertedValue[1] / 4096 * 3.3 * 100; break; case 2: ADCTemp = (float)ADC_ConvertedValue[2] / 4096 * 3.3 * 100; break; case 3: ADCTemp = (float)ADC_ConvertedValue[3] / 4096 * 3.3 * 100; break; case 4: ADCTemp = (float)ADC_ConvertedValue[4] / 4096 * 3.3 * 100; break; case 5: ADCTemp = (float)ADC_ConvertedValue[5] / 4096 * 3.3 * 100; break; case 6: ADCTemp = (float)ADC_ConvertedValue[6] / 4096 * 3.3 * 100; break; case 7: ADCTemp = (float)ADC_ConvertedValue[7] / 4096 * 3.3 * 100; break; case 8: ADCTemp = (float)ADC_ConvertedValue[8] / 4096 * 3.3 * 100; break; case 9: ADCTemp = (float)ADC_ConvertedValue[9] / 4096 * 3.3 * 100; break; } return ADCTemp; }