Linux 下控制蜂鸣器发声的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*===========================================
*《Linux声音设备编程实例》
* 1. 对内部扬声器编程
*  内部扬声器是控制台的一部分,所以它对应的设备文件为/dev/console。
*    变量KIOCSOUND在头文件 /usr /include /linux /kd.h中声明,
*    ioctl函数使用它可以来控制扬声器的发声,使用规则为:
*      ioctl ( fd, KIOCSOUND, (int) tone);
*      fd为文件设备号,tone 是音频值。当tone为0时,终止发声。
*    必须一提的是它所理解的音频和我们平常以为的音频是不同的,
*    由于计算机主板定时器的时钟频率为1.19MHZ,所以要进行正确的发声,
*    必须进行如下的转换:
*  扬声器音频值=1190000/我们期望的音频值。
*  扬声器发声时间的长短我们通过函数usleep(unsigned long usec)来控制。
*    它是在头文件/usr /include /unistd.h中定义的,让程序睡眠usec微秒。
*    下面即是让扬声器按指定的长度和音频发声的程序的完整清单:
*========================================================*/
 
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/kd.h>
 
/* 设定默认值 */
#define DEFAULT_FREQ 440   /* 设定一个合适的频率 */
#define DEFAULT_LENGTH 200 /* 200 微秒,发声的长度是以微秒为单位的*/
#define DEFAULT_REPS 1     /* 默认不重复发声 */
#define DEFAULT_DELAY 100  /* 同样以微秒为单位*/
 
/* 定义一个结构,存储所需的数据*/
typedef  struct  {
 
     int  freq;    /* 我们期望输出的频率,单位为Hz */
     int  length;  /* 发声长度,以微秒为单位*/
     int  reps;    /* 重复的次数*/
     int  delay;   /* 两次发声间隔,以微秒为单位*/
 
} beep_parms_t;
 
 
/* 打印帮助信息并退出*/
void  usage_bail (  const  char  *executable_name ) {
 
     printf  "Usage: \n \t%s [-f frequency] [-l length] [-r reps] [-d delay] \n " ,
     executable_name );
     exit (1);
 
}
 
/*===================================
* 分析运行参数,各项意义如下:
* "-f <以HZ为单位的频率值 >"
* "-l <以毫秒为单位的发声时长 >"
* "-r <重复次数 >"
* "-d <以毫秒为单位的间歇时长 >"
* =====================================*/
void  parse_command_line( char  **argv, beep_parms_t *result) {
 
     char  *arg0 = *(argv++);
     while  ( *argv ) {
 
         if  ( ! strcmp ( *argv, "-f"  )) {
  /*频率*/
             int  freq =  atoi  ( *( ++argv ) );
             if  ( ( freq <= 0 ) || ( freq > 10000 ) ) {
 
                 fprintf  ( stderr,  "Bad parameter: frequency must be from 1..10000\n"  );
                 exit  (1) ;
             
else  {
 
                 result->freq = freq;
                 argv++;
             
}
         
else  if  ( !  strcmp  ( *argv,  "-l"  ) ) {
  /*时长*/
             int  length =  atoi  ( *(++argv ) );
             if  (length < 0) {
 
                 fprintf (stderr,  "Bad parameter: length must be >= 0\n" );
                 exit (1);
             
else  {
 
                 result->length = length;
                 argv++;
             
}
         
else  if  (! strcmp (*argv,  "-r" )) {
  /*重复次数*/
             int  reps =  atoi (*(++argv));
             if  (reps < 0) {
 
                 fprintf (stderr,  "Bad parameter: reps must be >= 0\n" );
                 exit (1);
             
else  {
 
                 result->reps = reps;
                 argv++;
             
}
         
else  if  (! strcmp (*argv,  "-d" )) {
  /* 延时 */
             int  delay =  atoi (*(++argv));
             if  (delay < 0) {
 
                 fprintf (stderr,  "Bad parameter: delay must be >= 0\n" );
                 exit (1);
             
else  {
 
                 result->delay = delay;
                 argv++;
             
}
         
else  {
 
             fprintf (stderr,  "Bad parameter: %s\n" , *argv);
             usage_bail(arg0);
         
}
     
}
 
}
 
int  main( int  argc,  char  **argv) {
 
     int  console_fd;
     int  i;  /* 循环计数器 */
     /* 设发声参数为默认值*/
     beep_parms_t parms = {
DEFAULT_FREQ, DEFAULT_LENGTH, DEFAULT_REPS,
     DEFAULT_DELAY
};
     /* 分析参数,可能的话更新发声参数*/
     parse_command_line(argv, &parms);
 
     /* 打开控制台,失败则结束程序*/
     if  ( ( console_fd = open (  "/dev/console" , O_WRONLY ) ) == -1 ) {
 
         fprintf (stderr,  "Failed to open console.\n" );
         perror ( "open" );
         exit (1);
     
}
 
     /* 真正开始让扬声器发声*/
     for  (i = 0; i < parms.reps; i++) {
 
         /* 数字1190000从何而来,不得而知*/
         int  magical_fairy_number = 1190000/parms.freq;
 
         ioctl(console_fd, KIOCSOUND, magical_fairy_number);  /* 开始发声 */
         usleep(1000*parms.length);        /*等待... */
         ioctl(console_fd, KIOCSOUND, 0);  /* 停止发声*/
         usleep(1000*parms.delay);         /* 等待... */
     
/* 重复播放*/
     return  EXIT_SUCCESS;
 
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值