CubieBoard中文论坛

 找回密码
 立即注册
搜索
热搜: unable
查看: 16953|回复: 13

【原创】用C控制GPIO的代码[可以直接看CPU占用率了]

[复制链接]
发表于 2013-5-7 22:26:31 | 显示全部楼层 |阅读模式
本帖最后由 soloforce 于 2013-5-20 12:15 编辑

现在不需要通过写IO文件来操作GPIO了,请参考这个帖子:http://forum.cubietech.com/forum.php?mod=viewthread&tid=464&page=1&extra=#pid2719


写了个C语言控制GPIO的代码,目前只支持数字IO(只有0和1),分享一下。API模仿Arduino的风格,比较简单易用。
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>

  7. /**
  8. * Here we use the GPIO expansion near the SATA connector, from PD1 ~ PD7
  9. * */
  10. #define MIN_PIN 1
  11. #define MAX_PIN 7

  12. /**
  13. * Binary value that GPIO pins could accept
  14. * */
  15. typedef enum{
  16.     LOW=0,
  17.     HIGH=1
  18. }value_t;

  19. /**
  20. * GPIO pins get/set direction
  21. * */
  22. typedef enum{
  23.    IN=0,
  24.    OUT=1
  25. }direction_t;

  26. FILE* value_fp[MAX_PIN+1];

  27. /**
  28. * @brief Initialize the GPIO ports' value file pointers
  29. *
  30. * */
  31. void gpio_init()
  32. {
  33.     int i;
  34.     for(i=MIN_PIN;i<=MAX_PIN;i++)
  35.         value_fp[i]=NULL;
  36. }

  37. /**
  38. * @brief Uninitialize the GPIO ports, unexport those exported and close files.
  39. *
  40. * */
  41. int gpio_uninit()
  42. {
  43.     int i;
  44.     FILE *unexport_fp=fopen("/sys/class/gpio/unexport","w");
  45.     if(!unexport_fp) return -1;

  46.     for(i=MIN_PIN;i<=MAX_PIN;i++){
  47.         if(value_fp[i]){
  48.             fclose(value_fp[i]);
  49.             fprintf(unexport_fp,"%d",i);
  50.             fflush(unexport_fp);
  51.         }   
  52.     }

  53.     fclose(unexport_fp);

  54.     return 0;
  55. }

  56. /**
  57. * @brief Set the GPIO pins to specified direction
  58. *
  59. * @param pin: GPIO pin to set direction
  60. * @param dir: IN or OUT
  61. *
  62. * */
  63. int pinMode(int pin, direction_t dir)
  64. {
  65.     char direction_file[64];
  66.     char value_file[64];

  67.     FILE *export_fp=fopen("/sys/class/gpio/export","w");
  68.     if(!export_fp) return -1;
  69.    
  70.     fprintf(export_fp,"%d",pin);
  71.     sleep(1);
  72.     fclose(export_fp);

  73.     sprintf(direction_file,"/sys/class/gpio/gpio%d_pd%d/direction", pin, pin);
  74.     FILE *direction_fp=fopen(direction_file,"w");
  75.     if(!direction_fp) return -2;

  76.     if(dir==OUT){
  77.         fprintf(direction_fp,"out");
  78.     }else fprintf(direction_fp,"in");

  79.     fclose(direction_fp);

  80.     sprintf(value_file,"/sys/class/gpio/gpio%d_pd%d/value", pin, pin);
  81.     value_fp[pin]=fopen(value_file,"w");

  82.     if(!value_fp[pin]) return -3;


  83.     return 0;

  84. }

  85. /**
  86. * @brief Set the GPIO pins to specified binary value
  87. *
  88. * @param pin: GPIO pin to set value
  89. * @param value: LOW or HIGH
  90. *
  91. * */
  92. int digitalWrite(int pin, value_t value)
  93. {

  94.     if(!value_fp[pin])return -1;

  95.     if(pin<MIN_PIN) pin=MIN_PIN;
  96.     if(pin>MAX_PIN) pin=MAX_PIN;

  97.     fprintf(value_fp[pin],"%d", value);
  98.     fflush(value_fp[pin]);

  99.     return 0;
  100. }

  101. /**
  102. * @brief A demo to alternately set two GPIO pin's power level (LOW or HIGH),
  103. *       to flash a LED connected between the two pins.
  104. * */
  105. int main()
  106. {
  107.     gpio_init();

  108.     pinMode(1,OUT);
  109.     pinMode(2,OUT);

  110.     int i;
  111.     for(i=0;i<10;i++){
  112.         digitalWrite(1,HIGH);
  113.         digitalWrite(2,LOW);
  114.         sleep(1);

  115.         digitalWrite(1,LOW);
  116.         digitalWrite(2,HIGH);
  117.         sleep(1);
  118.     }

  119.     gpio_uninit();
  120. }
复制代码
回复

使用道具 举报

 楼主| 发表于 2013-5-8 18:16:53 | 显示全部楼层
本帖最后由 soloforce 于 2013-5-9 21:35 编辑

再发一个用GPIO控制LED显示当前CPU繁忙情况的小程序。
LED_cpu_usage.jpg
在GPIO的LD1~LD6接了3只LED,以二进制码形式显示CPU使用率。
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <string.h>
  8. #include <signal.h>


  9. /**
  10. * Here we use the GPIO expansion near the SATA connector, from PD1 ~ PD7
  11. * */
  12. #define MIN_PIN 1
  13. #define MAX_PIN 7

  14. /**
  15. * Binary value that GPIO pins could accept
  16. * */
  17. typedef enum{
  18.     LOW=0,
  19.     HIGH=1
  20. }value_t;

  21. /**
  22. * GPIO pins get/set direction
  23. * */
  24. typedef enum{
  25.    IN=0,
  26.    OUT=1
  27. }direction_t;

  28. typedef struct{
  29.     long int user,nice,sys,idle,iowait,irq,softirq;
  30. }jiffies_t;


  31. /**
  32. * GPIO pin values' file pointers
  33. * */
  34. FILE* value_fp[MAX_PIN+1]={NULL};

  35. /**
  36. * Signal actions structures
  37. * */
  38. struct sigaction int_act,term_act, old_act;


  39. /**
  40. * @brief Signal INT handler
  41. * */
  42. void sigint_handler(int sig_num)
  43. {
  44.     printf("Uninitialzing GPIO...\n");

  45.     /* uninitialize the GPIO */
  46.     gpio_uninit();

  47.     /* change back to the original handler */
  48.     sigaction(SIGINT, &old_act,NULL);

  49.    
  50.     /* emit the SIGINT again */
  51.     kill(0,SIGINT);
  52. }

  53. /**
  54. * @brief Signal TERM handler
  55. * */
  56. void sigterm_handler(int sig_num)
  57. {
  58.     printf("Uninitialzing GPIO...\n");

  59.     /* uninitialize the GPIO */
  60.     gpio_uninit();

  61.     /* change back to the original handler */
  62.     sigaction(SIGTERM, &old_act,NULL);

  63.     /* emit the SIGTERM again */
  64.     kill(0,SIGTERM);
  65. }


  66. /**
  67. * @brief Initialize signals
  68. * * */
  69. void catch_signal_init()
  70. {
  71.     memset(&int_act,0,sizeof(int_act));
  72.     memset(&term_act,0,sizeof(int_act));
  73.     memset(&old_act,0,sizeof(old_act));
  74.     int_act.sa_handler=&sigint_handler;
  75.     term_act.sa_handler=&sigterm_handler;
  76.     sigaction(SIGINT, &int_act, &old_act);
  77.     sigaction(SIGTERM, &term_act, &old_act);
  78. }


  79. /**
  80. * @brief Initialize the GPIO ports' value file pointers
  81. *
  82. * */
  83. void gpio_init()
  84. {
  85.     int i;
  86.     for(i=MIN_PIN;i<=MAX_PIN;i++)
  87.         value_fp[i]=NULL;

  88.     pinMode(1,OUT);
  89.     pinMode(2,OUT);
  90.     pinMode(3,OUT);
  91.     pinMode(4,OUT);
  92.     pinMode(5,OUT);
  93.     pinMode(6,OUT);
  94. }

  95. /**
  96. * @brief Uninitialize the GPIO ports, unexport those exported and close files.
  97. *
  98. * */
  99. int gpio_uninit()
  100. {
  101.     int i;
  102.     FILE *unexport_fp=fopen("/sys/class/gpio/unexport","w");
  103.     if(!unexport_fp) return -1;

  104.     for(i=MIN_PIN;i<=MAX_PIN;i++){
  105.         if(value_fp[i]){
  106.             fclose(value_fp[i]);
  107.             fprintf(unexport_fp,"%d",i);
  108.             fflush(unexport_fp);
  109.         }   
  110.     }

  111.     fclose(unexport_fp);

  112.     return 0;
  113. }

  114. /**
  115. * @brief Set the GPIO pins to specified direction
  116. *
  117. * @param pin: GPIO pin to set direction
  118. * @param dir: IN or OUT
  119. *
  120. * */
  121. int pinMode(int pin, direction_t dir)
  122. {
  123.     char direction_file[64];
  124.     char value_file[64];

  125.     FILE *export_fp=fopen("/sys/class/gpio/export","w");
  126.     if(!export_fp) return -1;
  127.    
  128.     fprintf(export_fp,"%d",pin);
  129.     sleep(1);
  130.     fclose(export_fp);

  131.     sprintf(direction_file,"/sys/class/gpio/gpio%d_pd%d/direction", pin, pin);
  132.     FILE *direction_fp=fopen(direction_file,"w");
  133.     if(!direction_fp) return -2;

  134.     if(dir==OUT){
  135.         fprintf(direction_fp,"out");
  136.     }else fprintf(direction_fp,"in");

  137.     fclose(direction_fp);

  138.     sprintf(value_file,"/sys/class/gpio/gpio%d_pd%d/value", pin, pin);
  139.     value_fp[pin]=fopen(value_file,"w");

  140.     if(!value_fp[pin]) return -3;


  141.     return 0;

  142. }

  143. /**
  144. * @brief Set the GPIO pins to specified binary value
  145. *
  146. * @param pin: GPIO pin to set value
  147. * @param value: LOW or HIGH
  148. *
  149. * */
  150. int digitalWrite(int pin, value_t value)
  151. {

  152.     if(!value_fp[pin])return -1;

  153.     if(pin<MIN_PIN) pin=MIN_PIN;
  154.     if(pin>MAX_PIN) pin=MAX_PIN;

  155.     fprintf(value_fp[pin],"%d", value);
  156.     fflush(value_fp[pin]);

  157.     return 0;
  158. }

  159. /**
  160. * @brief Get CPU jiffies from /proc/stat
  161. *
  162. * @param s(OUTPUT) Point of CPU jiffies structure
  163. *
  164. * */
  165. int get_jiffies(jiffies_t *s)
  166. {
  167.     char buf[128]={0};
  168.     char cpu[8]={0};

  169.     if(!s) return -1;
  170.     FILE* cpu_stat_fp = fopen("/proc/stat","r");
  171.     if(cpu_stat_fp == NULL){
  172.         return -1;
  173.     }

  174.     fgets(buf,sizeof(buf),cpu_stat_fp);
  175.     sscanf(buf,"%s%d%d%d%d%d%d%d",cpu, &(s->user),&(s->nice),&(s->sys),&(s->idle),&(s->iowait),&(s->irq),&(s->softirq));

  176.     fclose(cpu_stat_fp);
  177.     return 0;
  178. }

  179. /**
  180. * @brief Get CPU usage
  181. *
  182. * @param usage(OUTPUT): CPU usage in a short time
  183. *
  184. * */
  185. int get_cpu_usage(float * usage)
  186. {
  187.     jiffies_t j1,j2;
  188.     float all1, all2;
  189.     int status;

  190.     if(!usage) return -1;

  191.     status=get_jiffies(&j1);
  192.     if(status) return -2;
  193.     usleep(100000);
  194.     status=get_jiffies(&j2);
  195.     if(status) return -2;

  196.    
  197.     all1=j1.user+j1.nice+j1.sys+j1.idle+j1.iowait+j1.irq+j1.softirq;
  198.     all2=j2.user+j2.nice+j2.sys+j2.idle+j2.iowait+j2.irq+j2.softirq;

  199.     *usage=((all2-j2.idle)-(all1-j1.idle))/(all2-all1) ;

  200.     return 0;
  201. }

  202. /**
  203. * @brief Show CPU usage to LEDs in binary-mode
  204. *
  205. * @param n(INPUT): CPU usage level, from 0~7
  206. *
  207. * */
  208. void show_cpu_usage(int n)
  209. {

  210.     if(n & 0x04){
  211.         digitalWrite(1,LOW);
  212.         digitalWrite(2,HIGH);
  213.     }else{
  214.         digitalWrite(1,HIGH);
  215.         digitalWrite(2,LOW);
  216.     }


  217.     if(n & 0x02){
  218.         digitalWrite(3,LOW);
  219.         digitalWrite(4,HIGH);
  220.     }else{
  221.         digitalWrite(3,HIGH);
  222.         digitalWrite(4,LOW);
  223.     }


  224.     if(n & 0x01){
  225.         digitalWrite(5,LOW);
  226.         digitalWrite(6,HIGH);
  227.     }else{
  228.         digitalWrite(5,HIGH);
  229.         digitalWrite(6,LOW);
  230.     }
  231. }



  232. /**
  233. * @brief A daemon to show CPU usage through GPIO expansion
  234. *       to flash a LED connected between the two pins. Press Ctrl+C to Quit.
  235. * */
  236. int main()
  237. {
  238.     float usage;
  239.     pid_t pid=fork();
  240.    

  241.     /* Create a daemon process, and terminate the parent process. */
  242.     if(pid>0) exit(0);
  243.     if(pid<0) {
  244.         printf("Failed to create sub-process!\n");
  245.         exit(-1);
  246.     }
  247.     setsid();
  248.     catch_signal_init();
  249.     gpio_init();
  250.    
  251.     while(1){
  252.         if(get_cpu_usage(&usage)){
  253.             printf("Failed to get CPU usage!\n");
  254.             break;
  255.         }

  256.         int n=(int)(usage*8);
  257.         if(n>7) n=7;
  258.         show_cpu_usage(n);
  259.         sleep(1);
  260.     }

  261.    
  262. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2013-5-8 22:01:10 | 显示全部楼层
赞!代码很工整
回复 支持 反对

使用道具 举报

发表于 2013-5-8 23:04:26 | 显示全部楼层
{:soso_e100:} 看到使用了两种不同函数命名规则 :)
回复 支持 反对

