plat_button驱动测试程序及select()函数、阻塞与非阻塞

platform总线按键驱动分析(精华版) 驱动做了三个多星期了,从helloworld到LED再到PlatformLED,现在终于到了按键驱动,对于驱动的理解深刻了不少,从完全看不懂到现在能够独立分析,进步很大,今天完成了按键驱动,做一个总结性的分享,给后面的自己看!加油!按键驱动:与之前不同,这次将按 阅读详情
Makefile文件:
  1 TEST_APP=event_button
  2 
  3 
  4 KERNEL_VER = linux-3.0
  5 LINUX_SRC ?= /home/fanmaolin/fl2440/kernel/$(KERNEL_VER)
  6 
  7 
  1 TEST_APP=event_button
  2 
  3 
  4 KERNEL_VER = linux-3.0
  5 LINUX_SRC ?= /home/fanmaolin/fl2440/kernel/$(KERNEL_VER)
  6 
  7 
 Makefile                                                                                                                           
  8 CROSS_COMPILE=/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-
  9 
 10 
 11 PWD := $(shell pwd)
 12 
 13 
 14 obj-m += kbd_device.o
 15 obj-m += kbd_driver.o
 16 
 17 
 18 modules:  
 19         @make -C $(LINUX_SRC) M=$(PWD) modules  
 20         @make clear  
 21         @chmod a+x *.ko && cp *.ko /tftp  
 22         @make testapp  
 23 
 24 
 25 clear:  
 26         @rm -f *.o *.cmd *.mod.c  
 27         @rm -rf  *~ core .depend  .tmp_versions Module.symvers modules.order -f  
 28         @rm -f .*ko.cmd .*.o.cmd .*.o.d  
 29 
 30 
 31 clean: clear
 32         @rm -f  *.ko ${TEST_APP}  
 33 
 34 
 35 testapp:  
 36         ${CROSS_COMPILE}gcc ${TEST_APP}.c -o ${TEST_APP} 


