嵌入式开发记录-day28 ioremap+PWM 驱动蜂鸣器
1、常见两种蜂鸣器
蜂鸣器发出声音是因为震动,震动需要频率,就是说需要晶振;震动的频率高低,发出高低的声音;
有源蜂鸣器:有源蜂鸣器通电就可以响,里面自带了晶振,就可以发出声音;
无源蜂鸣器:需要外部给一定频率的脉冲信号,占空比也可以调节;高低电平切换,控制震动与不震动;
2、查看原理图
GPD0_0--->MOTOR_PWM --->beep
pwm + ioremap() 控制
3、需要用的寄存器地址:
1、PWM的地址0x139D0000
GPD0CON地址0x11400000
4、pwm.c
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <mach/gpio.h> #include <plat/gpio-cfg.h> #include <linux/miscdevice.h> #include <linux/platform_device.h> //#include <mach/gpio-bank.h> #include <mach/regs-gpio.h> #include <asm/io.h> #include <linux/regulator/consumer.h> //#include "gps.h" #include <linux/delay.h> MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("TOPEET"); // PWM定时器相关的寄存器 struct { unsigned int TCFG0; unsigned int TCFG1; unsigned int TCON; unsigned int TCNTB0; unsigned int TCMPB0; unsigned int TCNTO0; unsigned int TCNTB1; unsigned int TCMPB1; unsigned int TCNTO1; unsigned int TCNTB2; unsigned int TCMPB2; unsigned int TCNTO2; unsigned int TCNTB3; unsigned int TCMPB3; unsigned int TCNTO3; unsigned int TCNTB4; unsigned int TCNTO4; unsigned int TINT_CSTAT; // 每个都是4字节 }*PWM; // 定义物理地址 虚拟地址 volatile unsigned long phys_addr,phys_GPD0_addr,virtl_addr,virtl_GPD0_addr; // 定义寄存器地址变量 volatile unsigned long *GPD0CON,*GPD0PUD; void addr_Init(void) { phys_addr = (unsigned long)0x139D0000; // PWM 基地址 virtl_addr = (unsigned long)ioremap(phys_addr,0x32); // 虚拟地址 PWM = (unsigned long*)(virtl_addr + 0x0); /* GPD0CON Base Address: 0x1140_0000 Address = Base Address + 0x00A0 GPD0PUD Base Address: 0x1140_0000 Address = Base Address + 0x00A8 */ phys_GPD0_addr = 0x11400000 + 0xA0; // 端口基地址 virtl_GPD0_addr = (unsigned long)ioremap(phys_GPD0_addr, 0x10); GPD0CON = (unsigned long*)(virtl_GPD0_addr + 0x00); // 控制寄存器地址 GPD0PUD = (unsigned long*)(virtl_GPD0_addr + 0x00A8-0x00A0); // 上下电位寄存器地址 } void beepOn(void) { //开启自动重载 0x1 = Starts Timer 0 // 1 = Interval mode (auto-reload) 开启自动自动加载 翻转 | 0x1 | 0x8; (*PWM).TCON = (((*PWM).TCON) & (~(0xf))) | 0x9; } // void beepOff(void) { // 关闭定时器0 (*PWM).TCON = ((*PWM).TCON & (~(0xf)) )| 0x0; //定时器结束之后,输出的是高电平还是低电平? // GPD0_0设置为输入 *GPD0CON = (*GPD0CON&(~(0xf)))|0x0; } void pwmdev_Init(void) { addr_Init(); // 配置GPD0_0为定时器输出 0x2 = TOUT_0 *GPD0CON = (*GPD0CON & (~(0xf)) )| 0x2; // 上下拉输出 0x0 = Disables Pull-up/Pull-down *GPD0PUD = *GPD0PUD & (~(0xf)); //失能上下拉 // 设置预分频 0x1111 1001 249 (*PWM).TCFG0 = ((*PWM).TCFG0 &(~(0xff)))|0xf9; //分频1.2.4.8.16 (*PWM).TCFG1 = ((*PWM).TCFG1 &(~(0xf)))|0x2; //设置占空比 (*PWM).TCMPB0 = 50; (*PWM).TCNTB0 = 100; //设置手动加载,开启定时器 | 0x1 | 0x2; (*PWM).TCON = ((*PWM).TCON & (~(0xf)) )| 0x3; } int pwm_init(void) { pwmdev_Init(); beepOn(); return 0; } void pwm_exit(void) { beepOff(); } module_init(pwm_init); module_exit(pwm_exit);
5、编译后加载模块蜂鸣器响,卸载后蜂鸣器关闭

浙公网安备 33010602011771号