|
好几年没在数码之家发过帖子了,今年购买拓竹打印机,做了个小玩具,为自己的电脑增加2给实用小功能 1.增加电脑启动显示功能,由于我的电脑是开放性没有机箱外壳启动按钮非常简易一,方便操作以后启动电脑部需要在弯腰找电脑启动按钮了 2.增加电脑音量调节功能,调整音量大小,静音,切歌(短按:静音,长按:暂停播放,短按二次:切下一首,短按三次:切上一首) 3.两个控制器由磁铁连接,可以所以更换位置,单独使用
本人需要经常调整音量,静音和切歌,使用键盘不方便,本来想用ESP32开发一个蓝牙版本,不过目前没成功,所以先搞一个usb的,淘宝这种产品价格需要100多左右太不值得,此产品成本在10左右,使用STM32 编写程序,即插即用无需驱动,带灯光显示,每次操作带震动反馈
stm32 最小系统
旋转编码器
震动反馈电机 每次调节都能有反馈效果增加高级感觉
无需驱动即插即用
增加led灯
电脑启动比较简单,就是一个带灯的按钮
通电效果
gif的动态图片不知道是否能显示
最后臭美个整体效果图
程序keil5 HAL库
/*
usb电脑控制器
2024-9-11 GS
功能:旋转编码开关,震动反馈,呼吸灯显示
顺时针旋转音量+,逆时针旋转音量-,单击静音,长按音乐暂停,双击切下一首,三击切上一首
震动程序使用蜂鸣器代替
附件上传不了,大家先看看程序吧,硬件太简单了 就不画图了 编码器输入端口 PA0-2,震动PA4
*/
#include "main.h"
#include "usb_device.h"
#include "usbd_hid.h"
#include "buzzer.h"
#define KEYA_SPEED1 100 //长按的时间长度(单位10mS)
#define KEYA_SPEED2 10 //双击的时间长度(单位20mS)
extern uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len);
uint8_t HID_report[4];
unsigned char flag=0;
unsigned char z=0;
unsigned char KUP;
unsigned int cou;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
unsigned char ENCODER_READ(void);
int main(void)
{
HAL_Init(); //HAL库初始化
SystemClock_Config(); //系统时钟初始化
MX_GPIO_Init(); //GPIO初始化
MX_USB_DEVICE_Init(); //USB_HID初始化
BUZZER_Init(); //用蜂鸣器代替线性马达
while (1)
{
z=ENCODER_READ();
if(z==0x01){
BUZZER_BEEP1();HID_report[0]=0x01; //音量+
}else if(z==0x02){
BUZZER_BEEP1();HID_report[0]=0x02; //音量-
}else if(z==0x03){
BUZZER_BEEP1();HID_report[0]=0x04; //暂停/播放0x08
}else if(z==0x04){
BUZZER_BEEP1();HID_report[0]=0x08; //暂停
}else if(z==0x11){
BUZZER_BEEP1();HID_report[0]=0x10; //下一曲
}else if(z==0x12){
BUZZER_BEEP1();HID_report[0]=0x20; //上一曲
}
USBD_HID_SendReport(&hUsbDeviceFS,HID_report,1);
HID_report[0]=0x00;
USBD_HID_SendReport(&hUsbDeviceFS,HID_report,1);
// HAL_GPIO_WritePin(LEDPORT,LED,GPIO_PIN_SET);
// HAL_Delay(100); //延时
// HAL_GPIO_WritePin(LEDPORT,LED,GPIO_PIN_RESET);
// HAL_Delay(100); //延时
}
}
unsigned char ENCODER_READ(void){ //接口初始化
unsigned char k=0;//存放按键的值
unsigned char kt;
unsigned char a=0,b,c=0;
if(HAL_GPIO_ReadPin(butten_L_GPIO_Port,butten_L_Pin))KUP=0; //当L没有接通,标记为锁死
if(!HAL_GPIO_ReadPin(butten_L_GPIO_Port,butten_L_Pin)&&KUP==0){ //判断是否旋转旋钮,同时判断是否有旋钮锁死
cou=0;
HAL_Delay(1);
kt=HAL_GPIO_ReadPin(button_R_GPIO_Port,button_R_Pin); //把旋钮另一端电平状态记录
HAL_Delay(2); //延时
if(!HAL_GPIO_ReadPin(butten_L_GPIO_Port,butten_L_Pin)){ //去抖
if(kt==0){ //用另一端判断左或右旋转
k=1;//右转
}else{
k=2;//左转
}
cou=0; //初始锁死判断计数器
while(!HAL_GPIO_ReadPin(butten_L_GPIO_Port,butten_L_Pin)&&cou<1200){ //等待放开旋钮,同时累加判断锁死
cou++;KUP=1;HAL_Delay(1); //
}
}
}
if(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin))//检测按键是否按下
{
HAL_Delay(20); //延时去抖动
if(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin))//判断长短键
{
while((!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin))&&c<KEYA_SPEED1)//循环判断长按,到时跳转
{
c++;HAL_Delay(10); //长按判断的计时
}
if(c>=KEYA_SPEED1)//长键处理
{
k=4;//长按后执行的程序放到此处
while(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin));
}
else//单击处理和多击检测
{
for(b=0;b<KEYA_SPEED2;b++)//检测
{
HAL_Delay(20);
if(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin))
{
a=1;
while(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin));
for(b=0;b<KEYA_SPEED2;b++)//检测三击
{
HAL_Delay(20);
if(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin))
k=0x12;// 执行三击 上一曲
else
k=0x11; //执行二击 下一曲
}
while(!HAL_GPIO_ReadPin(button_D_GPIO_Port,button_D_Pin));
}
}
if(a==0)//判断单击
{
k=3;//单击后执行的程序放到此处
}
}
a=0;c=0; //参数清0
}
} //按键判断在此结束
if(k==0x10)k=0;
return k;
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pins : butten_L_Pin button_D_Pin */
GPIO_InitStruct.Pin = butten_L_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(butten_L_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = button_D_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(button_D_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : button_R_Pin */
GPIO_InitStruct.Pin = button_R_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(button_R_GPIO_Port, &GPIO_InitStruct);
}
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|