自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux紅外驅(qū)動(dòng)重點(diǎn)解析

系統(tǒng) Linux
紅外遙控是我們經(jīng)常見到的一種無線收發(fā)設(shè)備,比如電視遙控,空調(diào)遙控,現(xiàn)在電視遙控有些慢慢變成了藍(lán)牙裝置。昨天是在知識星球里面看到有人提問,今天來解析一份網(wǎng)友寫的驅(qū)動(dòng)程序。

 [[400687]]

紅外遙控是我們經(jīng)常見到的一種無線收發(fā)設(shè)備,比如電視遙控,空調(diào)遙控,現(xiàn)在電視遙控有些慢慢變成了藍(lán)牙裝置。昨天是在知識星球里面看到有人提問,今天來解析一份網(wǎng)友寫的驅(qū)動(dòng)程序。

調(diào)試紅外需要注意幾個(gè)細(xì)節(jié)

1、我們發(fā)射的遙控器用肉眼是看不到的,需要拿相機(jī)來觀察。

2、紅外接收管和普通的二極管不同,如果用錯(cuò)物料也是不行的。

1.NEC協(xié)議無線傳輸數(shù)據(jù)原理

NEC協(xié)議的特征: 

1、8位地址和8位指令長度; 

2、地址和命令兩次傳輸;(確??煽啃裕?nbsp;

3、PWM脈沖寬度調(diào)制,以發(fā)射紅外載波的占空比代表“0”和“1”; 

4、載波頻率為38KHz 

5、位時(shí)間為1.125ms和2.25ms 

NEC碼位的定義:一個(gè)脈沖對應(yīng)560us的連續(xù)載波,一個(gè)邏輯1傳輸需要2.25ms(560us脈沖+1680us低電平),一個(gè)邏輯0的 傳輸需要1.125ms(560us脈沖+560us低電平)。

而遙控接收頭在收到脈沖時(shí)為低電平,在沒有收到脈沖時(shí)為高電平,因此, 我們在接收頭端收到的信號為:邏輯1應(yīng)該是560us低+1680us高,邏輯0應(yīng)該是560us低+560us高。

如下圖:

硬件

2. Linux下的驅(qū)動(dòng)接收程序

參考原文:

https://blog.csdn.net/wllw7176/article/details/110506677

兩個(gè)驅(qū)動(dòng)文件 

  1. gpio-ir-recv.c  
  2. /* Copyright (c) 2012, Code Aurora Forum. All rights reserved.  
  3.  *  
  4.  * This program is free software; you can redistribute it and/or modify  
  5.  * it under the terms of the GNU General Public License version 2 and  
  6.  * only version 2 as published by the Free Software Foundation.  
  7.  *  
  8.  * This program is distributed in the hope that it will be useful,  
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of  
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
  11.  * GNU General Public License for more details.  
  12.  */ 
  13. #include <linux/kernel.h>  
  14. #include <linux/init.h>  
  15. #include <linux/module.h>  
  16. #include <linux/interrupt.h>  
  17. #include <linux/gpio.h>  
  18. #include <linux/slab.h>  
  19. #include <linux/of.h>  
  20. #include <linux/of_gpio.h>  
  21. #include <linux/platform_device.h>  
  22. #include <linux/irq.h>  
  23. #include <media/rc-core.h>  
  24. #include <media/gpio-ir-recv.h>  
  25. #define GPIO_IR_DRIVER_NAME "gpio-rc-recv"  
  26. #define GPIO_IR_DEVICE_NAME "gpio_ir_recv"  
  27. struct gpio_rc_dev {  
  28.  struct rc_dev *rcdev;  
  29.  int gpio_nr;  
  30.  bool active_low;  
  31. };  
  32. #ifdef CONFIG_OF  
  33. /*  
  34.  * Translate OpenFirmware node properties into platform_data  
  35.  */  
  36. static int gpio_ir_recv_get_devtree_pdata(struct device *dev,  
  37.       struct gpio_ir_recv_platform_data *pdata)  
  38.  
  39.  struct device_node *np = dev->of_node;  
  40.  enum of_gpio_flags flags;  
  41.  int gpio;  
  42.  gpio = of_get_gpio_flags(np, 0, &flags);  
  43.  if (gpio < 0) {  
  44.   if (gpio != -EPROBE_DEFER)  
  45.    dev_err(dev, "Failed to get gpio flags (%d)\n", gpio);  
  46.   return gpio;  
  47.  }  
  48.  pdata->gpiogpio_nr = gpio;  
  49.  pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW);  
  50.  /* probe() takes care of map_name == NULL or allowed_protos == 0 */  
  51.  pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL);  
  52.  pdata->allowed_protos = 0 
  53.  return 0;  
  54.  
  55. static const struct of_device_id gpio_ir_recv_of_match[] = {  
  56.  { .compatible = "gpio-ir-receiver", },  
  57.  { },  
  58. };  
  59. MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match); 
  60. #else /* !CONFIG_OF */  
  61. #define gpio_ir_recv_get_devtree_pdata(dev, pdata) (-ENOSYS)  
  62. #endif  
  63. static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id) 
  64.  
  65.  struct gpio_rc_dev *gpio_dev = dev_id 
  66.  int gval;  
  67.  int rc = 0 
  68.  enum raw_event_type type = IR_SPACE 
  69.  gval = gpio_get_value(gpio_dev->gpio_nr);  
  70.  if (gval < 0 
  71.   goto err_get_value;  
  72.  if (gpio_dev->active_low)  
  73.   gval = !gval;  
  74.  if (gval == 1)  
  75.   type = IR_PULSE 
  76.  rc = ir_raw_event_store_edge(gpio_dev->rcdev, type);  
  77.  if (rc < 0 
  78.   goto err_get_value;  
  79.  ir_raw_event_handle(gpio_dev->rcdev);  
  80. err_get_value:  
  81.  return IRQ_HANDLED;  
  82.  
  83. static int gpio_ir_recv_probe(struct platform_device *pdev)  
  84.  
  85.  struct gpio_rc_dev *gpio_dev;  
  86.  struct rc_dev *rcdev;  
  87.  const struct gpio_ir_recv_platform_data *pdata =  
  88.      pdev->dev.platform_data;  
  89.  int rc;  
  90.  if (pdev->dev.of_node) {  
  91.   struct gpio_ir_recv_platform_data *dtpdata =  
  92.    devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL);  
  93.   if (!dtpdata)  
  94.    return -ENOMEM;  
  95.   rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata);  
  96.   if (rc)  
  97.    return rc;  
  98.   pdata = dtpdata 
  99.  }  
  100.  if (!pdata)  
  101.   return -EINVAL;  
  102.  if (pdata->gpio_nr < 0 
  103.   return -EINVAL;  
  104.  gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL);  
  105.  if (!gpio_dev)  
  106.   return -ENOMEM;  
  107.  rcdev = rc_allocate_device();  
  108.  if (!rcdev) {  
  109.   rc = -ENOMEM;  
  110.   goto err_allocate_device;  
  111.  }  
  112.  rcdev->priv = gpio_dev 
  113.  rcdev->driver_type = RC_DRIVER_IR_RAW 
  114.  rcdev->input_name = GPIO_IR_DEVICE_NAME 
  115.  rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";  
  116.  rcdev->input_id.bustype = BUS_HOST 
  117.  rcdev->input_id.vendor = 0x0001 
  118.  rcdev->input_id.product = 0x0001 
  119.  rcdev->input_id.version = 0x0100 
  120.  rcdev->dev.parent = &pdev->dev;  
  121.  rcdev->driver_name = GPIO_IR_DRIVER_NAME 
  122.  if (pdata->allowed_protos)  
  123.   rcdev->allowed_protocols = pdata->allowed_protos;  
  124.  else  
  125.   rcdev->allowed_protocols = RC_BIT_ALL 
  126.  rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;   
  127.  gpio_dev->rcdevrcdev = rcdev;  
  128.  gpio_dev->gpio_nr = pdata->gpio_nr;  
  129.  gpio_dev->active_low = pdata->active_low;  
  130.  rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");  
  131.  if (rc < 0 
  132.   goto err_gpio_request;  
  133.  rc  = gpio_direction_input(pdata->gpio_nr);  
  134.  if (rc < 0 
  135.   goto err_gpio_direction_input;  
  136.  rc = rc_register_device(rcdev);  
  137.  if (rc < 0) {  
  138.   dev_err(&pdev->dev, "failed to register rc device\n");  
  139.   goto err_register_rc_device;  
  140.  }  
  141.  platform_set_drvdata(pdev, gpio_dev);  
  142.  rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),  
  143.     gpio_ir_recv_irq,  
  144.    IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,  
  145.      "gpio-ir-recv-irq", gpio_dev);  
  146.  if (rc < 0 
  147.   goto err_request_irq;  
  148.  return 0;  
  149. err_request_irq:  
  150.  rc_unregister_device(rcdev);  
  151.  rcdev = NULL 
  152. err_register_rc_device:  
  153. err_gpio_direction_input:  
  154.  gpio_free(pdata->gpio_nr);  
  155. err_gpio_request:  
  156.  rc_free_device(rcdev);  
  157. err_allocate_device:  
  158.  kfree(gpio_dev);  
  159.  return rc;  
  160.  
  161. static int gpio_ir_recv_remove(struct platform_device *pdev) 
  162.  
  163.  struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);  
  164.  free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);  
  165.  rc_unregister_device(gpio_dev->rcdev);  
  166.  gpio_free(gpio_dev->gpio_nr);  
  167.  kfree(gpio_dev);  
  168.  return 0; 
  169.  
  170. #ifdef CONFIG_PM  
  171. static int gpio_ir_recv_suspend(struct device *dev)  
  172.  
  173.  struct platform_device *pdev = to_platform_device(dev);  
  174.  struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);  
  175.  if (device_may_wakeup(dev))  
  176.   enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));  
  177.  else  
  178.   disable_irq(gpio_to_irq(gpio_dev->gpio_nr));  
  179.  return 0;  
  180.  
  181. static int gpio_ir_recv_resume(struct device *dev)  
  182.  
  183.  struct platform_device *pdev = to_platform_device(dev);  
  184.  struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);  
  185.  if (device_may_wakeup(dev))  
  186.   disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));  
  187.  else  
  188.   enable_irq(gpio_to_irq(gpio_dev->gpio_nr));  
  189.  return 0;  
  190.  
  191. static const struct dev_pm_ops gpio_ir_recv_pm_ops = {  
  192.  .suspend        = gpio_ir_recv_suspend 
  193.  .resume         = gpio_ir_recv_resume 
  194. }; 
  195. #endif  
  196. static struct platform_driver gpio_ir_recv_driver = {  
  197.  .probe  = gpio_ir_recv_probe 
  198.  .remove = gpio_ir_recv_remove 
  199.  .driver = {  
  200.   .name   = GPIO_IR_DRIVER_NAME 
  201.   .of_match_table = of_match_ptr(gpio_ir_recv_of_match),  
  202. #ifdef CONFIG_PM  
  203.   .pm = &gpio_ir_recv_pm_ops,  
  204. #endif 
  205.  },  
  206. };  
  207. module_platform_driver(gpio_ir_recv_driver);  
  208. MODULE_DESCRIPTION("GPIO IR Receiver driver");  
  209. MODULE_LICENSE("GPL v2"); 

