数码之家

 找回密码
 立即注册
搜索
查看: 1123|回复: 9

[STM] STM32音量控制器 (开源)

[复制链接]
发表于 2024-9-20 14:00:02 | 显示全部楼层 |阅读模式

好几年没在数码之家发过帖子了,今年购买拓竹打印机,做了个小玩具,为自己的电脑增加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
 楼主| 发表于 2024-9-20 14:03:57 | 显示全部楼层
这是数码之家新地址的第一个帖子
回复 支持 反对

使用道具 举报

发表于 2024-9-20 21:59:13 | 显示全部楼层
使用库函数啊
回复 支持 反对

使用道具 举报

发表于 2024-9-20 22:27:07 | 显示全部楼层
这个成品真漂亮。楼主整理的太干净了,我的桌面简直惨不忍睹
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-21 18:14:31 来自手机浏览器 | 显示全部楼层
lemontreenm 发表于 2024-9-20 22:27
这个成品真漂亮。楼主整理的太干净了,我的桌面简直惨不忍睹

因为我已经没有工作桌了,地方都被孩子霸占了,现在只能有个工作小车了
回复 支持 反对

使用道具 举报

发表于 2024-9-22 11:50:01 来自手机浏览器 | 显示全部楼层
偷偷告诉你,ch552就可以做
有开源的
回复 支持 反对

使用道具 举报

发表于 2024-9-22 12:06:08 来自手机浏览器 | 显示全部楼层
当年第一次见到这玩意儿也是数码之家18年吧…记得一开始是开源的,后来楼主删除固件就淘宝上有成品了…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-24 12:12:47 | 显示全部楼层
触景情伤 发表于 2024-9-22 12:06
当年第一次见到这玩意儿也是数码之家18年吧…记得一开始是开源的,后来楼主删除固件就淘宝上有成品了… ...

我也是自学stm32才用到的,不能和大神比啊
回复 支持 反对

使用道具 举报

发表于 2025-2-20 14:36:57 | 显示全部楼层
STM32接线图发一个啊,就是电路原理图
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-6 07:57 , Processed in 0.187200 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表