1 #include <stdio.h>
2 #include <termios.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <sys/ioctl.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9
10 #define PWM_IOCTL_SET_FREQ 1
11 #define PWM_IOCTL_STOP 0
12
13 #define ESC_KEY 0x1b
14
15 static int getch(void)
16 {
17 struct termios oldt,newt;
18 int ch;
19
20 //判断标准输入是否为终端
21 if (!isatty(STDIN_FILENO)) {
22 fprintf(stderr, "this problem should be run at a terminal\n");
23 exit(1);
24 }
25 //获取终端的相关参数
26 if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
27 perror("save the terminal setting");
28 exit(1);
29 }
30
31 //设置终端的相关参数
32 newt = oldt;
33 newt.c_lflag &= ~( ICANON | ECHO ); //不使用标准模式 不显示终端字符
34 if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
35 perror("set terminal");
36 exit(1);
37 }
38
39 ch = getchar();
40
41 // restore termial setting
42 if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
43 perror("restore the termial setting");
44 exit(1);
45 }
46 return ch;
47 }
48
49 static int fd = -1;
50 static void close_buzzer(void);
51 static void open_buzzer(void)
52 {
53 fd = open("/dev/pwm", 0);
54 if (fd < 0) {
55 perror("open pwm_buzzer device");
56 exit(1);
57 }
58
59 // any function exit call will stop the buzzer
60 atexit(close_buzzer); //exit函数运行时会调用close_buzzer进行一些清理工作
61 }
62
63 static void close_buzzer(void)
64 {
65 if (fd >= 0) {
66 ioctl(fd, PWM_IOCTL_STOP);
67 if (ioctl(fd, 2) < 0) {
68 perror("ioctl 2:");
69 }
70 close(fd);
71 fd = -1;
72 }
73 }
74
75 static void set_buzzer_freq(int freq)
76 {
77 // this IOCTL command is the key to set frequency
78 int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
79 if(ret < 0) {
80 perror("set the frequency of the buzzer");
81 exit(1);
82 }
83 }
84 static void stop_buzzer(void)
85 {
86 int ret = ioctl(fd, PWM_IOCTL_STOP);
87 if(ret < 0) {
88 perror("stop the buzzer");
89 exit(1);
90 }
91 if (ioctl(fd, 2) < 0) {
92 perror("ioctl 2:");
93 }
94 }
95
96 int main(int argc, char **argv)
97 {
98 int freq = 1000 ;
99
100 open_buzzer();
101
102 printf( "\nBUZZER TEST ( PWM Control )\n" );
103 printf( "Press +/- to increase/reduce the frequency of the BUZZER\n" ) ;
104 printf( "Press 'ESC' key to Exit this program\n\n" );
105
106
107 while( 1 )
108 {
109 int key;
110
111 set_buzzer_freq(freq);
112 printf( "\tFreq = %d\n", freq );
113
114 key = getch();//此处会阻塞 一直到读取到字符
115
116 switch(key) {
117 case '+':
118 if( freq < 20000 )
119 freq += 10;
120 break;
121
122 case '-':
123 if( freq > 11 )
124 freq -= 10 ;
125 break;
126
127 case ESC_KEY:
128 case EOF:
129 stop_buzzer();
130 exit(0);
131
132 default:
133 break;
134 }
135 }
136 }