STM32MP157A单片机驱动--控制拓展版的灯实现流水结果

打印 上一主题 下一主题

主题 985|帖子 985|积分 2955

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. 1.注册字符设备驱动
  2. int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
  3. 功能:进行字符设备驱动的注册,申请了256个次设备号(0-255)
  4. 参数:
  5.     major:   >0:手动指定的当前驱动的主设备号
  6.             ==0:由系统内核动态分配一个主设备号
  7.     name:设备名或者驱动名
  8.     fops:操作方法对象指针
  9.         /*
  10.             应用程序调用文件操作接口对设备文件进行操作时,驱动中要有操作方法被回调,想要这些操作方法被回调,需要将
  11.             操作方法的指针放在一个操作方法对象中进行统一管理
  12.             struct file_operations {
  13.                     int (*open) (struct inode *, struct file *);
  14.                   ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
  15.                  ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
  16.                    int (*release) (struct inode *, struct file *);
  17.                    };
  18.         */
  19. 返回值:
  20.     调用失败返回错误码
  21.     成功:
  22.         major==0,成功返回动态申请的主设备号
  23.         major>0,成功返回0
复制代码
  1. 2.注销字符设备驱动
  2. void unregister_chrdev(unsigned int major, const char *name)
  3. 功能:进行字符设备驱动的注销
  4. 参数:
  5.     major:注册时得到的主设备号
  6.     name:注册时填写的设备名
  7. 返回值:无
