27

主题

1

好友

486

积分

业余侠客 当前离线

Rank: 4

UID
787724
帖子
424
精华
0
经验
486 点
金钱
396 ¥
注册时间
2015-3-20
发表于 2022-9-24 01:40 | 显示全部楼层
本帖最后由 丰年好大雪 于 2022-9-24 01:45 编辑

先把图Po出来,咱不搞那神神秘秘的事情,把这玩意的原理和代码都告诉你。

·控制核心单片机为STM8S003或STM8S103,用这两个芯片,因为都是TSSOP20脚小芯片,节能,节省空间,还非常便宜。其他STM8系列也可以用,比如引脚更多的STM8S15系列,或者低能耗的STM8L系列,必须注意STM8L的部分寄存器配置和STM8S不同。
·STM8编程器使用淘宝的山寨STLINK V2,非常便宜。
·继电器使用国产宏发HFD4/5的银触点款,宏发用了15年,好着呢!
·控制外部LED和继电器均使用双片德仪的TCA9534,地址配置一个是0,一个是1。这个芯片的单脚吸收电流都是20ma级的,控制个继电器、LED只当玩一般,其实STM8也有此能力。
·图中略去总供电5V(其实可以直接用3.3V)的整流稳压电路,太简单,不浪费时间了。继电器控制电压可以共线使用5V(宏发HFD继电器有5V线圈款),也可以使用12V或24V外部供电,自己决定。
·继电器引脚必须加反向泄放二极管!电磁铁线圈在断开的瞬间会激励出一个强烈的反压,虽然STM8和TCA9534均有引脚保护二极管,但这个反压对整体供电的副作用不能轻视,可能会打坏其他芯片。
·小电容器以及所有的电阻均使用0603封装,除了R2R Ladder的音量衰减电阻使用1%外,均使用5%精度。R2R Ladder的计算方法随着Bit数变化而变化,每步长衰减分贝数可以由自己计算决定。大电容可以使用贴片1206大容量电容,因为便宜。
·网上有免费的继电器电阻计算工具:http://www.eijndhoven.net/jos/attenuator-calculator/index.html
·LED也使用0603封装,注意一点是LED的电流和压降,随着色彩不同而变化,一般红色、黄色为低压降小电流,白色、蓝色为高压降,图中给出的恒流源为8bit绿色LED的电流值,如使用其他色彩请自行计算(其实这个图也能点亮蓝色LED,就是不够亮)。
·图纸我是使用嘉立创制作,因此没有源文件(不兼容其他软件),如果你有心一起玩这个东西,那就从头开始画图,这样能更好的理解。

STM8音量1.png

STM8音量2.png

如有错误或不明白的请及时指出。
STM8音量2.png
STM8音量2.png

27

主题

1

好友

486

积分

业余侠客 当前离线

Rank: 4

UID
787724
帖子
424
精华
0
经验
486 点
金钱
396 ¥
注册时间
2015-3-20
 楼主| 发表于 2022-9-24 01:43 | 显示全部楼层
本帖最后由 丰年好大雪 于 2022-9-24 03:22 编辑

代码我使用了对新手最为友好的官方驱动库编程模式,虽然相比IAR等第三方工具,ST意法的官方开发环境STVP还是显得有点不好用,但制作这么简单的程序,仍然是绰绰有余。我尽量加了尽可能详细的注释以便于理解。

/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/

#include <stm8s.h>
#include <stm8s_gpio.h>
#include <stm8s_i2c.h>
#include <stm8s_conf.h>
#include <stm8s_clk.h>
#include <stm8s_exti.h>
#include <lib_rotary.h>

//以上引用的库文件,从stm8s.h到exti.h均为意法的官方驱动库"STM8S_StdPeriph_Lib",最后一个lib_rotary.h为驱动旋转编码器自制库
//未来如果需要用SPI端口驱动屏幕等,还需要加入spi官方库,以及为点阵屏、液晶屏专门用的其他驱动,到时候再说

u8 TCA9554_ADDR = 0x40;    //注:我最早使用的是TCA9554,和TCA9534能混用,此片为驱动LED用
u8 TCA9554_ADDR1 = 0x42;  //注:此片驱动继电器用
u8 VALUE_1;
u8 Switch_3 = 0;  //注:旋转编码器按压静音功能未做出来,我单独使用一个引脚控制额外的继电器断开输出,电路图中并未体现,因此未加入,有兴趣的朋友可以找例程研究
u8 Temp;     //Temp为温度计式字符串式LED的真值
bool LED_Status = TRUE;

/*下方为旋转编码器声明部分*/
#define PIN_MASK (4 | 5)        //做一下位或,选择GPIO_D的4、5脚
#define IDR GPIO_ReadInputData(GPIOD)   //为方便,我将所有输入引脚均连接至GPIO的D组

static char val_cur;        //当前旋转编码器位置
static char val_max;    //最高步长
static char Direction;   //方向向量
static char pins_last;   //最后位置暂存
static char roll_up, roll_down; //向左/向右判断变量
//结束

void delay_1ms(void)  //1ms延时函数,以16M高速时钟为参考
{
u8 t=108;
while(--t);
}

void delay_ms(u16 ms)  // ms延时函数,以16M高速时钟为参考
{
while(--ms)
{
   delay_1ms();
}
}

void SYS_Init(void)  //系统初始化函数,无返回
{
        CLK_HSICmd(ENABLE);   //使能STM8内置16M高速时钟
        CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2);    //高速时钟配置,除2
        //CLK_LSICmd(ENABLE);    //使能STM8内置低速400Khz时钟,害怕窜入干扰可以开启这个,同时注释掉上边两行,但注意总时钟变慢后,延时函数将边长,必须重新计算delay函数!
       
        CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);  //使能I2C端口分频后的时钟

        GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_IN_PU_IT);  //PD3上拉输入带中断,给EC11按下使能静音用,本程序无体现
        GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_IN_PU_NO_IT);
        GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_IN_PU_NO_IT);  //PD4、5脚上拉输入,无中断

        EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOD, EXTI_SENSITIVITY_FALL_ONLY);  //中断设置,仅下降沿触发

        I2C_DeInit();   //I2C端口标准初始化
        I2C_Init(200000, 0x1D, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 16);  //I2C端口设置,32位速度200k可以上400k酌情修改,占空比1:1,应答当前,7位地址模式,16M输入时钟
        I2C_Cmd(ENABLE);  //I2C使能
}

void I2C_Write(u8 CS,u8 Addr,u8 Data)  //I2C写函数,带三个输入参数,分别为目标芯片地址、寄存器地址、数据
{
       
        while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));  //判断总线忙
       
        /* 1.开始 */
        I2C_GenerateSTART(ENABLE);
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));   //主模式
       
        /* 2.设备地址/写 */
        I2C_Send7bitAddress(CS,I2C_DIRECTION_TX);   //写目标芯片TCA9554_ADDR的7位地址
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));  //判断主模式

        /* 3.数据地址 */
        I2C_SendData(Addr);
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));  //判断写动作完毕

        /* 4.写一字节数据 */
        I2C_SendData(Data);
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));  //判断写动作完毕
        /* 5.停止 */
        I2C_GenerateSTOP(ENABLE);
}

/******************************************************************************
*  以下为旋转编码器设置
*  
*  输入参数: 步长和总步长
******************************************************************************/

void alps_init(char steps, char option)  //旋转编码器初始化
{
        val_cur = 0;
        val_max = steps;
        Direction = 0;
        pins_last = IDR & PIN_MASK;         //将输入脚初始化并记录;

        // EC11编码器总步长设定
        roll_up = steps - 1;        //当达到最大值不再增加
        roll_down = 1;                //当达到最小值保持0
        if (option == ALPS_ROLLOVER)
        {
                roll_up = 0;
                roll_down = steps;
        }
}

/******************************************************************************
*  获得编码器当前位置 (需要前面的设置)
*****************************************************************************/

char alps_value(void)
{
        return val_cur;
}

/******************************************************************************
*  轮询引脚
******************************************************************************/

void alps_poll(void)
{
        char        pins_cur;
        char        diff;

        pins_cur = IDR & PIN_MASK;
        if ((pins_cur == 0) ||        (pins_cur == PIN_MASK))  // 判断是否全低
        {
                if (pins_cur == pins_last)   
                return;
                pins_last = pins_cur;       //如果等同上一次的值就返回(无动作)
               
                if (Direction)    //判断旋转事件
                        {
                        val_cur++;     //当前值变量加一
                        if (val_cur == val_max)   //如已达到最大值
                        val_cur = roll_up;      
                        return;
                        }
               
                if (val_cur == 0)    //判断第二种旋转事件
                val_cur = roll_down;   //如为负
                val_cur--;    //当前值减一
                return;
        }
        diff = pins_cur ^ pins_last;
        Direction = 0;                //则向左旋转
        if (diff == 4)                //如果同时另外一脚为高
            Direction = 1;        //向右旋转
}


/********************************************************************************
*迅速滚动开机自检LED
********************************************************************************/
void LED_Rolls(void)
{
        I2C_Write(TCA9554_ADDR,0x03,0x00);
        I2C_Write(TCA9554_ADDR,0x01,0x00);
        delay_ms(1000);
        I2C_Write(TCA9554_ADDR,0x01,0xFF);
        delay_ms(1000);
        I2C_Write(TCA9554_ADDR,0x01,0x00);
        delay_ms(1000);
        return;
}


main()   //主函数
{

        SYS_Init();
        LED_Rolls();
        I2C_Write(TCA9554_ADDR,0x03,0x00);
        I2C_Write(TCA9554_ADDR1,0x03,0x00);  //此两行为先设定TCA9554/9534的方向寄存器,开漏输出
        alps_init(63,63); //设定编码器步长,这里需要根据继电器数量自行决定,这里假设是6bit
        LED_Status = TRUE;
       
        //二进制音量设置,进入死循环轮询模式
        while(1)
        {
                delay_ms(100);  //轮询时间间断
                alps_poll();
                alps_value();
                VALUE_1 = ~val_cur;
                VALUE_1--;
               
                I2C_Write(TCA9554_ADDR1,0x01,VALUE_1);  //先把继电器都给跳喽
                delay_ms(10);   //没啥用,就是延时一下

                switch(VALUE_1)  //将真值变量送入switch语句转换成LED字符显示,我这里用了笨办法预设值查表,没有用更高级的枚举类型加指针,就是为了让初学者能看明白
                {
                        //假设使用8个led指示,每三个步长一跳变,自己酌情增减
                        case 0xFE:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111110);break;
                        case 0xFC:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111110);break;
                        case 0xFA:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111110);break;
                        case 0xF8:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111100);break;
                        case 0xF6:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111100);break;
                        case 0xF4:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111100);break;
                        case 0xF2:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111000);break;
                        case 0xF0:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111000);break;
                        case 0xEE:
                        I2C_Write(TCA9554_ADDR,0x01,0b11111000);break;
                        case 0xEC:
                        I2C_Write(TCA9554_ADDR,0x01,0b11110000);break;
                        case 0xEA:
                        I2C_Write(TCA9554_ADDR,0x01,0b11110000);break;
                        case 0xE8:
                        I2C_Write(TCA9554_ADDR,0x01,0b11110000);break;
                        case 0xE6:
                        I2C_Write(TCA9554_ADDR,0x01,0b11100000);break;
                        case 0xE4:
                        I2C_Write(TCA9554_ADDR,0x01,0b11100000);break;
                        case 0xE2:
                        I2C_Write(TCA9554_ADDR,0x01,0b11100000);break;
                        case 0xE0:
                        I2C_Write(TCA9554_ADDR,0x01,0b11000000);break;
                        case 0xDE:
                        I2C_Write(TCA9554_ADDR,0x01,0b11000000);break;
                        case 0xDC:
                        I2C_Write(TCA9554_ADDR,0x01,0b11000000);break;
                        case 0xDA:
                        I2C_Write(TCA9554_ADDR,0x01,0b10000000);break;
                        case 0xD8:
                        I2C_Write(TCA9554_ADDR,0x01,0b10000000);break;
                        case 0xD6:
                        I2C_Write(TCA9554_ADDR,0x01,0b10000000);break;
                        case 0xD4:
                        I2C_Write(TCA9554_ADDR,0x01,0b00000000);break;
                        //真开漏模式必须输入反码,必须注意
                }
        }
}

#ifdef USE_FULL_ASSERT   //STM8主函数后边要加上这玩意避免无法编译

