Success is the sum of small efforts, repeated day in and day out.
成功就是日复一日那一点点小小努力的积累。
学习linux application program,和学习其它操作系统应用程序一样,API是和操作系统打交道的基础,纷繁复杂的函数会让人应接不暇,幸好有man的帮助,得以让我们在浩瀚的代码世界里有了方向。前面学习led和buttons的时候接触的函数比较少,也比较简单,慢慢的涉及到更多的设备和更复杂的操作时,各种各样的函数就会涌来,不要失去信心,只要在实践过程中慢慢积累,陌生的也会变得熟悉。
还是先由例程学起,由简入难,循序渐进,源码如下:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PWM_IOCTL_SET_FREQ 1
#define PWM_IOCTL_STOP 0
#define ESC_KEY 0x1b
static int getch(void)
{
struct termios oldt,newt;
int ch;
if (!isatty(STDIN_FILENO)) {
fprintf(stderr, "this problem should be run at a terminal\n");
exit(1);
}
// save terminal setting
if(tcgetattr(STDIN_FILENO, &oldt) < 0) {
perror("save the terminal setting");
exit(1);
}
// set terminal as need
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
if(tcsetattr(STDIN_FILENO,TCSANOW, &newt) < 0) {
perror("set terminal");
exit(1);
}
ch = getchar();
// restore termial setting
if(tcsetattr(STDIN_FILENO,TCSANOW,&oldt) < 0) {
perror("restore the termial setting");
exit(1);
}
return ch;
}
static int fd = -1;
static void close_buzzer(void);
static void open_buzzer(void)
{
fd = open("/dev/pwm", 0);
if (fd < 0) {
perror("open pwm_buzzer device");
exit(1);
}
// any function exit call will stop the buzzer
atexit(close_buzzer);
}
static void close_buzzer(void)
{
if (fd >= 0) {
ioctl(fd, PWM_IOCTL_STOP);
if (ioctl(fd, 2) < 0) {
perror("ioctl 2:");
}
close(fd);
fd = -1;
}
}
static void set_buzzer_freq(int freq)
{
// this IOCTL command is the key to set frequency
int ret = ioctl(fd, PWM_IOCTL_SET_FREQ, freq);
if(ret < 0) {
perror("set the frequency of the buzzer");
exit(1);
}
}
static void stop_buzzer(void)
{
int ret = ioctl(fd, PWM_IOCTL_STOP);
if(ret < 0) {
perror("stop the buzzer");
exit(1);
}
if (ioctl(fd, 2) < 0) {
perror("ioctl 2:");
}
}
int main(int argc, char **argv)
{
int freq = 1000 ;
open_buzzer();
printf( "\nBUZZER TEST ( PWM Control )\n" );
printf( "Press +/- to increase/reduce the frequency of the BUZZER\n" ) ;
printf( "Press 'ESC' key to Exit this program\n\n" );
while( 1 )
{
int key;
set_buzzer_freq(freq);
printf( "\tFreq = %d\n", freq );
key = getch();
switch(key) {
case '+':
if( freq < 20000 )
freq += 10;
break;
case '-':
if( freq > 11 )
freq -= 10 ;
break;
case ESC_KEY:
case EOF:
stop_buzzer();
exit(0);
default:
break;
}
}
}
以上是友善之臂提供的例程的源代码,实现了PWM控制蜂鸣器鸣响频率的功能,仔细分析下代码很容易就能读懂,如开篇所言,在读代码的过程中最好注意总结积累常用到的数据结构和API函数,如ioctl()、open()、close()、isatty()、tcgetattr()、tcsetattr()等等。
一味的读代码不思考不动手实践是远远不够的,必须得有点儿自己的一招半式,哪怕再简单也是你自己的想法,所以,前面实现了PWM控制蜂鸣器,我想写一个小程序,用PWM实现LED灯的渐明渐暗的效果,忙查了查数据手册,发现GPIO没有配置为PWM输出的功能(当然可以采用软件模拟的方法),另外,application总是依赖于driver的,虽然现在还没深入driver的学习,但是,现在,先不论对错,大胆想象谁也管不着啊,哈。。。继续往下学习。
欢迎大家扫描下方二维码关注我的个人微信公众号,一起交流学习,谢谢。