首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux 蜂鳴器播放音樂小程式:直接操作硬體端口

     編輯:關於C語言

經典 Linux 控制台蜂鳴器(PC Speaker)直接編程範例,透過 I/O 端口操作 8254 可程式化間隔定時器 產生方波聲音,無需音效卡驅動支援。

核心原理

  • 使用 I/O 特權指令 (iopl(3)) 獲取端口存取權限(需 root 權限)。
  • 操作端口 0x43 (控制字)、0x42 (計數器 2 讀寫)、0x61 (喇叭控制)。
  • 寫入分頻值設定頻率,控制位元開啟/關閉喇叭閘門。
  • usleep 控制音長與間隔。

完整原始碼

#include <sys/io.h>
#include <unistd.h>

void play(unsigned int* freq, unsigned int* delay);

int main() {
    // 樂譜資料:頻率(Hz) 與 持續時間(單位)
    unsigned int freq[] = { 330, 392, 330, 294, 330, 392,
        330, 394, 330, 330, 392, 330,
        294, 262, 294, 330, 392, 294,
        262, 262, 220, 196, 196, 220,
        262, 294, 330, 262, 0 };
    unsigned int time[] = { 50, 50, 50, 25, 25, 50,
        25, 25, 100, 50, 50, 25,
        25, 50, 50, 25, 25, 100,
        50, 25, 25, 50, 25, 25,
        50, 25, 25, 100 };

    // 更多樂曲資料...
    unsigned int freq_alert[] = { 2000, 2400, 0 };
    unsigned int time_alert[] = { 50, 60 };

    // 播放提示音 5 次
    for (int i = 0; i < 5; i++) play(freq_alert, time_alert);
    // 播放主樂曲
    play(freq2, time2);
    return 0;
}

void play(unsigned int* freq, unsigned int* time) {
    for (int i = 0; freq[i] != 0; i++) {
        speaker(freq[i], time[i]);
    }
}

int speaker(unsigned int freq, unsigned int delay) {
    static int flag = 0, bit;
    if (flag == 0) {
        flag = 1;
        iopl(3);  // 獲取 I/O 特權 (需 root)
    }
    outb(0xB6, 0x43);              // 設定計數器 2 模式
    outb(freq & 0xFF, 0x42);       // 寫入低位元組
    outb((freq >> 8) & 0xFF, 0x42); // 寫入高位元組
    bit = inb(0x61);               // 讀取喇叭控制狀態
    outb(bit | 3, 0x61);           // 開啟喇叭 (bit 0,1 = 1)
    usleep(10000 * delay);         // 延遲 (delay * 10ms)
    outb(bit & 0xFC, 0x61);        // 關閉喇叭 (bit 0,1 = 0)
    return 0;
}

編譯與執行

gcc -o beep beep.c
sudo ./beep  # 必須 root 權限執行 iopl(3)

技術細節補充

  • 0x43 控制字 0xB6:二進制 10110110,選擇計數器 2、低高位元組寫入、模式 3 (方波產生器)、二進制計數。
  • 頻率計算:8254 基頻 1.193182 MHz,分頻值 = 1193182 / 目標頻率(Hz)。
  • 0x61 端口:Bit 0 連接計數器 2 輸出至喇叭,Bit 1 控制喇叭閘門開關。
  • 現代 Linux 可能需載入 pcspkr 核心模組:modprobe pcspkr。
警告: 直接硬體端口操作需 root 權限,屬低層級編程,現代系統建議使用 ALSA/PulseAudio 等標準音訊 API。本範例僅供教學與嵌入式環境參考。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved