Files
2026-03-31 15:40:09 +08:00

266 lines
8.1 KiB
C
Raw Permalink 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.
/*
* @Date: 2025-06-26 16:58:50
* @LastEditors: 路怀帅
* @LastEditTime: 2025-07-04 17:07:40
* @FilePath: \RVMDKuv5e:\个人项目\零距电子\安灯遥控器\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时钟狿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;
}