ir-nec-decoder.c 

  1. /* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol  
  2.  *  
  3.  * Copyright (C) 2010 by Mauro Carvalho Chehab  
  4.  *  
  5.  * This program is free software; you can redistribute it and/or modify  
  6.  *  it under the terms of the GNU General Public License as published by  
  7.  *  the Free Software Foundation version 2 of the License.  
  8.  *  
  9.  *  This program is distributed in the hope that it will be useful,  
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of  
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
  12.  *  GNU General Public License for more details.  
  13.  */  
  14. #include <linux/bitrev.h>  
  15. #include <linux/module.h>  
  16. #include "rc-core-priv.h"  
  17. #define NEC_NBITS  32  
  18. #define NEC_UNIT  562500  /* ns */  
  19. #define NEC_HEADER_PULSE (16 * NEC_UNIT)  
  20. #define NECX_HEADER_PULSE (8  * NEC_UNIT) /* Less common NEC variant */  
  21. #define NEC_HEADER_SPACE (8  * NEC_UNIT)  
  22. #define NEC_REPEAT_SPACE (4  * NEC_UNIT)  
  23. #define NEC_BIT_PULSE  (1  * NEC_UNIT)  
  24. #define NEC_BIT_0_SPACE  (1  * NEC_UNIT)  
  25. #define NEC_BIT_1_SPACE  (3  * NEC_UNIT)  
  26. #define NEC_TRAILER_PULSE (1  * NEC_UNIT)  
  27. #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */  
  28. #define NECX_REPEAT_BITS 1  
  29. enum nec_state {  
  30.  STATE_INACTIVE,  
  31.  STATE_HEADER_SPACE,  
  32.  STATE_BIT_PULSE,  
  33.  STATE_BIT_SPACE,  
  34.  STATE_TRAILER_PULSE,  
  35.  STATE_TRAILER_SPACE,  
  36. };  
  37. /**  
  38.  * ir_nec_decode() - Decode one NEC pulse or space  
  39.  * @dev: the struct rc_dev descriptor of the device  
  40.  * @duration: the struct ir_raw_event descriptor of the pulse/space  
  41.  *  
  42.  * This function returns -EINVAL if the pulse violates the state machine  
  43.  */  
  44. static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)  
  45.  
  46.  struct nec_dec *data = &dev->raw->nec;  
  47.  u32 scancode;  
  48.  u8 address, not_address, command, not_command;  
  49.  bool send_32bits = false 
  50.  if (!(dev->enabled_protocols & RC_BIT_NEC))  
  51.   return 0;  
  52.  if (!is_timing_event(ev)) {  
  53.   if (ev.reset)  
  54.    data->state = STATE_INACTIVE 
  55.   return 0;  
  56.  }  
  57.  IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",  
  58.      data->state, TO_US(ev.duration), TO_STR(ev.pulse));  
  59.  switch (data->state) {  
  60.  case STATE_INACTIVE:  
  61.   if (!ev.pulse)  
  62.    break;  
  63.   if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) {  
  64.    data->is_nec_x = false 
  65.    data->necx_repeat = false 
  66.   } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))  
  67.    data->is_nec_x = true 
  68.   else  
  69.    break;  
  70.   data->count = 0 
  71.   data->state = STATE_HEADER_SPACE 
  72.   return 0;  
  73.  case STATE_HEADER_SPACE:  
  74.   if (ev.pulse)  
  75.    break;  
  76.   if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) {  
  77.    data->state = STATE_BIT_PULSE 
  78.    return 0;  
  79.   } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {  
  80.    if (!dev->keypressed) {  
  81.     IR_dprintk(1, "Discarding last key repeat: event after key up\n");  
  82.    } else {  
  83.     rc_repeat(dev); 
  84.     IR_dprintk(1, "Repeat last key\n");  
  85.     data->state = STATE_TRAILER_PULSE 
  86.    }  
  87.    return 0;  
  88.   }  
  89.   break; 
  90.  case STATE_BIT_PULSE:  
  91.   if (!ev.pulse)  
  92.    break;  
  93.   if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))  
  94.    break;  
  95.   data->state = STATE_BIT_SPACE 
  96.   return 0;  
  97.  case STATE_BIT_SPACE:  
  98.   if (ev.pulse)  
  99.    break;  
  100.   if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&  
  101.    geq_margin(ev.duration, 
  102.     NEC_TRAILER_SPACE, NEC_UNIT / 2)) {  
  103.     IR_dprintk(1, "Repeat last key\n");  
  104.     rc_repeat(dev);  
  105.     data->state = STATE_INACTIVE 
  106.     return 0;  
  107.   } else if (data->count > NECX_REPEAT_BITS)  
  108.    data->necx_repeat = false 
  109.   data->bits <<= 1;  
  110.   if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2) 
  111.    data->bits |= 1;  
  112.   else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))  
  113.    break;  
  114.   data->count++;  
  115.   if (data->count == NEC_NBITS)  
  116.    data->state = STATE_TRAILER_PULSE 
  117.   else  
  118.    data->state = STATE_BIT_PULSE 
  119.   return 0;  
  120.  case STATE_TRAILER_PULSE:  
  121.   if (!ev.pulse)  
  122.    break;  
  123.   if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))  
  124.    break; 
  125.   data->state = STATE_TRAILER_SPACE 
  126.   return 0; 
  127.  case STATE_TRAILER_SPACE:  
  128.   if (ev.pulse)  
  129.    break;  
  130.   if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))  
  131.    break;  
  132.   address     = bitrev8((data->bits >> 24) & 0xff);  
  133.   not_address = bitrev8((data->bits >> 16) & 0xff);  
  134.   command     = bitrev8((data->bits >>  8) & 0xff);  
  135.   not_command = bitrev8((data->bits >>  0) & 0xff);  
  136.   if ((command ^ not_command) != 0xff) {  
  137.    IR_dprintk(1, "NEC checksum error: received 0x%08x\n",  
  138.        data->bits);  
  139.    send_32bits = true 
  140.   }  
  141.   if (send_32bits) {  
  142.    /* NEC transport, but modified protocol, used by at  
  143.     * least Apple and TiVo remotes */  
  144.    scancode = data->bits;  
  145.    IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);  
  146.   } else if ((address ^ not_address) != 0xff) {  
  147.    /* Extended NEC */  
  148.    scancode = address     << 16 |  
  149.        not_address <<  8 |  
  150.        command;  
  151.    IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);  
  152.   } else {  
  153.    /* Normal NEC */  
  154.    scancode = address << 8 | command;  
  155.    IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);  
  156.   }  
  157.   if (data->is_nec_x)  
  158.    data->necx_repeat = true 
  159.   rc_keydown(dev, RC_TYPE_NEC, scancode, 0);  
  160.   data->state = STATE_INACTIVE 
  161.   return 0;  
  162.  }  
  163.  IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",  
  164.      data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));  
  165.  data->state = STATE_INACTIVE 
  166.  return -EINVAL;  
  167.  
  168. static struct ir_raw_handler nec_handler = {  
  169.  .protocols = RC_BIT_NEC 
  170.  .decode  = ir_nec_decode 
  171. };  
  172. static int __init ir_nec_decode_init(void)  
  173.  
  174.  ir_raw_handler_register(&nec_handler);  
  175.  printk(KERN_INFO "IR NEC protocol handler initialized\n");  
  176.  return 0; 
  177.  
  178. static void __exit ir_nec_decode_exit(void)  
  179.  
  180.  ir_raw_handler_unregister(&nec_handler);  
  181.  
  182. module_init(ir_nec_decode_init);  
  183. module_exit(ir_nec_decode_exit);   
  184. MODULE_LICENSE("GPL");  
  185. MODULE_AUTHOR("Mauro Carvalho Chehab");  
  186. MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");  
  187. MODULE_DESCRIPTION("NEC IR protocol decoder"); 

參考文章中的dts文件: 

  1. gpio-ir-receiver {  
  2.     compatible = "gpio-ir-receiver" 
  3.     gpios = <&gpio4 19 GPIO_ACTIVE_HIGH>; //連接紅外的中斷引腳  
  4.     active_low = <1>;                     //紅外接收器是否將信號取反,有些紅外接收器會(huì)將接收到的高低電平信號反向輸出,比如我使用的hx1838紅外接收器  
  5.     linux,rc-map-name = "rc-hx18380-carmp3"; //紅外scancode與實(shí)際input_evnent code映射表名稱,要在rc_register_device注冊,具體見gpio-ir-recv.c  
  6.     allowed_protos = <0x100>; /*NEC protocol*/ //保留,驅(qū)動(dòng)中并未使用  
  7. }; 

另一個(gè)文件里面調(diào)用的

ir-nec-decoder.c

這個(gè)函數(shù)是Linux內(nèi)核中的紅外處理申請函數(shù)

這里主要是注冊一個(gè)解碼的結(jié)構(gòu)體

ir-nec-decoder.c

3.中斷處理程序解析

gpio-ir-recv.c

ir_raw_event_store_edge() 這個(gè)函數(shù)用來計(jì)算電平的持續(xù)時(shí)間。

ir_raw_event_handle() 用來處理這個(gè)電平表示什么含義。

