Micro2440/Mini2440 開發板預設內核已包含 PWM 蜂鳴器驅動。檢查 ls /dev/pwm 存在即表示支援。驅動通過 ioctl 介面控制頻率與啟停。
**注意**:手冊中 PWM_IOCTL_STOP 定義為 2 有誤,實際驅動碼為 0,需與內核一致。
#define PWM_IOCTL_SET_FREQ 1
#define PWM_IOCTL_STOP 0 // 修正值
static int fd = -1; // 文件描述符
// 關閉蜂鳴器並釋放句柄
static void close_buzzer(void)
{
if (fd >= 0)
{
ioctl(fd, PWM_IOCTL_STOP);
close(fd);
fd = -1;
}
}
// 開啟設備,註冊退出自動清理
static void open_buzzer(void)
{
fd = open("/dev/pwm", 0);
if (fd < 0) { perror("open pwm_buzzer"); exit(1); }
atexit(close_buzzer); // 程序退出時自動關閉
}
// 設置頻率 (Hz)
static void set_buzzer_freq(int freq)
{
if (ioctl(fd, PWM_IOCTL_SET_FREQ, freq) < 0)
{ perror("set freq"); exit(1); }
}
// 停止發聲 (保持設備打開)
static void stop_buzzer(void)
{
if (ioctl(fd, PWM_IOCTL_STOP) < 0)
{ perror("stop"); exit(-1); }
}
/**
* @param freq 頻率
* @param t1 單次鳴響時長
* @param t2 鳴響次數
* @remark 經驗值: usleep(t1*100) 近似毫秒延遲
* 正常提示: ./testBeep 3000 2000 3 (3kHz, 2秒, 3次)
* 失敗告警: ./testBeep 3000 500 20 (3kHz, 0.5秒, 20次)
*/
static void Beep(int freq, int t1, int t2)
{
printf("freq=%d, each_ms=%d, ntimes=%d\n", freq, t1, t2);
open_buzzer();
for (int i = 0; i < t2; i++)
{
set_buzzer_freq(freq);
usleep(t1 * 100); // 經驗係數
stop_buzzer();
usleep(t1 * 100); // 間隔
}
close_buzzer();
}
int main(int argc, char **argv)
{
int freq = 10000; // 預設 10kHz
int each_ms = 500; // 預設 500ms
int times = 5; // 預設 5次
if (argc >= 2) freq = atoi(argv[1]);
if (freq < 1000 || freq > 20000) freq = 10000;
if (argc >= 3) each_ms = atoi(argv[2]);
if (each_ms < 100 || each_ms > 5000) each_ms = 500;
if (argc >= 4) times = atoi(argv[3]);
if (times < 1 || times > 30) times = 5;
Beep(freq, each_ms, times);
return 0;
}
# 交叉編譯
arm-linux-gcc testBeep.c -o testBeep
# 下載到開發板執行
# ./testBeep 3000 2000 3
/dev/pwm 封裝硬體細節。switch(cmd) 完全一致。atexit 保證異常退出也能釋放硬體資源。usleep(t*100) 為經驗修正,實際專案建議用 nanosleep 或時鐘源精確延遲。