/**
  * @brief  Reports the name of the source file and the source line number
  *  where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */  
void assert_failed(u8* file, u32 line)  
{  
  /* User can add his own implementation to report the file name and line number,
     ex: printf(“Wrong parameters value: file %s on line %drn”, file, line) */  
  /* Infinite loop */  
  while (1)  
  {  
  }  
}  
#endif  

/******************************************************************
*全部结束
******************************************************************/

//彩蛋,我懒得删除的中断部分,使用一个引脚外接按钮,设定为上拉作为中断输入,可以用来控制第三片9534来做输入信号选择,按一下变换一次,有兴趣可以研究研究怎么用
//以下部分可以放在主函数后边

// 3选1开关
@far @interrupt void EXTI1_IRQHandler(void)
{
        disableInterrupts(); //讨厌的STM8,响应中断必须先关中断,再观察输入寄存器
        switch(Switch_3)
                {
                        case 0x00:
                        Switch_3 ++;
                        I2C_Write(TCA9554_2,0x01,0b11111110);
                        break;
                        case 0x01:
                        Switch_3 ++;
                        I2C_Write(TCA9554_2,0x01,0b11111101);
                        break;
                        case 0x02:
                        I2C_Write(TCA9554_2,0x01,0b11111011);
                        Switch_3 = 0x00;
                        break;
                }
                delay_ms(1000);
        enableInterrupts();
}


//第二彩蛋,没有放进去的EC11按下静音功能
@far @interrupt void EXTI1_IRQHandler(void)
{
        disableInterrupts();
        if(LED_Status == TRUE)
        {
                I2C_Write(TCA9554_2,0x01,0b01111111);
        }
        else
        {
                I2C_Write(TCA9554_2,0x01,0b11111111);
        }
        LED_Status = ~LED_Status;
        delay_ms(500);
        enableInterrupts();
}




/*****
*lib_rotary.h头文件
*****/

void alps_init(char steps, char option);

#define ALPS_LIMITS   1               
#define ALPS_ROLLOVER 2               

/*
*  当前值
*/
char alps_value(void);

/*
*  轮询时间
*/
void alps_poll(void);


//彩蛋3,如果要用中断,可以改写主程序和下列中断向量表:

/*        BASIC INTERRUPT VECTOR TABLE FOR STM8 devices
*        Copyright (c) 2007 STMicroelectronics
*/

typedef void @far (*interrupt_handler_t)(void);

struct interrupt_vector {
        unsigned char interrupt_instruction;
        interrupt_handler_t interrupt_handler;
};

@far @interrupt void NonHandledInterrupt (void)
{
        /* in order to detect unexpected events during development,
           it is recommended to set a breakpoint on the following instruction
        */
        return;
}

extern void _stext();     /* startup routine */

//extern @far @interrupt void EXTI1_IRQHandler (void); //**Interrupt of PD

struct interrupt_vector const _vectab[] = {
        {0x82, (interrupt_handler_t)_stext}, /* reset */
        {0x82, NonHandledInterrupt}, /* trap  */
        {0x82, NonHandledInterrupt}, /* irq0  */
        {0x82, NonHandledInterrupt}, /* irq1  */
        {0x82, NonHandledInterrupt}, /* irq2  */
        {0x82, NonHandledInterrupt}, /* irq3  */
        {0x82, NonHandledInterrupt}, /* irq4  */
        {0x82, NonHandledInterrupt}, /* irq5  */
        //{0x82, NonHandledInterrupt}, /* irq6  */
        {0x82, (interrupt_handler_t)EXTI1_IRQHandler}, /* 中断irq6 */
        {0x82, NonHandledInterrupt}, /* irq7  */
        {0x82, NonHandledInterrupt}, /* irq8  */
        {0x82, NonHandledInterrupt}, /* irq9  */
        {0x82, NonHandledInterrupt}, /* irq10 */
        {0x82, NonHandledInterrupt}, /* irq11 */
        {0x82, NonHandledInterrupt}, /* irq12 */
        {0x82, NonHandledInterrupt}, /* irq13 */
        {0x82, NonHandledInterrupt}, /* irq14 */
        {0x82, NonHandledInterrupt}, /* irq15 */
        {0x82, NonHandledInterrupt}, /* irq16 */
        {0x82, NonHandledInterrupt}, /* irq17 */
        {0x82, NonHandledInterrupt}, /* irq18 */
        {0x82, NonHandledInterrupt}, /* irq19 */
        {0x82, NonHandledInterrupt}, /* irq20 */
        {0x82, NonHandledInterrupt}, /* irq21 */
        {0x82, NonHandledInterrupt}, /* irq22 */
        {0x82, NonHandledInterrupt}, /* irq23 */
        {0x82, NonHandledInterrupt}, /* irq24 */
        {0x82, NonHandledInterrupt}, /* irq25 */
        {0x82, NonHandledInterrupt}, /* irq26 */
        {0x82, NonHandledInterrupt}, /* irq27 */
        {0x82, NonHandledInterrupt}, /* irq28 */
        {0x82, NonHandledInterrupt}, /* irq29 */
};