使用道具 举报

发表于 2013-5-10 10:44:27 | 显示全部楼层
unix风格和arduino风格。。。
回复 支持 反对

使用道具 举报

发表于 2013-6-17 15:32:54 | 显示全部楼层
有没有可能把树莓派的 WiringPi 直接移植过来? 貌似他们的东西做得挺全的,有机会可以探讨一下
回复 支持 反对

使用道具 举报

发表于 2013-6-19 11:29:46 | 显示全部楼层
学习了,这个也是直接调用Python GPIO库?
回复 支持 反对

使用道具 举报

发表于 2013-6-29 20:17:33 | 显示全部楼层
特别喜欢arduino风格,和以前我学的Action Script 2&3很像~
回复 支持 反对

使用道具 举报

发表于 2013-7-8 13:31:01 | 显示全部楼层
py的库好像内容不丰富啊
回复 支持 反对

使用道具 举报

发表于 2013-7-9 15:00:04 | 显示全部楼层


版主有没有android的gpio的读写工具类或者源码
I2C读写的工具栏或源码呢?能否发一份呢?


谢谢!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|粤ICP备13051116号|cubie.cc---深刻的嵌入式技术讨论社区

GMT+8, 2024-4-24 08:35 , Processed in 0.026808 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2012 Comsenz Inc. | Style by Coxxs

返回顶部