测试程序文件:

 + event_button.c                                                                                                                   
  1 /*********************************************************************************
  2  *      Copyright:  (C) 2017 fanmaolin<fanmaolinn@gmail.com>
  3  *                  All rights reserved.
  4  *
  5  *       Filename:  event_button.c
  6  *    Description:  This file 
  7  *                 
  8  *        Version:  1.0.0(04/17/2017)
  9  *         Author:  fanmaolin <fanmaolinn@gmail.com>
 10  *      ChangeLog:  1, Release initial version on "04/17/2017 05:37:17 AM"
 11  *                 
 12  ********************************************************************************/                                                                    
 13 
 14 #include <stdio.h>
 15 #include <unistd.h>
 16 #include <errno.h>
 17 #include <string.h>
 18 #include <stdlib.h>
 19 #include <unistd.h>
 20 #include <fcntl.h>
 21 #include <libgen.h>
 22 #include <getopt.h>
 23 #include <sys/types.h>
 24 #include <sys/ioctl.h>
 25 #include <linux/input.h>
 26 #include <linux/kd.h>
 27 #include <linux/keyboard.h>
 28 
 29 #if 0 /* Just for comment here, Reference to linux-3.3/include/linux/input.h */
 30 struct input_event 
 31 {
 32     struct timeval time;
 33     __u16 type;  /* 0x00:EV_SYN 0x01:EV_KEY 0x04:EV_MSC 0x11:EV_LED*/
 34     __u16 code;  /* key value, which key */
 35     __s32 value; /* 1: Pressed  0:Not pressed  2:Always Pressed */
 36 };  
 37 #endif
 38 
 39 #define TRUE               1
 40 #define FALSE              0
 41 
 42 #define EV_RELEASED        0
 43 #define EV_PRESSED         1
 44 #define EV_REPEAT          2
 45 
 46 #define BUTTON_CNT         5
 47 
 48 #define MODE_POLL          0x01
 49 #define MODE_NORMAL        0x02
 50 
 51 void usage(char *name);
 52 void display_button_event(struct input_event *ev, int cnt);
 53 
 54 int main(int argc, char **argv)
 55 {
 56     char                  *kbd_dev = NULL;
 57     char                  kbd_name[256] = "Unknown";
 58     int                   kbd_fd = -1;
 59 
 60     int                   rv, opt;
 61     int                   mode = MODE_NORMAL;
 62     int                   size = sizeof (struct input_event);
 63 
 64     struct input_event    ev[BUTTON_CNT];
 65 
 66     struct option long_options[] = {
 67         {"device", required_argument, NULL, 'd'},
 68         {"poll", no_argument, NULL, 'p'},
 69         {"help", no_argument, NULL, 'h'},
 70         {NULL, 0, NULL, 0}
 71     };
 72 
 73     while ((opt = getopt_long(argc, argv, "d:ph", long_options, NULL)) != -1)
 74     {
 75         switch (opt)
 76         {
 77             case 'd':
 78                 kbd_dev = optarg;
 79                 break;
 80 
 81             case 'p':
 82                 mode = MODE_POLL;
 83                 break;
 84 
 85             case 'h':
 86                 usage(argv[0]);
 87                 return 0;
 88 
 89             default:
 90                 break;
 91         }
 92     }
 93 
 94     if(NULL == kbd_dev)
 95     {
 96         usage(argv[0]);
 97         return -1;
 98     }
 99 
100     if ((getuid ()) != 0)
101         printf ("You are not root! This may not work...\n");
102 
103 
104     if ((kbd_fd = open(kbd_dev, O_RDONLY)) < 0)
105     {
106         printf("Open %s failure: %s", kbd_dev, strerror(errno));
107         return -1;
108     }
109 
110     ioctl (kbd_fd, EVIOCGNAME (sizeof (kbd_name)), kbd_name);
111     printf ("Monitor input device %s (%s) event with %s mode:\n", kbd_dev, kbd_name, MODE_POLL==mode?"poll":"infilit loop");
112 
113 
114 #if 0 /* Not implement in the Linux GPIO button driver */
115     unsigned char key_b[BUTTON_CNT/8 + 1];
116     memset(key_b, 0, sizeof(key_b));
117     if(ioctl(kbd_fd, EVIOCGKEY(sizeof(key_b)), key_b) < 0)
118     {
119         printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));
120         return -1;
121     }
122 #endif
123 
124 #if 0 /* Not implement in the Linux GPIO button driver */
125     /* rep[0]表示在按键重复出现之前 delay的时间,rep[1]表示按键重复出现的时间间隔。 */
126     int rep[2] ={2500, 1000} ;
127     if(ioctl(kbd_fd, EVIOCSREP, rep) < 0)
128     {
129         printf("EVIOCSREP ioctl get error: %s\n", strerror(errno));
130         return -1;
131     }
132 
133     if(ioctl(kbd_fd, EVIOCGREP, rep) < 0)
134     {
135         printf("EVIOCGKEY ioctl get error: %s\n", strerror(errno));
136         return -1;
137     }
138     else
139     {
140         printf("repeate speed: [0]= %d, [1] = %d/n", rep[0], rep[1]);
141     }
142 #endif
143 
144     while (1)
145     {
146         if(MODE_POLL==mode)
147         {
148             fd_set rds;
149             FD_ZERO(&rds);
150             FD_SET(kbd_fd, &rds);
151 
152             rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL);
153             if (rv < 0)
154             {
155                 printf("Select() system call failure: %s\n", strerror(errno));
156                 goto CleanUp;
157             }
158             else if (FD_ISSET(kbd_fd, &rds))
159             {
160                 if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
161                 {
162                     printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
163                     break;
164                 }
165                 else
166                 {
167                     display_button_event(ev, rv/size);
168                 }
169             }
170         }
171         else
172         {
173             if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
174             {
175                 printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
176                 break;
177             }
178             else
179             {
180                 display_button_event(ev, rv/size);
181             }
182         }
183     }
184 
185 CleanUp:
186     close(kbd_fd);
187 
188     return 0;
189 }
190 
191 void usage(char *name)
192 {
193     char *progname = NULL;
194     char *ptr = NULL;
195 
196     ptr = strdup(name);
197     progname = basename(ptr);
198 
199     printf("Usage: %s [-p] -d <device>\n", progname);
200     printf(" -d[device  ] button device name\n");
201     printf(" -p[poll    ] Use poll mode, or default use infinit loop.\n");
202     printf(" -h[help    ] Display this help information\n");
203 
204     free(ptr);
205 
206     return;
207 }
208 
209 void display_button_event(struct input_event *ev, int cnt)
210 {
211     int i;
212     struct timeval        pressed_time, duration_time;
213 
214     for(i=0; i<cnt; i++)
215     {
216         //printf("type:%d code:%d value:%d\n", ev[i].type, ev[i].code, ev[i].value);
217         if(EV_KEY==ev[i].type && EV_PRESSED==ev[i].value)
218         {
219             if(BTN_1 == ev[i].code)
220             {
221                 pressed_time = ev[i].time;
222                 printf("S1 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
223             }
224             else if(BTN_2 == ev[i].code)
225             {
226                 pressed_time = ev[i].time;
227                 printf("S2 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
228             }
229             else if(BTN_3 == ev[i].code)
230             {
231                 pressed_time = ev[i].time;
232                 printf("S3 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
233             }
234             else if(BTN_4 == ev[i].code)
235             {
236                 pressed_time = ev[i].time;
237                 printf("S4 button key[%d] pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
238             }
239             else
240             {
241                 pressed_time = ev[i].time;
242                 printf("button key[%d]  pressed time: %ld.%ld\n", ev[i].code, pressed_time.tv_sec, pressed_time.tv_usec);
243             }
244         }
245         if(EV_KEY==ev[i].type && EV_RELEASED==ev[i].value)
246         {
247             if(BTN_1 == ev[i].code)
248             {
249                 timersub(&ev[i].time, &pressed_time, &duration_time);
250                 printf("S1 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
 event_button.c                                                                                                                     
251                 printf("S1 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
252             }
253             else if(BTN_2 == ev[i].code)
254             {
255                 timersub(&ev[i].time, &pressed_time, &duration_time);
256                 printf("S2 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
257                 printf("S2 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
258             }
259             else if(BTN_3 == ev[i].code)
260             {
261                 timersub(&ev[i].time, &pressed_time, &duration_time);
262                 printf("S3 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
263                 printf("S3 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
264             }
265             else if(BTN_4 == ev[i].code)
266             {
267                 timersub(&ev[i].time, &pressed_time, &duration_time);
268                 printf("S4 button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
269                 printf("S4 button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
270             }
271             else
272             {
273                 timersub(&ev[i].time, &pressed_time, &duration_time);
274                 printf("button key[%d] released time: %ld.%ld\n", ev[i].code, ev[i].time.tv_sec, ev[i].time.tv_usec);
275                 printf("button key[%d] duration time: %ld.%ld\n", ev[i].code, duration_time.tv_sec, duration_time.tv_usec);
276             }
277         }
278     } /*  for(i=0; i<cnt; i++) */
279 }


[fanmaolin@Centeros button]$ make
make[1]: Entering directory `/home/fanmaolin/fl2440/kernel/linux-3.0'
  CC [M]  /home/fanmaolin/fl2440/driver/button/kbd_device.o
  CC [M]  /home/fanmaolin/fl2440/driver/button/kbd_driver.o
  Building modules, stage 2.
  MODPOST 2 modules
  CC      /home/fanmaolin/fl2440/driver/button/kbd_device.mod.o
  LD [M]  /home/fanmaolin/fl2440/driver/button/kbd_device.ko
  CC      /home/fanmaolin/fl2440/driver/button/kbd_driver.mod.o
  LD [M]  /home/fanmaolin/fl2440/driver/button/kbd_driver.ko
make[1]: Leaving directory `/home/fanmaolin/fl2440/kernel/linux-3.0'
make[1]: Entering directory `/home/fanmaolin/fl2440/driver/button'
make[1]: Leaving directory `/home/fanmaolin/fl2440/driver/button'
make[1]: Entering directory `/home/fanmaolin/fl2440/driver/button'
/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc event_button.c -o event_button
make[1]: Leaving directory `/home/fanmaolin/fl2440/driver/button'
[fanmaolin@Centeros button]$ /opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc event_button.c     
[fanmaolin@Centeros button]$ ls
a.out         event_button.c  kbd_device.ko  kbd_driver.h   Makefile
event_button  kbd_device.c    kbd_driver.c   kbd_driver.ko

在开发板上操作:


>: insmod kbd_device.ko 
S3C keyboard platform device register ok
>: insmod kbd_driver.ko 
input: s3c_kbd as /devices/platform/s3c_kbd.1/input/input0
s3c_kbd_probe ok
s3c keyboard platform driver register ok
>: ./a.out -p -d/dev/event0					//按键执行,检测按键
Monitor input device /dev/event0 (s3c_kbd) event with poll mode:
button key[2]  pressed time: 65.990097
button key[2] released time: 66.190063
button key[2] duration time: 1091798394.190055
button key[3]  pressed time: 68.800086
button key[3] released time: 69.5060
button key[3] duration time: 1091798397.5052
button key[4]  pressed time: 70.645089
button key[4] released time: 70.755058
button key[4] duration time: 1091798398.755050
button key[5]  pressed time: 73.760093
button key[5] released time: 74.63
button key[5] duration time: 1091798402.55



该测试文件可以显示按键时间


总结分析:

因为涉及到消抖处理,要注意该程序的select()函数及阻塞与非阻塞

if(MODE_POLL==mode)
        {
            fd_set rds;
            FD_ZERO(&rds);
            FD_SET(kbd_fd, &rds);

            rv = select(kbd_fd + 1, &rds, NULL, NULL, NULL);
            if (rv < 0)
            {
                printf("Select() system call failure: %s\n", strerror(errno));
                goto CleanUp;
            }
            else if (FD_ISSET(kbd_fd, &rds))
            { 
                if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
                {
                    printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
                    break;
                }
                else
                {
                    display_button_event(ev, rv/size);
                }
            }
        }
        else
        {
            if ((rv = read (kbd_fd, ev, size*BUTTON_CNT )) < size)
            {
                printf("Reading data from kbd_fd failure: %s\n", strerror(errno));
                break;
            }
            else
            {
                display_button_event(ev, rv/size);
            }
        }
我是这样理解阻塞与非阻塞的:

阻塞:当一个函数是阻塞的时,相当僵硬,你得等到事件发生,否则一直堵在这里

非阻塞:不管如何,执行完立刻返回,事件没来也不管。。。


所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。

所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高。可是使用Select就可以完成非阻塞方式工作的程序,它能够监视我们需要监视的文件描述符的变化情况——读写或是异常。


select()函数相当于一个监控辅助程序,如read()等阻塞函数,我们在调用read()时,程序会一直阻塞在这里,直到你按下按键,但是cpu时间宝贵,这个事件一直不发生就不能执行其他程序,效率太低,有了select()之后就相当于有个秘书,把阻塞丢给秘书,秘书会在这里判断事件是否发生,只有发生了才会扔给read处理。


int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval*timeout); 

第一,struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符(filedescriptor),即文件句柄,这可以是我们所说的普通意义的文件,当然Unix下任何设备、管道、FIFO等都是文件形式,全部包括在内,所以毫无疑问一个socket就是一个文件,socket句柄就是一个文件描述符。fd_set集合可以通过一些宏由人为来操作,比如清空集合FD_ZERO(fd_set *),将一个给定的文件描述符加入集合之中FD_SET(int ,fd_set*),将一个给定的文件描述符从集合中删除FD_CLR(int,fd_set*),检查集合中指定的文件描述符是否可以读写FD_ISSET(int ,fd_set* )。

第二,struct timeval是一个大家常用的结构,用来代表时间值,有两个成员,一个是秒数,另一个是毫秒数。 

具体解释select的参数: 
int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这个参数的值无所谓,可以设置不正确。 

fd_set * readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的读变化。 

fd_set * writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值。可以传入NULL值,表示不关心任何文件的写变化。 

fd_set * errorfds同上面两个参数的意图,用来监视文件错误异常。 

struct timeval * timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态,第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描述符发生变化为止;第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无变化返回0,有变化返回一个正值;第三,timeout的值大于0,这就是等待的超时时间,即select在timeout时间内阻塞,超时时间之内有事件到来就返回了,否则在超时后不管怎样一定返回,返回值同上述。 

返回值:返回状态发生变化的描述符总数。 
负值:select错误

正值:某些文件可读写或出错

0:等待超时,没有可读写或错误的文件





UDA1341声卡驱动与madplay移植播放mp3(第三方源代码移植步骤) 首先配置声卡UDA134驱动,看原理图 我们只需要将相应的IIS管脚设置为我们开发板的原理图设计的管脚就可以了。我们只要在/arch/arm/mach-s3c2440/mach-smdk2440.c文件中注册UDA1341 平台设备的控制端口就可以了,端口如上图所示,打开mach-smdk2440.c,添加如下内容: [fanmaolin@Centeros 阅读详情

相关推荐

fl2440移植RTC驱动及hwclock命令使用

RTC实时时钟  RTC(real time clock)实时时钟,主要作用是给Linux系统提供时间。RTC因为是电池供电的,所以掉电后时间不丢失。Linux内核把RTC用作“离线”的时间与日期维护器。当Linux内核启动时,它从RTC中读取时间与日期,作为基准值。在运行期间内核完全抛开RTC,以软件的形式维护系统的当前时间与日期,并在需要时将时间回写RTC芯片。另外如果RTC提供了IRQ中断

樊茂林的博客 1277

EVIOCGNAME:Get Device Name

linux内核提供了一个Input子系统来实现的,Input子系统会在/dev/input/路径下创建我们硬件输入设备的节点,一般情况下在我们的手机中这些节点是以eventXX来命名的,如event0,event1等等,可以利用EVIOCGNAME获取此事件结点名称。这就是a...

333

linux脚本使用-------安装madplay及MPlayer播放器脚本分析及命令参数前加“横杠”的背景解释

最近有考试这篇文章写了个开头就扔在了草稿箱,现在在把它搬出来,在学习代码语言的时候,有一个比较有效的学习过程,就是看别人的代码,读懂,理解透彻,然后模仿别人的代码,再自己写,边写边看,重点是运用。 以前接触过脚本,但是我是个菜鸟,这个是安装madplay和MPlayer的脚本 这里有几处说明: 1、# 表示注释 2、脚本是顺序执行的,没有指针等,相对比较简单,但是强大,

樊茂林的博客 1060

linux下使用ntpdate同步网络时间

为什么需要网络同步时间:Linux服务器运行久时,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在做数据库集群分片等操作时对多台机器的时间差是有要求的,此时就需要使用ntpdate进行时间同步安装ntpdate[fanmaolin@Centeros ~]$ sudo yum install ntpdate

樊茂林的博客 8529

pwm控制蜂鸣器驱动移植及初步认识Kconfig

S3C2440PWM定时器概述: PWM ( Pulse Width Modulation ) —— 脉宽调制,它是利用微控制器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等许多领域 。 S3C2440A 有5个16位定时器。其中定时器 0、1、2 和3具有脉宽调制(PWM)功能。定时器 4 是一个无输出引脚的内部定时器。定时器0

樊茂林的博客 1029

AltiumDesigner.zip

AltiumDesigner.zip

FL2440-WiFi模块学习之用rt3070无线网卡使开发板上网

主机操作系统:Centos 6.7 交叉编译器版本:buildroot-2012.08  开发板平台: FL2440  Linux内核版本: linux-3.0  开发模块:WIFI-STA模式使开发板上网 RT3070有两种工作模式:STA(station)模式和SoftAP(Access Point)模式。 STA模式就是笔记本上无线网卡模式,用来连接到无线路由器上上网

樊茂林的博客 1870

风储VSG-基于虚拟同步发电机的风储并网系统Simulink仿真

内容概要:本文介绍了“Plecs全桥LLC谐振变换器仿真模型”这一技术资源,聚焦于隔离型全桥LLC谐振变换器的建模、仿真与参数设计,涵盖其在电力电子系统中的关键应用,如软启动、闭环控制、变频控制及效率优化等。该模型支持对LLC变换器在不同工作模式下的动态响应与性能表现进行深入研究,适用于探究谐振拓扑结构、磁性元件设计、谐振参数匹配以及先进控制策略的科研与工程实践。同时,文档配套提供了仿真模型、设计报告与计算书等完整资料,强化了其实用性与教学价值。; 适合人群:具备电力电子、自动化或电气工程等相关专业背景,从事电力电子变换器研发、系统仿真与控制算法设计的科研人员、工程师及研究生。; 使用场景及目标:①用于全桥LLC谐振变换器的建模、仿真与动态性能分析;②支持对软启动过程、闭环稳压控制、变频调谐及效率优化等核心技术的研究与教学;③为电力电子电源系统的工程设计、参数优化与控制策略验证提供高精度仿真平台。; 阅读建议:建议结合Plecs或Simulink等仿真工具进行动手实践,重点理解电路拓扑构建、谐振参数计算、控制器设计与系统稳定性分析,并配合文档中的设计报告与计算书,系统掌握从理论到仿真的完整流程。

platform之led驱动分析及测试程序

什么是paltform总线: 一个现实的linux设备和驱动通常都需要挂接在一种总线上,比较常见的总线有USB、PCI总线等。但是,在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设却不依附与此类总线。基于这样的背景下,2.6内核加入了platform虚拟总线。platform机制将设备本身的资源注册进内核,有内核统一管理,在驱动程序使用这些资源时使用统一的接口,这

樊茂林的博客 1299

国央企创新负责人如何通过平台实现科技创新资源的系统集成与高效配置?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

独立储能的现货电能量与调频辅助服务市场出清协调机制(Matlab代码实现)

内容概要:本文介绍了“Plecs全桥LLC谐振变换器仿真模型”这一技术资源,聚焦于全桥LLC谐振变换器在电力电子系统中的建模与仿真研究。该资源提供了基于Plecs平台的高精度仿真模型,完整呈现了变换器的主电路拓扑、谐振参数设计、软开关实现机制及变频控制策略,能够有效支持对系统效率、动态响应与稳态性能的深入分析。模型充分体现了LLC谐振变换器在实现零电压开关(ZVS)、降低开关损耗和提升能量转换效率方面的优势,适用于新能源发电、储能系统及高效率电源设计等应用场景。; 适合人群:具备电力电子、自动控制及电路理论基础知识,从事电力电子变换器设计、新能源系统开发或相关领域研究的研究生、高校教师及工程技术人员。; 使用场景及目标:①用于全桥LLC谐振变换器的工作原理教学与参数设计实践;②支撑软开关特性、变频控制策略、效率优化等关键技术的仿真验证与性能评估;③作为科研项目、课程设计或毕业设计中电力电子系统仿真的核心参考模型,促进理论与工程实践的结合。; 阅读建议:建议使用者在掌握LLC谐振变换器基本工作原理的基础上,结合相关电力电子教材与Plecs软件操作指南,通过调整谐振元件参数、负载条件及控制策略进行多工况仿真,深入理解其工作机理与优化方法,并结合实验数据对比验证仿真结果的准确性。

fl2440内核自带按键驱动移植及hexdump命令

主机操作系统:Centos 6.7 交叉编译器版本:buildroot-2012.08  开发板平台: FL2440  Linux内核版本: linux-3.0  开发模块: linux内核自带按键驱动移植 1、修改arch/arm/mach-s3c2440/mach-smdk2440.c添加button驱动 添加头文件 #include #inclu

樊茂林的博客 1191

国产安路FPGA(二)-TD软件时序约束与硬件调试实战

本文深入探讨了国产安路FPGA开发中TD软件时序约束的实战应用。文章详细解析了SDC文件的核心语法,包括基础时钟、生成时钟及输入输出延迟约束的编写方法,并针对硬件调试中常见的时序问题提供了解决方案。通过一个图像处理流水线的优化案例,阐述了如何结合代码修改与约束设置,实现设计从“能跑”到“跑得稳”的关键提升,是掌握FPGA可靠设计的实用指南。

weixin_29183637的博客 378

s3c2440-led驱动分析注释及一次跑马灯测试程序

首先要明白字符设备驱动注册的基本流程: 当我们调用insomd命令加载驱动后,驱动程序从module_init函数开始执行:硬件初始化 -> 申请主次设备号 -> 定义fops(file_operations)结构体 -> 申请cdev结构体并把fops结构体嵌入cdev结构体中与之绑定 -> cdev字符设备的注册。 有一点需要明确的是,在Linux内核中,所有的设备都是以文件。我们

樊茂林的博客 1180

国产系统迁移实战:在银河麒麟V10上搞定Wine32位支持,让老Windows软件跑起来

本文详细介绍了在银河麒麟V10操作系统上构建Wine32位支持的全过程,帮助用户解决Windows应用迁移难题。从系统架构差异分析到Wine环境配置,再到实战应用部署与优化,提供了一套完整的解决方案,确保老Windows软件在国产系统上稳定运行。

weixin_32288959的博客 649

Zoom AI 技术架构研究:联合式方法与多模态集成

通过 Zoom AI 开放平台,企业可以自定义 AI 模块 (如法律合规审查、客户反馈分析),扩展应用场景。这种开放平台策略使企业能够根据自身需求定制 AI 功能,满足特定业务需求。

shao.bing的专栏 1318

内核自带LED驱动移植

在fl2440的内核中,本身已经有了LED驱动,我们要根据自己的需求将它使能即可,重要的是如何找到需要修改的位置,如何修改。在前面分析过我们自己写的驱动代码,内核中自带的驱动原理也大概相似,首先在make menuconfig 下添加内核对LED驱动的支持,然后我们要在内核的drivers/目录下找到leds,然后去看s3c24xx.c里的代码,前面在plat-led中分析过设备和驱动是如何找

樊茂林的博客 1163

双有源桥DC-DC变换器:原理、软开关与移相控制深度解析

隔离型DC-DC变换器是电力电子系统的核心部件,通过高频变压器实现电气隔离与电压匹配,保障系统安全与灵活适配。其工作原理基于功率半导体器件的开关动作,通过调制策略控制能量传输。该技术的核心价值在于实现高效、高功率密度的电能转换,并支持双向能量流动,这对于提升系统整体能效和运行灵活性至关重要。在新能源储能、电动汽车V2G及数据中心供电等场景中,双向能量流成为刚性需求,推动了如双有源桥等先进拓扑的应用。本文聚焦于双有源桥这一实现高效双向隔离变换的“明星”方案,深入剖析其利用移相控制实现软开关的机理。通过分析谐振

weixin_34195142的博客 380

驱动入门hello world

首先mkdir hello1文件夹,在下面编写hello.c vi hello.c  #include linux/init.h>   #include linux/module.h>   MODULE_LICENSE("Dual BSD/GPL");       static int hello_init(void)   {       printk(KERN_ALE

樊茂林的博客 686

Cadence公司的数字IC设计工具:综合工具(Genus)——(2)

介绍Cadence公司的数字IC设计工具Genus

qq_42922513的博客 1944

某音播放量查询,播放量接口研究,最新版本抓包,修改SO文件绕过SSL

本教程适用于某音27.8,64位版本,32为版本及某音旁侧版本修改方法大同小异,部分旁侧版本修改之后模拟器可能无法抓包,真机测试均可正常抓包,此方法修改后绝大部分包可以正常抓取,但部分包无法抓取,例如验证码,内置浏览器功能,如需抓取此类包可通过 Postern + Charles 实现。

byalipus的博客 1万+

Platform总线按键驱动分析(精华版)

驱动做了三个多星期了,从helloworld到LED再到PlatformLED,现在终于到了按键驱动,对于驱动的理解深刻了不少,从完全看不懂到现在能够独立分析,进步很大,今天完成了按键驱动,做一个总结性的分享,给后面的自己看!加油! 按键驱动: 与之前不同,这次将按键驱动按照platform总线的理解,设备链表和驱动链表,做成了两个模块,一个kbd_driver.c    一个kbd

樊茂林的博客 663

Comsol单层焊缝焊接数值模拟:温度场与应力场全流程解析

在工程制造领域,有限元模拟是研究焊接热-力行为、优化工艺参数的重要工具。焊接过程涉及强烈的局部加热和快速冷却,材料经历复杂的非线性和相变,必须通过瞬态分析和热-力顺序耦合,才能准确捕捉移动热源作用下的温度演化与应力塑性积累。这一技术广泛应用于压力容器、船舶结构、车辆制造等场景,用以预测残余应力与变形、评估冷裂纹风险,并为工艺设计提供定量支撑。焊接数值模拟能否真正指导实践,关键在于热源校核、随温度变化的材料参数、合理的边界条件与网格策略。单层焊缝作为焊接模拟的基础模型,涵盖了移动热源加载、熔池形成、高温软化与

weixin_30444111的博客 222

fl2440蜂鸣器测试程序和strcmp()及struct input_event 还有perror()浅析

前面移植了内核自带的蜂鸣器驱动,现在有时间写一个最简单的测试程序,功能是打开蜂鸣器,或者关闭蜂鸣器。 1 /********************************************************************************* 2 * Copyright: (C) 2017 fanmaolin 3 *

樊茂林的博客 576

YOLOv11改进策略【Conv和Transformer】| IJCAI 2024 利用FreqFormer中的SFA 空间 - 频率注意力和CTA 通道转置注意力 二次改进C3k2

在FreqFormer模型中,SFA(Spatial-Frequency Attention)和CTA(Channel Transposed Attention)模块是关键组成部分,它们针对传统Transformer在图像超分辨率任务中的不足而设计,旨在更好地恢复高频细节,提升模型性能。

Limiiiing的博客 759

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: Platform总线按键驱动分析(精华版)
下一篇: 内核添加USB驱动
fml1997
博客等级 码龄10年 30粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值