• [模块化编写驱动控制LED灯]


    arm知识-----芯片手册

    根据引脚PE10,PF0,PE8,搜索寄存器地址

     RCC_AHB4使能以及AHB4总线作用

     

     

     内核3-4G代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include "myled.h"
    7. #define CNAME "myled"
    8. //主设备号
    9. int major;
    10. char kbuf[128]={0};
    11. //LED1--PE10
    12. //LED2--PF10
    13. //LED3--PE8
    14. gpio_t *vir_led1_3;
    15. gpio_t *vir_led2;
    16. volatile unsigned int *vir_rcc;
    17. int leds_init()
    18. {
    19. //将led的物理地址PHY做映射到vir虚拟空间
    20. //1个寄存器地址是32位,用4字节存放;映射后可以直接使用
    21. vir_rcc=ioremap(PHY_RCC,4);
    22. if(vir_rcc==NULL)
    23. {
    24. printk("vir_rcc faild\n");
    25. return -ENOMEM;
    26. }
    27. vir_led1_3=ioremap(0x50006000,sizeof(gpio_t));
    28. if(vir_led1_3==NULL)
    29. {
    30. printk("vir_led1_3 faild\n");
    31. return -ENOMEM;
    32. }
    33. vir_led2=ioremap(0x50007000,sizeof(gpio_t));
    34. if(vir_led2==NULL)
    35. {
    36. printk("vir_led2 faild\n");
    37. return -ENOMEM;
    38. }
    39. //LED1--PE10引脚初始化
    40. *vir_rcc |= (0x1<<4); //rcc使能
    41. vir_led1_3->MODER &=(~(0x3<<20));
    42. vir_led1_3->MODER |=(0x1<<20);//设置gpioe引脚输出模式
    43. //设置PE10引脚默认输出低电平
    44. vir_led1_3->ODR &= (~(0x1<<10));
    45. //LED2--PF10引脚初始化
    46. *vir_rcc |= (0x1<<5); //rcc使能
    47. vir_led2->MODER &=(~(0x3<<20));
    48. vir_led2->MODER |=(0x1<<20);//设置gpiof引脚输出模式
    49. //设置PF10引脚默认输出低电平
    50. vir_led2->ODR &= (~(0x1<<10));
    51. //LED3--PE8引脚初始化
    52. vir_led1_3->MODER &=(~(0x3<<16));
    53. vir_led1_3->MODER |=(0x1<<16);//设置gpioe引脚输出模式
    54. //设置PE8引脚默认输出低电平
    55. vir_led1_3->ODR &= (~(0x1<<16));
    56. return 0;
    57. }
    58. int mycdev_open(struct inode *inode, struct file *file)
    59. {
    60. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    61. return 0;
    62. }
    63. ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *loffs)
    64. {
    65. int ret;
    66. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    67. //校验传输数据大小
    68. if(size>sizeof(kbuf)) size = sizeof(kbuf);
    69. ret = copy_to_user(ubuf,kbuf,size);
    70. if(ret)
    71. {
    72. printk("copy from user is error\n");
    73. return -EIO;
    74. }
    75. return size;
    76. }
    77. ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *loffs)
    78. {
    79. int ret;
    80. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    81. if(size>sizeof(kbuf))
    82. size = sizeof(kbuf);
    83. ret=copy_from_user(kbuf,ubuf,size);
    84. if(ret)
    85. {
    86. printk("copy from user is error\n");
    87. return -EIO;
    88. }
    89. printk("copy from user kbuf=%s\n",kbuf);
    90. //连接应用层传参
    91. if(kbuf[0]=='1')
    92. {
    93. if(kbuf[1]=='1')
    94. {
    95. //led1输出高电平PE10
    96. vir_led1_3->ODR |= (0x1<<10);
    97. }
    98. else if(kbuf[1]=='0')
    99. {
    100. vir_led1_3->ODR &= (~(0x1<<10));
    101. }
    102. }else if(kbuf[0]=='2')
    103. {
    104. if(kbuf[1]=='1')
    105. {
    106. //led2输出高电平PF10
    107. vir_led2->ODR |= (0x1<<10);
    108. }
    109. else if(kbuf[1]=='0')
    110. {
    111. vir_led2->ODR &= (~(0x1<<10));
    112. }
    113. }else if(kbuf[0]=='3')
    114. {
    115. if(kbuf[1]=='1')
    116. {
    117. //led3输出高电平PE8
    118. vir_led1_3->ODR |= (0x1<<8);
    119. }
    120. else if(kbuf[1]=='0')
    121. {
    122. vir_led1_3->ODR &= (~(0x1<<8));
    123. }
    124. }
    125. return size;
    126. }
    127. int mycdev_close(struct inode *inode, struct file *file)
    128. {
    129. printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    130. return 0;
    131. }
    132. //结构体中存放函数指针,指向自己定义的函数
    133. const struct file_operations fops = {
    134. .open = mycdev_open,
    135. .read = mycdev_read,
    136. .write = mycdev_write,
    137. .release = mycdev_close,
    138. };
    139. //入口
    140. static int __init mycdev_init(void)
    141. {
    142. //1.注册字符设备驱动
    143. major = register_chrdev(0,CNAME,&fops);
    144. if(major < 0)
    145. {
    146. printk("register chrdev is error\n");
    147. return major;
    148. }
    149. printk("major=%d\n",major);
    150. leds_init();
    151. return 0;
    152. }
    153. //出口
    154. static void __exit mycdev_exit(void)
    155. {
    156. iounmap(vir_rcc);
    157. iounmap(vir_led1_3);
    158. iounmap(vir_led2);
    159. //2.注销字符设备驱动
    160. unregister_chrdev(major,CNAME);
    161. }
    162. module_init(mycdev_init);
    163. module_exit(mycdev_exit);
    164. //许可证
    165. MODULE_LICENSE("GPL");

     应用层0-3G代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. char buf[128] = {""};
    9. int main(int argc, char const *argv[])
    10. {
    11. int fd = -1;
    12. fd = open("/dev/myled",O_RDWR);
    13. if(-1 == fd)
    14. {
    15. perror("open is error");
    16. exit(1);
    17. }
    18. while(1)
    19. {
    20. //控制哪盏灯,1代表LED1
    21. buf[0]='1';
    22. write(fd,buf,sizeof(buf));
    23. //灯亮
    24. buf[1]='1';
    25. write(fd,buf,sizeof(buf));
    26. sleep(1);
    27. //灯灭
    28. buf[1]='0';
    29. write(fd,buf,sizeof(buf));
    30. sleep(1);
    31. //led2
    32. buf[0]='2';
    33. write(fd,buf,sizeof(buf));
    34. //灯亮
    35. buf[1]='1';
    36. write(fd,buf,sizeof(buf));
    37. sleep(1);
    38. //灯灭
    39. buf[1]='0';
    40. write(fd,buf,sizeof(buf));
    41. sleep(1);
    42. //led3
    43. buf[0]='3';
    44. write(fd,buf,sizeof(buf));
    45. //灯亮
    46. buf[1]='1';
    47. write(fd,buf,sizeof(buf));
    48. sleep(1);
    49. //灯灭
    50. buf[1]='0';
    51. write(fd,buf,sizeof(buf));
    52. sleep(1);
    53. }
    54. close(fd);
    55. return 0;
    56. }

     测试代码:

    1. #ifndef __LED_H__
    2. #define __LED_H__
    3. //LED1--PE10
    4. //LED2--PF10
    5. //LED3--PE8
    6. #define PHY_RCC 0x50000A28
    7. typedef struct{
    8. volatile unsigned int MODER;
    9. volatile unsigned int OTYPER;
    10. volatile unsigned int OSPEEDR;
    11. volatile unsigned int PUPDR;
    12. volatile unsigned int IDR;
    13. volatile unsigned int ODR;
    14. }gpio_t;
    15. #define PHY_GPIOE ((gpio_t*)0x50006000)
    16. #define PHY_GPIOF ((gpio_t*)0x50007000)
    17. int leds_init(void);
    18. #endif

    Makefile编写

    1. ARCH?=arm
    2. filename?=myled
    3. ifeq ($(ARCH),arm)
    4. KERNDIR:=/home/ubuntu/linux-5.10.61
    5. else
    6. KERNDIR:=/lib/modules/$(shell uname -r)/build //x86架构
    7. endif
    8. PWD:=$(shell pwd)
    9. all:
    10. make -C $(KERNDIR) M=$(PWD) modules
    11. clean:
    12. make -C $(KERNDIR) M=$(PWD) clean
    13. #模块化编译的类型
    14. obj-m:=$(filename).o

    实现效果:三盏灯开关控制

    对test.c和myled.c分别编译成arm架构

    myled.c编译:make ARCH=arm filename=myled

     串口内核启动成功,加载根文件系统,进入用户界面:

    安装驱动文件,并执行a.out可执行文件,结果显示如下:并且看到三盏灯亮灭的现象

  • 相关阅读:
    [附源码]java毕业设计医院挂号管理系统
    java mysql体检管理系统源码
    STM32 HAL库F103系列之ADC实验(三)
    LeetCode(算法)- 343. 整数拆分
    egrep扩展正则表达式
    FPGA 串口多字节发送,串口回环测试
    《深度学习在医学图像分析中的应用(第二版)》
    架构整洁之道摘录
    Go语言学习教程(十三)
    Android组件通信——广播机制:BroadcastReceiver(二十九)
  • 原文地址:https://blog.csdn.net/m0_68004652/article/details/127892621