上次,我们写了一个LED的驱动程序,这一节,我们只需稍微改动一下就可以实现蜂鸣器的驱动,让我们来看看吧。

     还是跟之前一样,先找电路图,找到电路板上对应的引脚和相关联的寄存器。

     1、看电路图

     (1)蜂鸣器接口位于电路板的底板,看电路图可知道是高电平有效。

 

   (2)相对应的找到核心板的接口。由此可知,我们的蜂鸣器是GPD0_0

 

接下来找数据手册,嵌入式物联网等系统学习企鹅意义气呜呜吧久零就易,找到对应的寄存器,然后配置它就可以了。

  2、查数据手册,找到相关的寄存器,并配置

(1)找到GPD0CON,地址是0x114000A0,我们需要配置GPD0CON(0)为输出状态。也就是写0x1这个值到这个寄存器。

 

 

(2)找到GPD0DAT这个寄存器,用于配置蜂鸣器的高低电平,物理地址是0x114000A4,刚好与上一个差4个字节的偏移

我们只要对这个寄存器写1和写0,那么蜂鸣器就可以叫起来了,哈哈。是不是很简单?

 

3、开始写驱动程序。

 

[plain] view plain copy print?

1. 

#include <linux/init.h>  

2. 

3. 

#include <linux/module.h>  

4. 

5. 

#include <linux/kernel.h>  

6. 

7. 

#include <linux/fs.h>  

8. 

9. 

#include <linux/io.h>  

10. 

11. 

#include <asm/uaccess.h>  

12. 

13. 

#include <asm/irq.h>  

14. 

15. 

#include <asm/io.h>  

16. 

17. 

#define DEV_NAME    "test-dev"  

18. 

19. 

//定义蜂鸣器配置IO的地址   

20. 

21. 

#define GPD0CON  0x114000A0  

22. 

23. 

volatile unsigned long *bell_config = NULL ;   

24. 

25. 

volatile unsigned long *bell_dat = NULL ;   

26. 

27. 

int bell_open(struct inode *inode, struct file *filp)  

28. 

29. 

{  

30. 

31. 

    printk("bell_open\n");  

32. 

33. 

    //清寄存器   

34. 

35. 

    *bell_config &= ~(0xf);  

36. 

37. 

    //设置io为输出   

38. 

39. 

    *bell_config |= (0x1);  

40. 

41. 

    return 0;  

42. 

43. 

}  

44. 

45. 

  

46. 

47. 

int bell_close(struct inode *inode, struct file *filp)  

48. 

49. 

{  

50. 

51. 

    printk("bell_close\n");  

52. 

53. 

    //关闭蜂鸣器   

54. 

55. 

    *bell_dat &= ~0x1 ;  

56. 

57. 

    return 0;  

58. 

59. 

}  

60. 

61. 

  

62. 

63. 

long bell_ioctl(struct file *filp, unsigned int request, unsigned long arg)  

64. 

65. 

{  

66. 

67. 

    //控制蜂鸣器的状态   

68. 

69. 

    switch(request)  

70. 

71. 

    {  

72. 

73. 

        case 0:  

74. 

75. 

            printk(KERN_EMERG"bell on\n");  

76. 

77. 

            *bell_dat |= 0x1 ;  

78. 

79. 

            break;  

80. 

81. 

  

82. 

83. 

        case 1:  

84. 

85. 

            printk(KERN_EMERG"bell off\n");  

86. 

87. 

            *bell_dat &=~0x1 ;  

88. 

89. 

            break;  

90. 

91. 

    }  

92. 

93. 

    return 0 ;  

94. 

95. 

}  

96. 

97. 

  

98. 

99. 

struct file_operations fops = {  

100. 

101. 

    .owner = THIS_MODULE ,  

102. 

103. 

    .open = bell_open,  

104. 

105. 

    .release = bell_close,  

106. 

107. 

    .unlocked_ioctl = bell_ioctl,  

108. 

109. 

};  

110. 

111. 

  

112. 

113. 

int major ;  

114. 

115. 

int test_init(void)  

116. 

117. 

{  

118. 

119. 

    printk("bell_init\n");  

120. 

121. 

    //注册设备   

122. 

123. 

    major = register_chrdev(major, DEV_NAME, &fops);  

124. 

125. 

    //映射IO   

126. 

127. 

    bell_config = (volatile unsigned long *)ioremap(GPD0CON , 16);  

128. 

129. 

    //加4个字节偏移到GP0DAT顺便映射该物理地址   

130. 

131. 

    bell_dat = bell_config + 1 ;      

132. 

133. 

    return 0;  

134. 

135. 

}  

136. 

137. 

  

138. 

139. 

void test_exit(void)  

140. 

141. 

{  

142. 

143. 

    printk("bell_exit\n");  

144. 

145. 

    //解除注册   

146. 

147. 

    unregister_chrdev(major, DEV_NAME);  

148. 

149. 

    //取消映射   

150. 

151. 

    iounmap(bell_config);  

152. 

153. 

}  

154. 

155. 

  

156. 

157. 

module_init(test_init);  

158. 

159. 

module_exit(test_exit);  

160. 

161. 

  

162. 

163. 

MODULE_LICENSE("GPL");  

164. 

165. 

MODULE_AUTHOR("Y.X.YANG");  

166. 

167. 

MODULE_VERSION("2016.1.16");</span>  

168. 

4、写测试程序

[plain] view plain copy print?

1. 

#include <stdio.h>  

2. 

3. 

#include <sys/types.h>  

4. 

5. 

#include <sys/stat.h>  

6. 

7. 

#include <fcntl.h>  

8. 

9. 

  

10. 

11. 

int main(int argc, char **argv)  

12. 

13. 

{  

14. 

15. 

    int fd;  

16. 

17. 

    //打开设备   

18. 

19. 

    fd = open("/dev/test-dev",O_RDWR) ;  

20. 

21. 

    if(-1 == fd)  

22. 

23. 

    {  

24. 

25. 

        printf("open fair!\n");  

26. 

27. 

        return -1 ;  

28. 

29. 

    }  

30. 

31. 

    while(1){  

32. 

33. 

        //打开蜂鸣器   

34. 

35. 

        ioctl(fd,1);  

36. 

37. 

        sleep(1);  

38. 

39. 

        //关闭蜂鸣器   

40. 

41. 

        ioctl(fd,0);  

42. 

43. 

        sleep(1);  

44. 

45. 

    }  

46. 

47. 

    return 0;  

48. 

49. 

}</span>  

50. 

5、编写makefile

[plain] view plain copy print?

1. 

obj-m   += bell.o  

2. 

3. 

  

4. 

5. 

ROOTFS = /disk/A9/filesystem  

6. 

7. 

KERNEL = /disk/A9/linux-3.5/  

8. 

9. 

all:  

10. 

11. 

    make -C $(KERNEL) M=`pwd` modules  

12. 

13. 

  

14. 

15. 

clean:  

16. 

17. 

    make -C $(KERNEL) M=`pwd` clean  

18. 

19. 

    rm -rf my_bell  

20. 

21. 

  

22. 

23. 

install:  

24. 

25. 

    make -C $(KERNEL) M=`pwd` modules_install INSTALL_MOD_PATH=$(ROOTFS)  

26. 

27. 

  

28. 

29. 

my_bell:  

30. 

31. 

    arm-linux-gcc my_bell.c -o my_bell  

32. 

33. 

</span>  

34.