//结束,累死我了

评分

参与人数 2经验 +4 魅力 +4 收起 理由
naturey2000 + 2 + 2 很给力!
mchoi518 + 2 + 2 很给力!

查看全部评分

头像被屏蔽

413

主题

3

好友

2756

积分

禁止发言 当前离线

UID
16477
帖子
7165
精华
0
经验
2756 点
金钱
2423 ¥
注册时间
2006-12-26
发表于 2022-9-24 08:46 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

4

主题

2

好友

382

积分

业余侠客 当前离线

Rank: 4

UID
25182
帖子
422
精华
0
经验
382 点
金钱
374 ¥
注册时间
2007-7-28
发表于 2022-9-24 20:46 | 显示全部楼层
虽然看不懂,但是开源必须支持

4

主题

0

好友

93

积分

论坛游民 当前离线

Rank: 3Rank: 3

UID
780540
帖子
91
精华
0
经验
93 点
金钱
77 ¥
注册时间
2015-1-6
发表于 2022-9-24 21:02 | 显示全部楼层
谢谢楼主的分享!不知道与使用pga2310效果有什么大的区别?似乎使用IC的要简单点。

23

主题

1

好友

2636

积分
     

罗宾汉 当前离线

Rank: 7Rank: 7Rank: 7

UID
52804
帖子
3267
精华
0
经验
2636 点
金钱
2565 ¥
注册时间
2008-9-1
发表于 2022-9-24 23:04 来自手机端 | 显示全部楼层
支持楼主,stm片不熟,脚太细,还是喜欢51多点,脚宽,便宜。

2

主题

0

好友

131

积分

论坛游民 当前离线

Rank: 3Rank: 3

UID
409918
帖子
134
精华
0
经验
131 点
金钱
127 ¥
注册时间
2011-10-7
发表于 2022-9-25 19:25 | 显示全部楼层
谢谢楼主,想学习一下,可能学不会

8

主题

0

好友

329

积分
     

业余侠客 当前离线

Rank: 4

UID
37395
帖子
408
精华
0
经验
329 点
金钱
371 ¥
注册时间
2008-3-14
发表于 2022-9-25 21:48 | 显示全部楼层
虽然看不懂,但好贴必须要赞,学习了。

42

主题

10

好友

732

积分
     

职业侠客 当前离线

Rank: 5Rank: 5

UID
411926
帖子
958
精华
0
经验
732 点
金钱
682 ¥
注册时间
2011-10-10

DIY大赛获奖 DIY大赛亚军

发表于 2022-11-11 12:07 | 显示全部楼层
开源必须支持

27

主题

1

好友

486

积分

业余侠客 当前离线

Rank: 4

UID
787724
帖子
424
精华
0
经验
486 点
金钱
396 ¥
注册时间
2015-3-20
 楼主| 发表于 2022-11-16 11:19 | 显示全部楼层
y1974 发表于 2022-9-24 21:02
谢谢楼主的分享!不知道与使用pga2310效果有什么大的区别?似乎使用IC的要简单点。

2310有一个比较挠头的问题,就是控制脚地线和模拟信号地线没有分开。

当然控制2310的数字地离模拟地分割开,星状入电源地是较好的,不过这么走线难度颇大。或者单片机设置为中断触发活跃关机,在没有动旋钮的时候关机停晶振,也是没什么干扰的,但似乎软件开发难度更大了(好多单片机活跃关机下触发开机可靠性不行,比如STC)。

