目次

簡易電子ボリューム(LM1972)

概要

安価で高性能な電子ボリューム用のIC(LM1972)が手に入りましたので、早速、簡易な電子ボリュームを製作してみました。

<簡易電子ボリュームの仕様>

<LM1972の主な仕様と特長>

<LM1972の概観>

<LM1972のピン配置>

動作原理

PICで電子ボリューム(LM1972)を制御し、その時の制御値をLCDに表示します。

動作原理(ハードウェア)

◎電子ボリューム

◎dB表示&バー表示

◎ボリューム値の設定

動作原理(ソフトウェア)

◎LM1972の制御(初期化)

◎LM1972の制御(ボリューム設定)

◎ボリューム値→dB変換

◎表示モード切替

◎ミュート動作

◎ボリューム値のアップ&ダウン

◎ボリューム値の書き込みと読み出し

<LM1972のタイミングチャート>

<LM1972のデータと減衰量の関係>

回路図

ソースコード

electronic_volume_v2.c
//********************************************************************** 
/*
  <電子ボリュームV2> 
*/
//********************************************************************** 
#define BYTE      unsigned short
#define WORD      unsigned int
#define DWORD     unsigned long
//
#define SW_R_UP   PORTA.B0
#define SW_R_DOWN PORTA.B1
#define SW_L_UP   PORTA.B2
#define SW_L_DOWN PORTA.B3
#define SW_MUTE   PORTA.B4
#define SW_MODE   PORTA.B5
//
#define CH_R      0
#define CH_L      1
//********************************************************************** 
const char character0[] = { 0, 0, 0, 0, 0, 0, 0, 0};
const char character1[] = { 0,16,16,16,16,16, 0, 0};
const char character2[] = { 0,24,24,24,24,24, 0, 0};
const char character3[] = { 0,28,28,28,28,28, 0, 0};
const char character4[] = { 0,30,30,30,30,30, 0, 0};
const char character5[] = { 0,31,31,31,31,31, 0, 0};
//
void    RegistCustomChar()
{
        char    i;
        //
        LCD_Cmd(64);
        for (i = 0; i<=7; i++) {
                LCD_Chr_Cp(character0[i]);
        }
        for (i = 0; i<=7; i++) {
                LCD_Chr_Cp(character1[i]);
        }
        for (i = 0; i<=7; i++) {
                LCD_Chr_Cp(character2[i]);
        }
        for (i = 0; i<=7; i++) {
                LCD_Chr_Cp(character3[i]);
        }
        for (i = 0; i<=7; i++) {
                LCD_Chr_Cp(character4[i]);
        }
        for (i = 0; i<=7; i++) {
                LCD_Chr_Cp(character5[i]);
        }
        LCD_Cmd(_LCD_RETURN_HOME);
}
//********************************************************************** 
void    BarDisp(char row, char column, short mode, unsigned int dat)
{
        short   i, j, k, cnt;
        //
        if (mode == 0) {
                i = dat / 1.79;
        } else {
                i = dat;
        }
        j = i / 5;
        k = i - (j * 5);
        //
        if (row == 1)
                Lcd_Cmd(_LCD_FIRST_ROW);
        else
                Lcd_Cmd(_LCD_SECOND_ROW);
        //
        for (cnt = 1; cnt < column; cnt++) {
                Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT);
        }
        //
        for (cnt = 0; cnt < j; cnt++) {
                Lcd_Chr_Cp(5);
        }
        Lcd_Chr_Cp(k);
        for (cnt++; cnt < 10; cnt++) {
                Lcd_Chr_Cp(' ');
        }
}
//********************************************************************** 
sbit LCD_RS at RA6_bit;
sbit LCD_EN at RA7_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_RS_Direction at TRISA6_bit;
sbit LCD_EN_Direction at TRISA7_bit;
sbit LCD_D7_Direction at TRISB7_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB4_bit;
//
void    init_lcd()
{
        short   cnt;
        //
        Lcd_Init();
        RegistCustomChar();
        Lcd_Cmd(_LCD_CURSOR_OFF);
        Lcd_Cmd(_LCD_CLEAR);
        Lcd_Out(1, 1, "e-volume V2.0");
        for (cnt = 0; cnt <= 80; cnt++) {
                BarDisp(2, 1, 1, cnt);
                Delay_ms(10);
        }
        Lcd_Cmd(_LCD_CLEAR);
}
//********************************************************************** 
sbit LM1972_CLOCK at RB1_bit;
sbit LM1972_LOAD at RB2_bit;
sbit LM1972_DATA at RB3_bit;
sbit LM1972_CLOCK_Direction at TRISB1_bit;
sbit LM1972_LOAD_Direction at TRISB2_bit;
sbit LM1972_DATA_Direction at TRISB3_bit;
//
void    init_volume()
{
        LM1972_CLOCK_Direction = 0;
        LM1972_LOAD_Direction = 0;
        LM1972_DATA_Direction = 0;
        //
        LM1972_LOAD = 1;
        LM1972_CLOCK = 0;
}
//********************************************************************** 
void    set_volume(BYTE channel, BYTE attenuation)
{
        short   cnt;
        //
        LM1972_LOAD = 0;
        for (cnt = 0; cnt < 8; cnt++) {
                LM1972_DATA = (channel & 0x80) != 0 ? 1 : 0;
                LM1972_CLOCK = 1;
                LM1972_CLOCK = 0;
                channel <<= 1;
        }
        for (cnt = 0; cnt < 8; cnt++) {
                LM1972_DATA = (attenuation & 0x80) != 0 ? 1 : 0;
                LM1972_CLOCK = 1;
                LM1972_CLOCK = 0;
                attenuation <<= 1;
        }
        LM1972_LOAD = 1;
}
//********************************************************************** 
void    db_cnv(BYTE dt, char* result)
{
        int     tmp;
        //
        tmp = dt;
        if (tmp >= 127) {
                IntToStr(-1000, result);
                result[9] = 0x00;
                result[8] = 'B';
                result[7] = 'd';
                result[6] = result[5];
                result[5] = '.';
                return;
        }
        if (tmp <= 96) {
                tmp *= 5;
                IntToStr(tmp * -1, result);
                result[9] = 0x00;
                result[8] = 'B';
                result[7] = 'd';
                result[6] = result[5];
                result[5] = '.';
                return;
        }
        tmp = 490 + ((tmp - 97) * 10);
        IntToStr(tmp * -1, result);
        result[9] = 0x00;
        result[8] = 'B';
        result[7] = 'd';
        result[6] = result[5];
        result[5] = '.';
}
//********************************************************************** 
void    main()
{
        BYTE   R_data, L_data;
        char   buf[16];
        short  mute_flg = 0;
        //
        OSCCON = 0b01110000;
        CMCON  = 0b00000111;
        ANSEL  = 0b00000000;
        TRISA  = 0b11111111;
        //
        init_lcd();
        Lcd_Out(1, 1, "R:");
        Lcd_Out(2, 1, "L:");
        //
        init_volume();
        //
        R_data = EEPROM_Read(0);
        R_data = R_data > 127 ? 127 : R_data;
        L_data = EEPROM_Read(1);
        L_data = L_data > 127 ? 127 : L_data;
        set_volume(CH_R, R_data);
        set_volume(CH_L, L_data);
        db_cnv(R_data, buf);
        Lcd_Out(1, 3, &buf[1]);
        db_cnv(L_data, buf);
        Lcd_Out(2, 3, &buf[1]);
        //
        while (1) {
                //(R)ボリュームUP! 
                if (SW_R_UP == 0) {
                        Delay_ms(100);
                        if (R_data > 0) {
                                R_data--;
                                EEPROM_Write(0, R_data);
                        }
                        set_volume(CH_R, R_data);
                }
                //(R)ボリュームDOWN! 
                if (SW_R_DOWN == 0) {
                        Delay_ms(100);
                        if (R_data < 127) {
                                R_data++;
                                EEPROM_Write(0, R_data);
                        }
                        set_volume(CH_R, R_data);
                }
                //(L)ボリュームUP! 
                if (SW_L_UP == 0) {
                        Delay_ms(100);
                        if (L_data > 0) {
                                L_data--;
                                EEPROM_Write(1, L_data);
                        }
                        set_volume(CH_L, L_data);
                }
                //(L)ボリュームDOWN! 
                if (SW_L_DOWN == 0) {
                        Delay_ms(100);
                        if (L_data < 127) {
                                L_data++;
                                EEPROM_Write(1, L_data);
                        }
                        set_volume(CH_L, L_data);
                }
                //表示モード切替(dB表示、バー表示) 
                if (SW_MODE == 1) {
                        db_cnv(R_data, buf);
                        Lcd_Out(1, 3, &buf[1]);
                        Lcd_Out(1, 11, "      ");
                        db_cnv(L_data, buf);
                        Lcd_Out(2, 3, &buf[1]);
                        Lcd_Out(2, 11, "      ");
                } else {
                        BarDisp(1, 3, 0, 127 - R_data);
                        BarDisp(2, 3, 0, 127 - L_data);
                }
                //ミュート動作 
                if (SW_MUTE == 0) {
                        Delay_ms(100);
                        if (mute_flg == 0) {
                                mute_flg = 1;
                                Lcd_Chr(1, 2, '_');
                                Lcd_Chr(2, 2, '_');
                                set_volume(CH_R, 127);
                                set_volume(CH_L, 127);
                        } else {
                                mute_flg = 0;
                                Lcd_Chr(1, 2, ':');
                                Lcd_Chr(2, 2, ':');
                                set_volume(CH_R, R_data);
                                set_volume(CH_L, L_data);
                        }
                }
        }
}
//**********************************************************************

動作確認

左側:dB表示、右側:バー表示

(編者注:破損した画像しかありませんでした)

左側から、ミュート、10Hz正弦波、100Hz正弦波

左側から、1KHz正弦波、10kHz、100KHz正弦波

著作権表示 copyright notice

このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。詳細
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.Details