驅(qū)動(dòng)程序里面,首先是判斷當(dāng)前GPIO電平,如果是低電平,就進(jìn)入紅外解析,如果不是,或者獲取失敗,就退出程序。

4.紅外數(shù)據(jù)處理程序解析

內(nèi)核專門開了一個(gè)線程來處理數(shù)據(jù)解析

rc-ir-raw.c

處理函數(shù)其實(shí)就是處理電平時(shí)間長短來決定數(shù)字信號

ir-nec-decoder.c

這里是判斷頭,這個(gè)時(shí)間和9ms進(jìn)行比較

9ms 從哪里來的,可以看看這里

ir-nec-decoder.c

拿到頭后,這個(gè)switch函數(shù)就繼續(xù)往下跑

ir-nec-decoder.c

然后就是判斷 1 和 0  的時(shí)候了

ir-nec-decoder.c

上面那個(gè)就是1,下面那個(gè)就是0。

4.然后數(shù)據(jù)怎么上報(bào)呢?

ir-nec-decoder.c

這里是在另一個(gè)模塊中注冊的映射

不同的紅外鍵值對應(yīng)不同的上報(bào)按鍵鍵值

rc-trekstor.c

 

 

責(zé)任編輯:龐桂玉 來源: 良許Linux
相關(guān)推薦

2012-07-06 15:23:28

Linux集群

2010-05-20 08:49:52

MyEclipse8.

2016-05-12 14:45:29

IBM大型機(jī)LinuxONE

2010-08-03 12:53:51

FlexBuilder

2009-12-10 13:43:08

使用PHPExcel

2011-01-27 11:18:27

三級信息管理

2011-01-20 11:14:50

三級信息管理

2011-01-17 11:33:01

三級信息管理

2015-03-27 22:23:28

FreeSyncLiquidVR

2010-06-17 15:54:24

UML總結(jié)

2009-12-29 16:36:47

Silverlight

2017-09-30 10:17:24

云計(jì)算PaaS容器云

2010-08-09 10:03:43

FlexBuilder

2009-12-31 16:50:02

Silverlight

2010-02-22 17:13:40

WCF會(huì)話狀態(tài)

2021-08-10 11:30:30

Linux代碼中斷控制器

2021-08-03 15:10:26

Linux代碼驅(qū)動(dòng)

2011-09-16 11:23:10

布線布線系統(tǒng)線纜

2010-01-28 13:50:03

Android移植

2009-12-24 09:48:29

WPF分割條
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號