复制代码

  led.c
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/fs.h>
  4. #include <linux/uaccess.h>
  5. #include <linux/io.h>
  6. #define LED1_PHY_GPIO_MODER 0x50006000
  7. #define LED1_PHY_GPIO_ODR   0x50006014
  8. #define LED1_PHY_RCC_GPIO   0x50000A28
  9. #define LED2_PHY_GPIO_MODER 0x50007000
  10. #define LED2_PHY_GPIO_ODR   0x50007014
  11. #define LED2_PHY_RCC_GPIO   0x50000A2C
  12. #define LED3_PHY_GPIO_MODER 0x50006000
  13. #define LED3_PHY_GPIO_ODR   0x50006014
  14. #define LED3_PHY_RCC_GPIO   0x50000A28
  15. unsigned int major;  // 保存主设备号
  16. char kbuf[128] = {0};
  17. unsigned int *led1_vir_moder;
  18. unsigned int *led1_vir_odr;
  19. unsigned int *led1_vir_rcc;
  20. unsigned int *led2_vir_moder;
  21. unsigned int *led2_vir_odr;
  22. unsigned int *led2_vir_rcc;
  23. unsigned int *led3_vir_moder;
  24. unsigned int *led3_vir_odr;
  25. unsigned int *led3_vir_rcc;
  26. // 封装各种操作方法
  27. int myled_open(struct inode *inode, struct file *file) {
  28.     printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  29.     return 0;
  30. }
  31. ssize_t myled_read(struct file *file, char __user *ubuf, size_t size, loff_t *lft) {
  32.     unsigned long ret = copy_to_user(ubuf, kbuf, size);
  33.     if (ret) {
  34.         printk("copy_to_user failed\n");
  35.         return -ret;
  36.     }
  37.     return 0;
  38. }
  39. ssize_t myled_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lft) {
  40.     unsigned long ret = copy_from_user(kbuf, ubuf, size);
  41.     if (ret) {
  42.         printk("copy_from_user failed\n");
  43.         return -ret;
  44.     }
  45.     if (strcmp(kbuf, "1") == 0) {  // 点亮 LED1
  46.         *led1_vir_odr |= (0x1 << 10);
  47.         printk("点亮 LED1\n");
  48.     } else if (strcmp(kbuf, "2") == 0) {  // 点亮 LED2
  49.         *led2_vir_odr |= (0x1 << 10);
  50.         printk("点亮 LED2\n");
  51.     } else if (strcmp(kbuf, "3") == 0) {  // 点亮 LED3
  52.         *led3_vir_odr |= (0x1 << 8);
  53.         printk("点亮 LED3\n");
  54.     } else if (strcmp(kbuf, "0") == 0) {  // 全部熄灭
  55.         *led1_vir_odr &= ~(0x1 << 10);
  56.         *led2_vir_odr &= ~(0x1 << 10);
  57.         *led3_vir_odr &= ~(0x1 << 8);
  58.         printk("全部熄灭\n\n");
  59.     }
  60.     return 0;
  61. }
  62. int myled_close(struct inode *inode, struct file *file) {
  63.     printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  64.     return 0;
  65. }
  66. // 定义一个操作方法结构体变量
  67. struct file_operations fops = {
  68.    .open = myled_open,
  69.    .read = myled_read,
  70.    .write = myled_write,
  71.    .release = myled_close,
  72. };
  73. static int __init mycdev_init(void) {
  74.     // 进行字符设备驱动的注册
  75.     major = register_chrdev(0, "myled", &fops);
  76.     if (major < 0) {
  77.         printk("字符设备驱动注册失败\n");
  78.         return major;
  79.     }
  80.     printk("字符设备驱动注册成功 major=%d\n", major);
  81.     // 进行 LED1 寄存器的地址映射
  82.     led1_vir_moder = ioremap(LED1_PHY_GPIO_MODER, 4);
  83.     if (led1_vir_moder == NULL) {
  84.         printk("LED1 物理内存映射失败%d\n", __LINE__);
  85.         return -ENOMEM;
  86.     }
  87.     led1_vir_odr = ioremap(LED1_PHY_GPIO_ODR, 4);
  88.     if (led1_vir_odr == NULL) {
  89.         printk("LED1 物理内存映射失败%d\n", __LINE__);
  90.         iounmap(led1_vir_moder);
  91.         return -ENOMEM;
  92.     }
  93.     led1_vir_rcc = ioremap(LED1_PHY_RCC_GPIO, 4);
  94.     if (led1_vir_rcc == NULL) {
  95.         printk("LED1 物理内存映射失败%d\n", __LINE__);
  96.         iounmap(led1_vir_moder);
  97.         iounmap(led1_vir_odr);
  98.         return -ENOMEM;
  99.     }
  100.     // 进行 LED2 寄存器的地址映射
  101.     led2_vir_moder = ioremap(LED2_PHY_GPIO_MODER, 4);
  102.     if (led2_vir_moder == NULL) {
  103.         printk("LED2 物理内存映射失败%d\n", __LINE__);
  104.         iounmap(led1_vir_moder);
  105.         iounmap(led1_vir_odr);
  106.         iounmap(led1_vir_rcc);
  107.         return -ENOMEM;
  108.     }
  109.     led2_vir_odr = ioremap(LED2_PHY_GPIO_ODR, 4);
  110.     if (led2_vir_odr == NULL) {
  111.         printk("LED2 物理内存映射失败%d\n", __LINE__);
  112.         iounmap(led1_vir_moder);
  113.         iounmap(led1_vir_odr);
  114.         iounmap(led1_vir_rcc);
  115.         iounmap(led2_vir_moder);
  116.         return -ENOMEM;
  117.     }
  118.     led2_vir_rcc = ioremap(LED2_PHY_RCC_GPIO, 4);
  119.     if (led2_vir_rcc == NULL) {
  120.         printk("LED2 物理内存映射失败%d\n", __LINE__);
  121.         iounmap(led1_vir_moder);
  122.         iounmap(led1_vir_odr);
  123.         iounmap(led1_vir_rcc);
  124.         iounmap(led2_vir_moder);
  125.         iounmap(led2_vir_odr);
  126.         return -ENOMEM;
  127.     }
  128.     // 进行 LED3 寄存器的地址映射
  129.     led3_vir_moder = ioremap(LED3_PHY_GPIO_MODER, 4);
  130.     if (led3_vir_moder == NULL) {
  131.         printk("LED3 物理内存映射失败%d\n", __LINE__);
  132.         iounmap(led1_vir_moder);
  133.         iounmap(led1_vir_odr);
  134.         iounmap(led1_vir_rcc);
  135.         iounmap(led2_vir_moder);
  136.         iounmap(led2_vir_odr);
  137.         iounmap(led2_vir_rcc);
  138.         return -ENOMEM;
  139.     }
  140.     led3_vir_odr = ioremap(LED3_PHY_GPIO_ODR, 4);
  141.     if (led3_vir_odr == NULL) {
  142.         printk("LED3 物理内存映射失败%d\n", __LINE__);
  143.         iounmap(led1_vir_moder);
  144.         iounmap(led1_vir_odr);
  145.         iounmap(led1_vir_rcc);
  146.         iounmap(led2_vir_moder);
  147.         iounmap(led2_vir_odr);
  148.         iounmap(led2_vir_rcc);
  149.         iounmap(led3_vir_moder);
  150.         return -ENOMEM;
  151.     }
  152.     led3_vir_rcc = ioremap(LED3_PHY_RCC_GPIO,4);
  153.     if (led3_vir_rcc == NULL) {
  154.         printk("LED3 物理内存映射失败%d\n", __LINE__);
  155.         iounmap(led1_vir_moder);
  156.         iounmap(led1_vir_odr);
  157.         iounmap(led1_vir_rcc);
  158.         iounmap(led2_vir_moder);
  159.         iounmap(led2_vir_odr);
  160.         iounmap(led2_vir_rcc);
  161.         iounmap(led3_vir_moder);
  162.         iounmap(led3_vir_odr);
  163.         return -ENOMEM;
  164.     }
  165.     printk("物理内存映射成功\n");
  166.     //PE10设置为输出
  167.     (*led1_vir_moder) &= (~(0X3<<20));
  168.     (*led1_vir_moder) |= (0x1<<20);
  169.     //让PE10默认输出低电平
  170.     (*led1_vir_odr) &= (~(0X1<<10));
  171.     //PF10设置为输出
  172.     (*led2_vir_moder) &= (~(0X3<<20));
  173.     (*led2_vir_moder) |= (0x1<<20);
  174.     //让PF10默认输出低电平
  175.     (*led2_vir_odr) &= (~(0X1<<10));
  176.     //PE8设置为输出
  177.     (*led3_vir_moder) &= (~(0X3<<16));
  178.     (*led3_vir_moder) |= (0x1<<16);
  179.     //让PE8默认输出低电平
  180.     (*led3_vir_odr) &= (~(0X1<<8));
  181.    
  182.     return 0;
  183. }
  184. static void __exit mycdev_exit(void)
  185. {
  186.     //取消物理内存的映射
  187.     iounmap(led1_vir_moder);
  188.     iounmap(led1_vir_odr);
  189.     iounmap(led1_vir_rcc);
  190.     iounmap(led2_vir_moder);
  191.     iounmap(led2_vir_odr);
  192.     iounmap(led2_vir_rcc);
  193.     iounmap(led3_vir_moder);
  194.     iounmap(led3_vir_odr);
  195.     iounmap(led3_vir_rcc);
  196.     //进行字符设备驱动的注销
  197.     unregister_chrdev(major,"myled");
  198. }
  199. module_init(mycdev_init);
  200. module_exit(mycdev_exit);
  201. MODULE_LICENSE("GPL");
复制代码
app.c
  1. #include <stdio.h>
  2. #include <stdlib.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.     int fd = open("/dev/myLed", O_RDWR);
  11.     if (fd < 0) {
  12.         printf("设备文件打开失败\n");
  13.         return -1;
  14.     }
  15.     char cmd[2] = {0}; // 优化缓冲区大小
  16.    
  17.     while(1) {
  18.         // LED1亮
  19.         cmd[0] = '1';
  20.         if(write(fd, cmd, sizeof(cmd)) < 0) {
  21.             perror("write error");
  22.             break;
  23.         }
  24.         sleep(1); // 延时1秒
  25.         
  26.         // LED2亮(保持LED1亮)
  27.         cmd[0] = '2';
  28.         write(fd, cmd, sizeof(cmd));
  29.         sleep(1);
  30.         
  31.         // LED3亮(保持前两盏亮)
  32.         cmd[0] = '3';
  33.         write(fd, cmd, sizeof(cmd));
  34.         sleep(1);
  35.         
  36.         // 全部熄灭
  37.         cmd[0] = '0';
  38.         write(fd, cmd, sizeof(cmd));
  39.         sleep(1); // 全灭保持1秒
  40.     }
  41.     close(fd);
  42.     return 0;
  43. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

用户国营

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表