• 【驱动开发】控制stm32mp157a开发板三盏灯的亮灭


    编写应用程序控制三盏灯的亮灭

    head.h:

    1. #ifndef __HEAD_H__
    2. #define __HEAD_H__
    3. typedef struct
    4. {
    5. unsigned int MODER;
    6. unsigned int OTYPER;
    7. unsigned int OSPEEDR;
    8. unsigned int PUPDR;
    9. unsigned int IDR;
    10. unsigned int ODR;
    11. }gpio_t;
    12. //LED灯的寄存器地址
    13. #define LED1_ADDR 0X50006000
    14. #define LED2_ADDR 0X50007000
    15. #define LED3_ADDR 0X50006000
    16. #define RCC_ADDR 0X50000A28
    17. #endif

    demo.c:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "head.h"
    7. #include
    8. char kbuf[128] = {};
    9. unsigned int major;
    10. gpio_t *vir_led1;
    11. gpio_t *vir_led2;
    12. gpio_t *vir_led3;
    13. // 定义指针指向映射后的虚拟内存
    14. unsigned int *vir_rcc;
    15. // 封装操作方法
    16. int mycdev_open(struct inode *inode, struct file *file)
    17. {
    18. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    19. return 0;
    20. }
    21. ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
    22. {
    23. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    24. int ret;
    25. ret = copy_to_user(ubuf, kbuf, size);
    26. if (ret)
    27. {
    28. printk("copy_to_user filed\n");
    29. return -EIO;
    30. }
    31. return 0;
    32. }
    33. ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
    34. {
    35. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    36. int ret;
    37. ret = copy_from_user(kbuf, ubuf, size);
    38. if (ret)
    39. {
    40. printk("copy_from_user filed\n");
    41. return -EIO;
    42. }
    43. switch (kbuf[0])
    44. {
    45. case '1':
    46. if (kbuf[1] == '1') // 开灯
    47. vir_led1->ODR |= (0x1 << 10);
    48. else if (kbuf[1] == '0') // 关灯
    49. vir_led1->ODR &= (~(0x1 << 10));
    50. break;
    51. case '2':
    52. if (kbuf[1] == '1') // 开灯
    53. vir_led2->ODR |= (0x1 << 10);
    54. else if (kbuf[1] == '0') // 关灯
    55. vir_led2->ODR &= (~(0x1 << 10));
    56. break;
    57. case '3':
    58. if (kbuf[1] == '1') // 开灯
    59. vir_led3->ODR |= (0x1 << 8);
    60. else if (kbuf[1] == '0') // 关灯
    61. vir_led3->ODR &= (~(0x1 << 8));
    62. break;
    63. default:
    64. printk("输入错误\n");
    65. }
    66. return 0;
    67. }
    68. int mycdev_close(struct inode *inode, struct file *file)
    69. {
    70. printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    71. return 0;
    72. }
    73. // 定义操作方法结构体对象
    74. struct file_operations fops = {
    75. .open = mycdev_open,
    76. .read = mycdev_read,
    77. .write = mycdev_write,
    78. .release = mycdev_close,
    79. };
    80. static int __init mycdev_init(void)
    81. {
    82. // 注册字符设备驱动
    83. major = register_chrdev(0, "mychrdev", &fops);
    84. if (major < 0)
    85. {
    86. printk("字符设备驱动注册失败\n");
    87. return major;
    88. }
    89. printk("注册字符设备驱动成功major=%d\n", major);
    90. // 进行寄存器的地址映射
    91. vir_led1 = ioremap(LED1_ADDR, sizeof(gpio_t));
    92. if (vir_led1 == NULL)
    93. {
    94. printk("物理内存地址映射失败%d\n", __LINE__);
    95. return -EFAULT;
    96. }
    97. vir_led2 = ioremap(LED2_ADDR, sizeof(gpio_t));
    98. if (vir_led2 == NULL)
    99. {
    100. printk("物理内存地址映射失败%d\n", __LINE__);
    101. return -EFAULT;
    102. }
    103. vir_led3 = ioremap(LED3_ADDR, sizeof(gpio_t));
    104. if (vir_led3 == NULL)
    105. {
    106. printk("物理内存地址映射失败%d\n", __LINE__);
    107. return -EFAULT;
    108. }
    109. vir_rcc=ioremap(RCC_ADDR,4);
    110. if(vir_rcc == NULL)
    111. {
    112. printk("物理内存映射失败%d\n",__LINE__);
    113. return -EFAULT;
    114. }
    115. printk("寄存器内存映射成功\n");
    116. // 寄存器初始化
    117. (*vir_rcc) |= (0x3 << 4); // GPIOE控制器时钟使能
    118. // LED1
    119. vir_led1->MODER &= (~(0x3 << 20));
    120. vir_led1->MODER |= (0x1 << 20);
    121. vir_led1->ODR &= (~(0x1 << 10));
    122. // LED2
    123. vir_led2->MODER &= (~(0x3 << 20));
    124. vir_led2->MODER |= (0x1 << 20);
    125. vir_led2->ODR &= (~(0x1 << 10));
    126. // LED3
    127. vir_led3->MODER &= (~(0x3 << 16));
    128. vir_led3->MODER |= (0x1 << 16);
    129. vir_led3->ODR &= (~(0x1 << 8));
    130. printk("寄存器初始化成功\n");
    131. return 0;
    132. }
    133. static void __exit mycdev_exit(void)
    134. {
    135. // 取消内存映射
    136. iounmap(vir_led1);
    137. iounmap(vir_led2);
    138. iounmap(vir_rcc);
    139. // 注销字符设备驱动
    140. unregister_chrdev(major, "mychrdev");
    141. return 0;
    142. }
    143. module_init(mycdev_init);
    144. module_exit(mycdev_exit);
    145. MODULE_LICENSE("GPL");

    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. return -1;
    16. }
    17. printf("打开设备文件成功\n");
    18. while (1)
    19. {
    20. printf("请输入要控制的灯:1(LED1) 2(LED2) 3(LED3) >>>\n");
    21. printf("请输入您要进行的操作:1(开灯) 0(关灯) >>>\n");
    22. printf("请输入控制灯的两个字符 >>> ");
    23. fgets(buf, sizeof(buf), stdin); //在终端读一个字符串
    24. buf[strlen(buf) - 1] = '\0';
    25. write(fd, buf, sizeof(buf)); //将数据传递给内核
    26. }
    27. close(fd);
    28. return 0;
    29. }

  • 相关阅读:
    开源微信小程序商城源码PHP带后台管理——构建高效电商平台的基石
    vue(十)——插槽slot
    【云原生 | 从零开始学Kubernetes】二十七、配置管理中心Secret和rbac授权
    ubuntu上运行make menuconfig两种报错
    Taurus.MVC WebMVC 入门开发教程2:一个简单的页面呈现
    【Android笔记45】Android中几个常用对话框的使用
    oracle学习16-命令学习4
    mysql安装,安装mysql配置教程(超级详细图解)
    Redis高可用之主从复制原理演进分析
    vue面试题总结
  • 原文地址:https://blog.csdn.net/m0_68542867/article/details/133953740