• 基于GPIO子系统编写LED驱动


    编写应用程序进行测试

    设置定时器,每5秒打印一次hello world

    驱动程序

    1. #include <linux/init.h>
    2. #include <linux/module.h>
    3. #include<linux/of.h>
    4. #include<linux/of_gpio.h>
    5. #include<linux/fs.h>
    6. #include<linux/io.h>
    7. #include<linux/gpio.h>
    8. /* myled
    9. {
    10. led1-gpio=<&gpioe 10 0>;
    11. led2-gpio=<&gpiof 10 0>;
    12. led3-gpio=<&gpioe 8 0>;
    13. };
    14. */
    15. struct device_node *dnode;
    16. unsigned int gpiono;
    17. unsigned int gpiono2;
    18. unsigned int gpiono3;
    19. struct timer_list mytimer;
    20. char kbuf[128]={0};
    21. int major;
    22. //定时器处理函数
    23. void mytimer_function(struct timer_list *timer)
    24. {
    25. //打印
    26. printk("hello world\n");
    27. //再次启用定时器
    28. mod_timer(timer,jiffies+5*HZ);
    29. }
    30. ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
    31. {
    32. int net = copy_from_user(kbuf, ubuf, size);
    33. if (net)
    34. {
    35. printk("copy_from_user filed\n");
    36. return -EIO;
    37. }
    38. switch(kbuf[0]){
    39. case '1'://LED1
    40. if(kbuf[1]=='0')//关灯
    41. gpio_set_value(gpiono,0);
    42. else
    43. //灯亮
    44. gpio_set_value(gpiono,1);
    45. break;
    46. case '2'://LED2
    47. if(kbuf[1]=='0')//关灯
    48. gpio_set_value(gpiono2,0);
    49. else
    50. //灯亮
    51. gpio_set_value(gpiono2,1);
    52. break;
    53. case '3'://LED3
    54. if(kbuf[1]=='0')//关灯
    55. gpio_set_value(gpiono3,0);
    56. else
    57. //灯亮
    58. gpio_set_value(gpiono3,1);
    59. break;
    60. }
    61. return 0;
    62. }
    63. struct file_operations fops={
    64. .write=mycdev_write,
    65. };
    66. static int __init mycdev_init(void)
    67. {
    68. //字符设备驱动注册
    69. major=register_chrdev(0,"mychrdev",&fops);
    70. if(major<0)
    71. {
    72. printk("字符设备驱动注册失败\n");
    73. return major;
    74. }
    75. printk("字符设备驱动注册成功:major=%d\n",major);
    76. //解析设备树节点信息
    77. dnode=of_find_node_by_path("/myled");
    78. if(dnode==NULL)
    79. {
    80. printk("解析设备树节点失败\n");
    81. return -ENXIO;
    82. }
    83. //获取LED1 GPIO编号
    84. gpiono=of_get_named_gpio(dnode,"led1-gpio",0);
    85. if(gpiono<0)
    86. {
    87. printk("获取GPIO编号失败\n");
    88. return -ENXIO;
    89. }
    90. gpiono2=of_get_named_gpio(dnode,"led2-gpio",0);
    91. if(gpiono2<0)
    92. {
    93. printk("获取GPIO编号失败\n");
    94. return -ENXIO;
    95. }
    96. gpiono3=of_get_named_gpio(dnode,"led3-gpio",0);
    97. if(gpiono3<0)
    98. {
    99. printk("获取GPIO编号失败\n");
    100. return -ENXIO;
    101. }
    102. //申请gpio编号
    103. int ret=gpio_request(gpiono,NULL);
    104. if(ret)
    105. {
    106. printk("申请GPIO编号失败\n");
    107. return -ENXIO;
    108. }
    109. printk("申请GPIO编号成功:%d\n",gpiono);
    110. //申请gpio编号
    111. int ret2=gpio_request(gpiono2,NULL);
    112. if(ret2)
    113. {
    114. printk("申请GPIO编号失败\n");
    115. return -ENXIO;
    116. }
    117. printk("申请GPIO编号成功:%d\n",gpiono2);
    118. //申请gpio编号
    119. int ret3=gpio_request(gpiono3,NULL);
    120. if(ret3)
    121. {
    122. printk("申请GPIO编号失败\n");
    123. return -ENXIO;
    124. }
    125. printk("申请GPIO编号成功:%d\n",gpiono3);
    126. //初始化定时器对象
    127. timer_setup(&mytimer,mytimer_function,0);
    128. mytimer.expires=jiffies+5*HZ;//定时1s;
    129. //注册定时器
    130. add_timer(&mytimer);
    131. //设置GPIO为输出
    132. ret=gpio_direction_output(gpiono,0);
    133. if(ret)
    134. {
    135. printk("GPIO输出设置失败\n");
    136. return -1;
    137. }
    138. //设置GPIO为输出
    139. ret2=gpio_direction_output(gpiono2,0);
    140. if(ret2)
    141. {
    142. printk("GPIO输出设置失败\n");
    143. return -1;
    144. }
    145. //设置GPIO为输出
    146. ret3=gpio_direction_output(gpiono3,0);
    147. if(ret3)
    148. {
    149. printk("GPIO输出设置失败\n");
    150. return -1;
    151. }
    152. // //灯亮
    153. // gpio_set_value(gpiono,1);
    154. // //灯亮
    155. // gpio_set_value(gpiono2,1);
    156. // //灯亮
    157. // gpio_set_value(gpiono3,1);
    158. return 0;
    159. }
    160. static void __exit mycdev_exit(void)
    161. {
    162. //注销定时器
    163. del_timer(&mytimer);
    164. //gpiod_set_value(gpiono,0);
    165. gpio_set_value(gpiono,0);
    166. gpio_set_value(gpiono2,0);
    167. gpio_set_value(gpiono3,0);
    168. //释放GPIO编号
    169. gpio_free(gpiono);
    170. //释放GPIO编号
    171. gpio_free(gpiono2);
    172. //释放GPIO编号
    173. gpio_free(gpiono3);
    174. //注销字符设备驱动
    175. unregister_chrdev(major,"mychrdev");
    176. }
    177. module_init(mycdev_init);
    178. module_exit(mycdev_exit);
    179. MODULE_LICENSE("GPL");

    应用程序

    1. #include<stdlib.h>
    2. #include<stdio.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <fcntl.h>
    6. #include<unistd.h>
    7. #include<string.h>
    8. int main(int argc, char const *argv[])
    9. {
    10. char buf[128]={0};
    11. int fd=open("/dev/mychrdev",O_RDWR);
    12. if(fd<0)
    13. {
    14. printf("打开设备文件失败\n");
    15. exit(-1);
    16. }
    17. while(1)
    18. {
    19. //从终端读取
    20. printf("请输入两个字符\n");
    21. printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");
    22. printf("第二个字符:0(关灯) 1(开灯)\n");
    23. printf("请输入>");
    24. fgets(buf,sizeof(buf),stdin);
    25. buf[strlen(buf)-1]='\0';
    26. //向设备文件中写
    27. write(fd,buf,sizeof(buf));
    28. }
    29. return 0;
    30. }

  • 相关阅读:
    Python利用torch.max函数计算一批特征图中每个通道的最大值
    NGS基础---Plink文件格式ped/map和bed/bim/fam
    股票四倍杠杆什么意思?
    openGauss学习笔记-62 openGauss 数据库管理-两地三中心跨Region容灾
    手机进销存软件在企业中的应用
    Centos7把home目录下多余的空间转移到/根目录下
    机器学习中 TP FP TN FN的概念
    Sosyal Lig Arena VoxEdit 比赛
    Mac 安装 boost(bjam)
    SpringMVC如何实现重定向和转发呢?
  • 原文地址:https://blog.csdn.net/m0_73775266/article/details/134082784