30

主题

3

好友

1361

积分
     

侠之大者 当前离线

Rank: 6Rank: 6

UID
52517
帖子
3295
精华
0
经验
1361 点
金钱
1319 ¥
注册时间
2008-8-29
发表于 2022-11-17 18:28 | 显示全部楼层
不知是几级音量的?几个继电器?

209

主题

1

好友

2706

积分
     

罗宾汉 当前离线

越减越繁

Rank: 7Rank: 7Rank: 7

UID
1005
帖子
3351
精华
3
经验
2706 点
金钱
959 ¥
注册时间
2004-7-11
发表于 2022-11-18 10:16 | 显示全部楼层
感谢楼主无私分享!

1

主题

0

好友

9

积分
     

注册会员 当前离线

Rank: 2

UID
844217
帖子
9
精华
0
经验
9 点
金钱
7 ¥
注册时间
2018-2-6
发表于 2023-5-3 19:39 | 显示全部楼层
谢谢楼主的分享!有空试试

6

主题

0

好友

171

积分
     

论坛游民 当前离线

Rank: 3Rank: 3

UID
814161
帖子
167
精华
0
经验
171 点
金钱
157 ¥
注册时间
2016-5-16
发表于 2023-5-9 16:49 | 显示全部楼层
授人以渔,厉害

47

主题

14

好友

5464

积分

罗宾汉 当前离线

Rank: 7Rank: 7Rank: 7

UID
816790
帖子
5344
精华
0
经验
5464 点
金钱
5303 ¥
注册时间
2016-7-8
发表于 2023-5-9 21:12 | 显示全部楼层
你不是说放弃STM8了

8

主题

0

好友

480

积分

业余侠客 当前离线

Rank: 4

UID
490975
帖子
472
精华
0
经验
480 点
金钱
464 ¥
注册时间
2012-4-21
发表于 2023-5-10 15:23 | 显示全部楼层
这个继电器切换的时候有没有噪声的呀。再说现在流行MODBUS的呀。

1

主题

5

好友

147

积分
     

论坛游民 当前离线

Rank: 3Rank: 3

UID
24913
帖子
353
精华
0
经验
147 点
金钱
147 ¥
注册时间
2007-7-21
发表于 2024-1-3 21:33 | 显示全部楼层

谢谢楼主的分享!

15

主题

0

好友

2415

积分

罗宾汉 当前离线

Rank: 7Rank: 7Rank: 7

UID
761332
帖子
2460
精华
0
经验
2415 点
金钱
2370 ¥
注册时间
2014-10-10
发表于 2024-1-3 23:29 | 显示全部楼层
这种帖子要支持。

81

主题

3

好友

1501

积分

侠之大者 当前离线

Rank: 6Rank: 6

UID
897598
帖子
1394
精华
0
经验
1501 点
金钱
1300 ¥
注册时间
2021-2-4
发表于 2024-1-4 16:09 | 显示全部楼层
感谢大师无私分享~

我正好要写继电器音调代码,就看到您这个神贴了~

有个小疑问,您那个继电器音调电路图,我是真没看懂!!!

我也想用6~8个继电器搞双声道,但继电器一侧只有3个脚,怎么画都画不出来~ 只能是一个声道用6~8个继电器,如下图,,

另外您那个计算阻值的链接失效,有新的吗?

1.JPG

27

主题

1

好友

486

积分

业余侠客 当前离线

Rank: 4

UID
787724
帖子
424
精华
0
经验
486 点
金钱
396 ¥
注册时间
2015-3-20
 楼主| 发表于 2024-1-4 16:16 | 显示全部楼层
mchoi518 发表于 2024-1-4 16:09
感谢大师无私分享~

我正好要写继电器音调代码,就看到您这个神贴了~  

https://www.vaneijndhoven.net/jo ... lculator/index.html
这个
另外注意一点,他的图示逻辑设计是反相的,即开机后不上电为衰减器直通最大音量,继电器上电才衰减,要注意一下设计逻辑。

评分

参与人数 1经验 +2 魅力 +2 收起 理由
mchoi518 + 2 + 2 赞一个!

查看全部评分

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

本版积分规则

Powered by Discuz! X3.4

© 2001-2012 Comsenz Inc.

返回顶部