提交全部资料

This commit is contained in:
2026-03-31 15:40:09 +08:00
parent 46f0e8d6c2
commit 4d2204bf84
235 changed files with 101676 additions and 0 deletions

View File

@@ -0,0 +1,265 @@
/*
* @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;
}

View File

@@ -0,0 +1,459 @@
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "main.h"
#define KEY_ENABLED(bit) ((rc_data()->Kv_get.key_en_table & (1 << (bit - 1))) != 0)
typedef enum
{
S1_BUTTON = 0,
S2_BUTTON,
S3_BUTTON,
S4_BUTTON,
S5_BUTTON,
S6_BUTTON,
S7_BUTTON,
S8_BUTTON,
S9_BUTTON,
S10_BUTTON,
S11_BUTTON,
S12_BUTTON,
BUTTON_MAX
} user_button_t;
static flex_button_t user_button[BUTTON_MAX];
/**
*@brief 按键1回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_1_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
rc_data()->Lock_state = !rc_data()->Lock_state;
rc_data()->Lock_time_tick = 0;
LEDClass.Set(BLACK);
rc_data()->isLEDTog = DISABLE;
rc_data()->isSend = DISABLE;
ASR_Power_OFF;
rc_data()->Asr_state = LOCK;
break;
case FLEX_BTN_PRESS_LONG_START:
BOARD_Power_OFF;
break;
}
}
/**
*@brief 按键2回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_2_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(2))
{
rc_data()->Lock_time_tick = 0;
rc_data()->Key_data[1] = 1;
rc_data()->isLEDTog = ENABLE;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键3回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_3_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(3))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[0] = 3;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键4回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_4_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(4))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[0] = 4;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键5回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_5_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(5))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[0] = 5;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键6回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_6_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(6))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[0] = 6;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键7回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_7_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(7))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[0] = 7;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键8回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_8_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(8))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[0] = 8;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键9回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_9_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(9))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[2] = 1;
rc_data()->Key_data[3] = 0;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键10回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_10_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(10))
{
rc_data()->Lock_time_tick = 0;
rc_data()->isLEDTog = ENABLE;
rc_data()->Key_data[2] = 0;
rc_data()->Key_data[3] = 1;
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键11回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_11_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
if (KEY_ENABLED(11))
{
rc_data()->Lock_time_tick = 0;
if (rc_data()->Asr_state == UNLOCK && rc_data()->Lock_state == UNLOCK)
{
ASR_Power_OFF;
LEDClass.Set(BLACK);
rc_data()->Asr_state = LOCK;
}
else if (rc_data()->Asr_state == LOCK && rc_data()->Lock_state == UNLOCK)
{
ASR_Power_ON;
LEDClass.Set(BLACK);
rc_data()->Asr_state = UNLOCK;
}
}
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
/**
*@brief 按键12回调函数
*@param *btn 按键结构体
*@retval None
*/
static void btn_12_cb(flex_button_t *btn)
{
switch (btn->event)
{
case FLEX_BTN_PRESS_DOWN:
break;
case FLEX_BTN_PRESS_CLICK:
rc_data()->Lock_time_tick = 0;
rc_data()->isSend = ENABLE;
break;
case FLEX_BTN_PRESS_LONG_START:
break;
}
}
// 按键001平读取接口
static uint8_t button_s1_read(void)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
}
// 按键02电平读取接口
static uint8_t button_s2_read(void)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11);
}
// 按键03平读取接口
static uint8_t button_s3_read(void)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12);
}
// 按键04电平读取接口
static uint8_t button_s4_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7);
}
// 按键05电平读取接口
static uint8_t button_s5_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14);
}
// 按键06电平读取接口
static uint8_t button_s6_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6);
}
// 按键07电平读取接口
static uint8_t button_s7_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
}
// 按键08电平读取接口
static uint8_t button_s8_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5);
}
// 按键09电平读取接口
static uint8_t button_s9_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15);
}
// 按键10电平读取接口
static uint8_t button_s10_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_3);
}
// 按键11电平读取接口
static uint8_t button_s11_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1);
}
// 按键12电平读取接口
static uint8_t button_s12_read(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12);
}
/**
*@brief 按键初始化
*@param None
*@retval None
*/
void user_button_init(void)
{
/*注册按键Callback函数*/
memset(&user_button[0], 0x0, sizeof(user_button));
user_button[S1_BUTTON].usr_button_read = button_s1_read;
user_button[S1_BUTTON].cb = (flex_button_response_callback)btn_1_cb;
user_button[S2_BUTTON].usr_button_read = button_s2_read;
user_button[S2_BUTTON].cb = (flex_button_response_callback)btn_2_cb;
user_button[S3_BUTTON].usr_button_read = button_s3_read;
user_button[S3_BUTTON].cb = (flex_button_response_callback)btn_3_cb;
user_button[S4_BUTTON].usr_button_read = button_s4_read;
user_button[S4_BUTTON].cb = (flex_button_response_callback)btn_4_cb;
user_button[S5_BUTTON].usr_button_read = button_s5_read;
user_button[S5_BUTTON].cb = (flex_button_response_callback)btn_5_cb;
user_button[S6_BUTTON].usr_button_read = button_s6_read;
user_button[S6_BUTTON].cb = (flex_button_response_callback)btn_6_cb;
user_button[S7_BUTTON].usr_button_read = button_s7_read;
user_button[S7_BUTTON].cb = (flex_button_response_callback)btn_7_cb;
user_button[S8_BUTTON].usr_button_read = button_s8_read;
user_button[S8_BUTTON].cb = (flex_button_response_callback)btn_8_cb;
user_button[S9_BUTTON].usr_button_read = button_s9_read;
user_button[S9_BUTTON].cb = (flex_button_response_callback)btn_9_cb;
user_button[S10_BUTTON].usr_button_read = button_s10_read;
user_button[S10_BUTTON].cb = (flex_button_response_callback)btn_10_cb;
user_button[S11_BUTTON].usr_button_read = button_s11_read;
user_button[S11_BUTTON].cb = (flex_button_response_callback)btn_11_cb;
user_button[S12_BUTTON].usr_button_read = button_s12_read;
user_button[S12_BUTTON].cb = (flex_button_response_callback)btn_12_cb;
/*按键检测IO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_13 | GPIO_Pin_6 | GPIO_Pin_14 | GPIO_Pin_7 | GPIO_Pin_12 | GPIO_Pin_1 | GPIO_Pin_15 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_12 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
user_button[0].pressed_logic_level = 1;
user_button[0].click_start_tick = 20;
user_button[0].short_press_start_tick = 80;
user_button[0].long_press_start_tick = 200;
user_button[0].long_hold_start_tick = 300;
flex_button_register(&user_button[0]);
for (uint8_t i = 1; i < BUTTON_MAX; i++)
{
user_button[i].pressed_logic_level = 0;
user_button[i].click_start_tick = 20;
user_button[i].short_press_start_tick = 80;
user_button[i].long_press_start_tick = 200;
user_button[i].long_hold_start_tick = 300;
flex_button_register(&user_button[i]);
}
}

View File

@@ -0,0 +1,30 @@
#include "bsp_chipid.h"
uint32_t ChipUniqueID[3];
/*
* 函数名Get_ChipID
* 描述 获取芯片ID
* 输入 :无
* 输出 :无
*/
void Get_ChipID(void)
{
ChipUniqueID[0] = *(__IO u32 *)(0X1FFFF7F0); // 高字节
ChipUniqueID[1] = *(__IO u32 *)(0X1FFFF7EC); //
ChipUniqueID[2] = *(__IO u32 *)(0X1FFFF7E8); // 低字节
}
void WDOG_Init()
{
// 使能 预分频寄存器PR和重装载寄存器RLR可写
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
// 设置预分频器值
IWDG_SetPrescaler(IWDG_Prescaler_16); // IWDG 1s 超时溢出40k/16/2500= 1s
// 设置重装载寄存器值
IWDG_SetReload(0xfff);
// 把重装载寄存器的值放到计数器中
IWDG_ReloadCounter();
// 使能 IWDG
IWDG_Enable();
}

View File

@@ -0,0 +1,117 @@
/*
* @Date: 2025-06-26 09:38:27
* @LastEditors: 路怀帅
* @LastEditTime: 2025-06-26 15:04:35
* @FilePath: \Andon_Remote_Control\MDK_PROJECT\Drive\Led.c
*/
#include "main.h"
static void LED_Init(void);
static void LED_Set(uint8_t led_x);
static void Green_Toggle_Fun(void);
static void Red_Toggle_Fun(void);
static void Blue_Toggle_Fun(void);
static void Yellow_Toggle_Fun(void);
typedef LED_Color_Enum Led_Color;
LEDClassStruct LEDClass = {
.Init = LED_Init,
.Set = LED_Set,
.GREEN_Toggle = Green_Toggle_Fun,
.RED_Toggle = Red_Toggle_Fun,
.BLUE_Toggle = Blue_Toggle_Fun,
.YELLOW_Toggle = Yellow_Toggle_Fun};
static void LED_Set(uint8_t led_x)
{
switch (led_x)
{
case BLACK:
LED_ALL_OFF;
break;
case BLUE:
BLUE_ON;
break;
case GREEN:
GREEN_ON;
break;
case RED:
RED_ON;
break;
case YELLOW:
RED_ON;
GREEN_ON;
break;
case WHITE:
RED_ON;
GREEN_ON;
BLUE_ON;
break;
default:
break;
}
}
static void Green_Toggle_Fun()
{
GREEN_TOG;
}
static void Blue_Toggle_Fun()
{
BLUE_TOG;
}
static void Red_Toggle_Fun()
{
RED_TOG;
}
static void Yellow_Toggle_Fun()
{
RED_TOG;
GREEN_TOG;
}
/**
* @brief LED初始化
* @param None
* @retval None
*/
void LED_Init()
{
/*初始化LED引脚*/
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_SetBits(GPIOA, GPIO_Pin_6 | GPIO_Pin_7);
GPIO_SetBits(GPIOB, GPIO_Pin_0);
}
void ASR_Power_Init()
{
/*初始化LED引脚*/
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void BOARD_Power_Init()
{
/*初始化LED引脚*/
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
BOARD_Power_ON;
}

View File

@@ -0,0 +1,40 @@
#include "main.h"
typedef void (*ToggleFunc)(void);
typedef void (*DelayFunc)(uint32_t);
static void toggleLoop(ToggleFunc toggle, DelayFunc delayFunc, uint8_t iterations, uint32_t delayTime);
MODClassStruct MODClass = {
.Loop = toggleLoop,
};
static void toggleLoop(ToggleFunc toggle, DelayFunc delayFunc, uint8_t iterations, uint32_t delayTime)
{
for (uint8_t i = 0; i < iterations; i++)
{
toggle();
delayFunc(delayTime);
}
}
LoraCommandParams cmd_params[] = {
{"6", "1", "0", "0"},
{"3", "1", "0", "0"},
{"7", "1", "0", "0"},
{"5", "1", "0", "0"},
{"4", "1", "0", "0"},
{"6", "0", "0", "0"},
{"3", "0", "0", "0"},
{"7", "0", "0", "0"},
{"5", "0", "0", "0"},
{"4", "0", "0", "0"},
{"0", "0", "1", "0"},
{"0", "0", "0", "1"},
};
rc_data_t *rc_data(void)
{
static rc_data_t instance = {0};
return &instance;
}

View File

@@ -0,0 +1,370 @@
#include "main.h"
static void USART1_Init(uint32_t baudRate);
static void USART2_Init(uint32_t baudRate);
static void USART3_Init(uint32_t baudRate);
static void USART_SendString1(USART_TypeDef *USARTx, uint8_t *str, uint16_t len);
static void USART_SendString2(USART_TypeDef *USARTx, uint8_t *str);
USARTClassStruct USARTClass = {
.USART1_Init = USART1_Init,
.USART2_Init = USART2_Init,
.USART3_Init = USART3_Init,
.USART_SendString1 = USART_SendString1,
.USART_SendString2 = USART_SendString2};
#define use_USART1
#define use_USART2
#define use_USART3
#define DEBUG_USART USART1
/* 在别的地方复现此函数 串口1中断函数
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
*/
/* 在别的地方复现此函数 串口2中断函数
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
}
*/
/* 在别的地方复现此函数 串口3中断函数
void USART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
}
*/
#define DEBUG_REVDATA_SIZE 500
uint8_t g_debugRxFlag = 0;
uint8_t g_debugRxBuf[DEBUG_REVDATA_SIZE];
uint16_t g_debugRxLen = 0;
uint8_t Lora_sendbuf[DEBUG_REVDATA_SIZE];
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
g_debugRxBuf[g_debugRxLen] = USART_ReceiveData(USART1);
g_debugRxLen++;
}
else if (USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET)
{
USART1->SR;
USART1->DR;
// memcpy(Lora_sendbuf,g_debugRxBuf,g_debugRxLen);
// printf("send data:%s\r\n",g_debugRxBuf);
// USARTClass.USART_SendString1(USART3,g_debugRxBuf,g_debugRxLen);
// memset(g_debugRxBuf,0x00,DEBUG_REVDATA_SIZE);
// g_debugRxLen = 0;
g_debugRxFlag = 1;
}
}
/**
* @brief USART1初始化
* @param baudRate: 波特率
* @retval None
*/
static void USART1_Init(uint32_t baudRate)
{
#ifdef use_USART1
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 打开串口外设的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置波特率
USART_InitStructure.USART_BaudRate = baudRate;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(USART1, &USART_InitStructure);
// 使能串口
USART_Cmd(USART1, ENABLE);
// 使能接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 使能串口空闲中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // 中断控制器分组设置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
#endif
}
#define ASR_REVDATA_SIZE 20
uint8_t g_asrRxFlag = 0;
uint8_t Asr_recbuff[ASR_REVDATA_SIZE];
uint16_t g_asrRxLen = 0;
void USART2_IRQHandler(void)
{
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
Asr_recbuff[g_asrRxLen] = USART_ReceiveData(USART2);
g_asrRxLen++;
}
else if (USART_GetFlagStatus(USART2, USART_FLAG_IDLE) != RESET)
{
USART2->SR;
USART2->DR;
g_asrRxLen = 0;
// printf("asr data:");
// for(int i = 0;i<=2;i++)
// {
// printf("%02X",Asr_recbuff[i]);
// }
// printf("\r\n");
g_asrRxFlag = 1;
}
}
/**
* @brief USART2初始化
* @param baudRate: 波特率
* @retval None
*/
static void USART2_Init(uint32_t baudRate)
{
#ifdef use_USART2
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 打开串口外设的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置波特率
USART_InitStructure.USART_BaudRate = baudRate;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(USART2, &USART_InitStructure);
// 使能串口
USART_Cmd(USART2, ENABLE);
// 使能接收中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); // 使能串口空闲中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // 中断控制器分组设置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
#endif
}
#define LORA_REVDATA_SIZE 400
uint8_t g_loraRxFlag = 0;
uint8_t Lora_recbuff[LORA_REVDATA_SIZE];
uint16_t g_loraRxLen = 0;
void USART3_IRQHandler(void)
{
if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
Lora_recbuff[g_loraRxLen] = USART_ReceiveData(USART3);
g_loraRxLen++;
}
else if (USART_GetFlagStatus(USART3, USART_FLAG_IDLE) != RESET)
{
USART3->SR;
USART3->DR;
g_loraRxLen = 0;
printf("%s", Lora_recbuff);
memset(Lora_recbuff, 0x00, LORA_REVDATA_SIZE);
g_loraRxFlag = 1;
}
}
/**
* @brief USART3初始化
* @param baudRate: 波特率
* @retval None
*/
static void USART3_Init(uint32_t baudRate)
{
#ifdef use_USART3
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 打开串口GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 打开串口外设的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 配置波特率
USART_InitStructure.USART_BaudRate = baudRate;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(USART3, &USART_InitStructure);
// 使能串口
USART_Cmd(USART3, ENABLE);
// 使能接收中断
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); // 使能串口空闲中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // 中断控制器分组设置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStructure);
#endif
}
/**
* @brief USART发送定长字符串
* @param USARTx: 串口几发送
* @param str: 发送的内容
* @param len: 长度
* @retval None
*/
static void USART_SendString1(USART_TypeDef *USARTx, uint8_t *str, uint16_t len)
{
unsigned short count = 0;
for (; count < len; count++)
{
USART_SendData(USARTx, *str++); // 发送数据
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET)
; // 等待发送完成
}
}
/**
* @brief USART发送不定长字符串
* @param USARTx: 串口几发送
* @param str: 发送的内容
* @retval None
*/
static void USART_SendString2(USART_TypeDef *USARTx, uint8_t *str)
{
unsigned int k = 0;
do
{
USART_SendData(USARTx, *(str + k));
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
{
}
k++;
} while (*(str + k) != '\0');
/* 等待发送完成 */
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET)
{
}
}
/// 重定向c库函数printf到串口重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(DEBUG_USART, (uint8_t)ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET)
;
return (ch);
}
void Usart_SendByte(USART_TypeDef *pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
USART_SendData(pUSARTx, ch);
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET)
;
}
void Usart_SendString(USART_TypeDef *pUSARTx, char *str)
{
unsigned int k = 0;
do
{
Usart_SendByte(pUSARTx, *(str + k));
k++;
} while (*(str + k) != '\0');
/* 等待发送完成 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET)
{
}
}

View File

@@ -0,0 +1,153 @@
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_UCOS
#include "includes.h" //ucos 使用
#endif
static u8 fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{
OSIntEnter(); //进入中断
OSTimeTick(); //调用ucos的时钟服务程序
OSIntExit(); //触发任务切换软中断
}
#endif
//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()
{
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
u32 reload;
#endif
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为K
reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
fac_ms=1000/OS_TICKS_PER_SEC;//代表ucos可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/OS_TICKS_PER_SEC秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
fac_ms=(u16)fac_us*1000;//非ucos下,代表每个ms需要的systick时钟数
#endif
}
#ifdef OS_CRITICAL_METHOD //使用了ucos
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nus*fac_us; //需要的节拍数
tcnt=0;
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
}
};
}
//延时nms
//nms:要延时的ms数
void delay_ms(u16 nms)
{
if(OSRunning==TRUE)//如果os已经在跑了
{
if(nms>=fac_ms)//延时的时间大于ucos的最少时间周期
{
OSTimeDly(nms/fac_ms);//ucos延时
}
nms%=fac_ms; //ucos已经无法提供这么小的延时了,采用普通方式延时
}
delay_us((u32)(nms*1000)); //普通方式延时,此时ucos无法启动调度.
}
#else//不用ucos时
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}
while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
#endif

View File

@@ -0,0 +1,293 @@
/*
* @Date: 2025-06-26 10:58:20
* @LastEditors: 路怀帅
* @LastEditTime: 2025-06-26 14:47:21
* @FilePath: \Andon_Remote_Control\MDK_PROJECT\Drive\flexible_button.c
*/
/**
* @File: flexible_button.c
* @Author: MurphyZhao
* @Date: 2018-09-29
*
* Copyright (c) 2018-2019 MurphyZhao <d2014zjt@163.com>
* https://github.com/murphyzhao
* All rights reserved.
* License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Change logs:
* Date Author Notes
* 2018-09-29 MurphyZhao First add
* 2019-08-02 MurphyZhao 迁移代码到 murphyzhao 仓库
*
*/
#include "flexible_button.h"
#include <string.h>
#include <stdio.h>
static flex_button_t *btn_head = NULL;
#define EVENT_CB_EXECUTOR(button) if(button->cb) button->cb((flex_button_t*)button)
#define MAX_BUTTON_CNT 16
static uint16_t trg = 0;
static uint16_t cont = 0;
static uint16_t keydata = 0xFFFF;
static uint16_t key_rst_data = 0xFFFF;
static uint8_t button_cnt = 0;
/**
* @brief Register a user button
*
* @param button: button structure instance
* @return Number of keys that have been registered
*/
int8_t flex_button_register(flex_button_t *button)
{
flex_button_t *curr = btn_head;
if (!button || (button_cnt > MAX_BUTTON_CNT))
{
return -1;
}
while (curr)
{
if(curr == button)
{
return -1; //already exist.
}
curr = curr->next;
}
button->next = btn_head;
button->status = 0;
button->event = FLEX_BTN_PRESS_NONE;
button->scan_cnt = 0;
button->click_cnt = 0;
btn_head = button;
key_rst_data = key_rst_data << 1;
button_cnt ++;
return button_cnt;
}
/**
* @brief Read all key values in one scan cycle
*
* @param void
* @return none
*/
static void flex_button_read(void)
{
flex_button_t* target;
uint16_t read_data = 0;
keydata = key_rst_data;
int8_t i = 0;
for(target = btn_head, i = 0;
(target != NULL) && (target->usr_button_read != NULL);
target = target->next, i ++)
{
keydata = keydata |
(target->pressed_logic_level == 1 ?
((!(target->usr_button_read)()) << i) :
((target->usr_button_read)() << i));
}
read_data = keydata^0xFFFF;
trg = read_data & (read_data ^ cont);
cont = read_data;
}
/**
* @brief Handle all key events in one scan cycle.
* Must be used after 'flex_button_read' API
*
* @param void
* @return none
*/
static void flex_button_process(void)
{
int8_t i = 0;
flex_button_t* target;
for (target = btn_head, i = 0; target != NULL; target = target->next, i ++)
{
if (target->status > 0)
{
target->scan_cnt ++;
}
switch (target->status)
{
case 0: /* is default */
if (trg & (1 << i)) /* is pressed */
{
target->scan_cnt = 0;
target->click_cnt = 0;
target->status = 1;
target->event = FLEX_BTN_PRESS_DOWN;
EVENT_CB_EXECUTOR(target);
}
else
{
target->event = FLEX_BTN_PRESS_NONE;
}
break;
case 1: /* is pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
else if ((target->scan_cnt >= target->short_press_start_tick) &&
(target->scan_cnt < target->long_press_start_tick))
{
target->status = 4;
target->event = FLEX_BTN_PRESS_SHORT_START;
EVENT_CB_EXECUTOR(target);
}
break;
case 2: /* is up */
if ((target->scan_cnt < target->click_start_tick))
{
target->click_cnt++; // 1
if (target->click_cnt == 1)
{
target->status = 3; /* double click check */
}
else
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_DOUBLE_CLICK;
EVENT_CB_EXECUTOR(target);
}
}
else if ((target->scan_cnt >= target->click_start_tick) &&
(target->scan_cnt < target->short_press_start_tick))
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_CLICK;
EVENT_CB_EXECUTOR(target);
}
else if ((target->scan_cnt >= target->short_press_start_tick) &&
(target->scan_cnt < target->long_press_start_tick))
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_SHORT_UP;
EVENT_CB_EXECUTOR(target);
}
else if ((target->scan_cnt >= target->long_press_start_tick) &&
(target->scan_cnt < target->long_hold_start_tick))
{
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_LONG_UP;
EVENT_CB_EXECUTOR(target);
}
else if (target->scan_cnt >= target->long_hold_start_tick)
{
/* long press hold up, not deal */
target->click_cnt = 0;
target->status = 0;
target->event = FLEX_BTN_PRESS_LONG_HOLD_UP;
EVENT_CB_EXECUTOR(target);
}
break;
case 3: /* double click check */
if (trg & (1 << i))
{
target->click_cnt++;
target->status = 2;
target->scan_cnt --;
}
else if (target->scan_cnt >= target->click_start_tick)
{
target->status = 2;
}
break;
case 4: /* is short pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
else if ((target->scan_cnt >= target->long_press_start_tick) &&
(target->scan_cnt < target->long_hold_start_tick))
{
target->status = 5;
target->event = FLEX_BTN_PRESS_LONG_START;
EVENT_CB_EXECUTOR(target);
}
break;
case 5: /* is long pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
else if (target->scan_cnt >= target->long_hold_start_tick)
{
target->status = 6;
target->event = FLEX_BTN_PRESS_LONG_HOLD;
EVENT_CB_EXECUTOR(target);
}
break;
case 6: /* is long pressed */
if (!(cont & (1 << i))) /* is up */
{
target->status = 2;
}
break;
}
}
}
/**
* flex_button_event_read
*
* @brief Get the button event of the specified button.
*
* @param button: button structure instance
* @return button event
*/
flex_button_event_t flex_button_event_read(flex_button_t* button)
{
return (flex_button_event_t)(button->event);
}
/**
* flex_button_scan
*
* @brief Start key scan.
* Need to be called cyclically within the specified period.
* Sample cycle: 5 - 20ms
*
* @param void
* @return none
*/
void flex_button_scan(void)
{
flex_button_read();
flex_button_process();
}