需求: 让PWM蜂鸣器响起来
注意事项:无源、需要有源、PWM方式和普通IO高低电平方式
看原理图:
1)原理:MOTOR_PWM 持续 输出 高低变化的电平,产生震动,从而发出声音
2)两个控制器:MOTOR_PWM ---》GPD0_0 ---》XpwmTOUT0(GPIO控制器,将IO脚转换成功能脚) |-----------------》PWM蜂鸣器控制器
蜂鸣器模块选择:timer 0 8位预分频器,2,4,8,16分割
寄存器:TCNTBn(159)->TOUTn(低位) TCMPBn(109)->TOUTn(高) 更新计数 0-》中断请求
自动加载TCNTBn,进入下一次循环 TCNTB0
两种模式:自动加载(连续脉冲) 一次加载(一次脉冲) 根据编程的占空比和极性
中断产生:
TCNTBn = 3 and TCMPBn = 1
auto-reload = 1 and manual update = 1
TCNTBn = 2 and TCMPBn = 0
auto-reload = 1 and manual update = 0
start = 1 for starting
TCNTn is down counting
Auto-reload是一个拷贝函数,当TCNTn达到0时,将TCNTBn的值拷贝到TCNTn中。
写入TCNTBn的值,如果TCNTn达到O且启用了自动重新加载,则加载到TCNTn。
如果TCNTn为O,自动加载位为O,则TCNTn不再运行。
TCNTBn -> TCNTn
寄存器初筛:
TCFG0 0x139D0000
TCFG1 0x139D0004 Divider MUX4 [19:16] 0100 = 1/16
TCON 0x139D0008
Timer 0 auto reload on/off [3] 1
Timer 0 start/stop [2] 1
Timer 0 manual update [1] 1
Timer 0 start/stop [0] 1
Dead zone enable/disable [4] Enables/Disables
TCNTB0 0x139D000C count buffer [31:0] Count
TCMPB0 0x139D0010 count observation [31:0] Observation
Makefile:
all: arm-linux-gcc myadd.S -o start.o -c -g arm-linux-gcc main.c -o main.o -c -g arm-linux-ld start.o main.o -o start.elf -Ttest.lds arm-linux-objcopy start.elf start.bin -O binary clean: rm *.o *.elf *.bin
main.c:
//GPIO控制器转换专用脚 #define GPD0CON *(unsigned int volatile*)0x114000A0 //PWM蜂鸣器的控制器 #define TCON *(unsigned int volatile*)0x139D0008 //第一个分频寄存器 #define TCFG0 *(unsigned int volatile*)0x139D0000 //第二个分频寄存器 #define TCFG1 *(unsigned int volatile*)0x139D0004 //timer 0 的count buffer #define TCNTB0 *(unsigned int volatile*)0x139D000C //timer 0 的 compare buffer register #define TCMPB0 *(unsigned int volatile*)0x139D0010 //自定义睡眠函数 void delay(){ int t = 0xfffff*3; while(t--); } void pwd_init() { //GPIO控制器转换专用脚 GPD0CON = GPD0CON & ~0xf | 0x2; //PWM0_clk = pclk/(255+1)/4 //随意分频,只需要人耳能听见即可,20HZ-2WHZ TCFG0 = TCFG0 | 0xff;//255分频、随便分频便可 TCFG1 = TCFG1 & ~0xf | 0x2;//4分频(先清再或) TCNTB0 = 300;//TCNTB0初始值、随便设置的 TCMPB0 = 150;//翻转值、到达这个值后便换转、TCNTB0的一半为最佳 //蜂鸣器的关闭与开启 //加载分为自动加载和手动加载 //0x1<<3 自动加载 //0x1<<1 由于是第一次,需要手动加载 //~(0x1<<0) 手动加载时关闭蜂鸣器 TCON = TCON | 0x1<<3 | 0x1<<1 & ~(0x1<<0); //将手动加载更改为自动加载 TCON = TCON & ~(0x1<<1); } //打开蜂鸣器 void pwm_on(){ TCON = TCON | 0x1; } //关闭蜂鸣器 void pwm_off(){ TCON = TCON & ~0x1; } void main() { pwd_init(); while(1) { pwm_on(); delay(); pwm_off(); delay(); } }
myadd.S、test.lds:ARM之串口的收发_承诺$枷锁的博客-CSDN博客