• 【驱动开发】实现三盏灯的控制,编写应用程序测试


    head.h

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. //LED1:PE10
    4. //LED2:PF10
    5. //LED3:PE8
    6. #define LED_RCC 0X50000A28 //使能GPIO
    7. #define LED_MODER 0X50006000 //设置输出模式
    8. #define LED_ODR 0X50006014 //设置输出高低电平
    9. #define LED2_MODER 0X50007000 //设置输出模式
    10. #define LED2_ODR 0X50007014 //设置输出高低电平
    11. #endif

    mychrdev.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "head.h"
    7. unsigned int major; //保存主设备号
    8. char kbuf[128] = {0};
    9. unsigned int *vir_rcc;
    10. unsigned int *vir_moder;
    11. unsigned int *vir_odr;
    12. unsigned int *vir_moder_led2;
    13. unsigned int *vir_odr_led2;
    14. //封装操作方法
    15. int mycdev_open(struct inode *inode,struct file *file)
    16. {
    17. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    18. return 0;
    19. }
    20. ssize_t mycdev_read(struct file *file,char *ubuf,size_t size,loff_t *lof)
    21. {
    22. // printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    23. int ret;
    24. ret = copy_to_user(ubuf,kbuf,size);
    25. if(ret)
    26. {
    27. printk("copy_to_user err\n");
    28. return -EIO;
    29. }
    30. return 0;
    31. }
    32. ssize_t mycdev_write(struct file *file,const char *ubuf,size_t size,loff_t *lof)
    33. {
    34. //printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    35. int ret;
    36. ret = copy_from_user(kbuf,ubuf,size);
    37. if(ret)
    38. {
    39. printk("copy_from_user err\n");
    40. return -EIO;
    41. }
    42. //控制LED1-LED3开和关
    43. if(kbuf[0] == '1') //开灯
    44. {
    45. (*vir_odr) |= (0x1<<10); //输出高电平
    46. (*vir_odr_led2) |= (0x1<<10); //输出高电平
    47. (*vir_odr) |= (0x1<<8); //输出高电平
    48. }
    49. else if(kbuf[0] == '0') //关灯
    50. {
    51. (*vir_odr) &= (~(0x1<<10)); //输出低电平
    52. (*vir_odr_led2) &= (~(0x1<<10)); //输出高电平
    53. (*vir_odr) &= (~(0x1<<8)); //输出高电平
    54. }
    55. return 0;
    56. }
    57. int mycdev_close(struct inode *inode,struct file *file)
    58. {
    59. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    60. return 0;
    61. }
    62. struct file_operations fops={ //定义一个操作方法结构体对象并初始化
    63. .open = mycdev_open,
    64. .read = mycdev_read,
    65. .write = mycdev_write,
    66. .release = mycdev_close,
    67. };
    68. static int __init mycdev_init(void) //入口函数 安装内核模块时执行
    69. {
    70. major=register_chrdev(0,"mychrdev",&fops); //字符设备驱动的注册
    71. if(major<0)
    72. {
    73. printk("字符设备驱动注册失败\n");
    74. return major;
    75. }
    76. printk("字符设备驱动注册成功 major=%d\n",major);
    77. //进行LED控制相关寄存器的内存映射
    78. vir_rcc = ioremap(LED_RCC,4);
    79. if(vir_rcc == NULL)
    80. {
    81. printk("物理内存映射失败%d\n",__LINE__);
    82. return -EFAULT;
    83. }
    84. vir_moder = ioremap(LED_MODER,4);
    85. if(vir_moder == NULL)
    86. {
    87. printk("物理内存映射失败%d\n",__LINE__);
    88. return -EFAULT;
    89. }
    90. vir_odr = ioremap(LED_ODR,4);
    91. if(vir_odr == NULL)
    92. {
    93. printk("物理内存映射失败%d\n",__LINE__);
    94. return -EFAULT;
    95. }
    96. vir_moder_led2 = ioremap(LED2_MODER,4);
    97. if(vir_moder_led2 == NULL)
    98. {
    99. printk("物理内存映射失败%d\n",__LINE__);
    100. return -EFAULT;
    101. }
    102. vir_odr_led2 = ioremap(LED2_ODR,4);
    103. if(vir_odr_led2 == NULL)
    104. {
    105. printk("物理内存映射失败%d\n",__LINE__);
    106. return -EFAULT;
    107. }
    108. printk("寄存器内存映射成功\n");
    109. //控制led1-led3硬件寄存器的初始化
    110. (*vir_rcc) |= (0x1<<4); //RCC使能GPIO E组
    111. (*vir_rcc) |= (0x1<<5); //RCC使能GPIO F组
    112. (*vir_moder) &= (~(0x3<<20)); //设置PE10为输出
    113. (*vir_moder) |= (0x1<<20);
    114. (*vir_moder_led2) &= (~(0x3<<20)); //设置PF10为输出
    115. (*vir_moder_led2) |= (0x1<<20);
    116. (*vir_moder) &= (~(0x3<<16)); //设置PE8为输出
    117. (*vir_moder) |= (0x1<<16);
    118. (*vir_odr) &= (~(0x1<<10)); //设置led1默认关灯
    119. (*vir_odr_led2) &= (~(0x1<<10)); //设置led2默认关灯
    120. (*vir_odr) &= (~(0x1<<8)); //设置led3默认关灯
    121. return 0;
    122. }
    123. static void __exit mycdev_exit(void) //出口函数,卸载内核模块时执行
    124. {
    125. iounmap(vir_moder); //取消物理内存映射
    126. iounmap(vir_moder_led2); //取消物理内存映射
    127. iounmap(vir_odr); //取消物理内存映射
    128. iounmap(vir_odr_led2); //取消物理内存映射
    129. iounmap(vir_rcc); //取消物理内存映射
    130. unregister_chrdev(major,"mychrdev"); //注销字符设备驱动
    131. }
    132. module_init(mycdev_init); //用于声明当前内核模块入口函数的地址
    133. module_exit(mycdev_exit); //用于声明当前内核模块出口函数的地址
    134. MODULE_LICENSE("GPL"); //声明当前内核模块遵循GPL协议

    led_test.c

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    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. { //控制LED亮和灭
    19. printf("请输入LED的控制命令:1(开灯),0(关灯) >>");
    20. fgets(buf,sizeof(buf),stdin); //从终端输入数据传递到buf中
    21. buf[strlen(buf)-1] = '\0'; //末尾替换\n
    22. write(fd,buf,sizeof(buf));
    23. }
    24. return 0;
    25. }

     测试结果如下:

       

  • 相关阅读:
    深入讲解Netty那些事儿之从内核角度看IO模型(下)
    Python图像处理【1】图像与视频处理
    Uinux网络模型-IO模型
    【问题思考总结】数据链路层和传输层的功能是否重复冗余?(差错控制与流量控制)
    【MATLAB源码-第46期】基于matlab的OFDM系统多径数目对比,有无CP(循环前缀)对比,有无信道均衡对比。
    JavaScript 中的高阶函数
    Vue源码阅读笔记—— 数组是如何做到响应式的
    C++高级功能笔记
    网络安全(黑客技术)-高效自学
    leetcode 367 有效的完全平方数
  • 原文地址:https://blog.csdn.net/wangxiasun/article/details/132802618