当前位置: 首页> 房产> 建筑 > seo关键词优化软件合作_工业外观设计_广州网站营销seo_软文范例100例

seo关键词优化软件合作_工业外观设计_广州网站营销seo_软文范例100例

时间:2025/7/15 11:32:53来源:https://blog.csdn.net/m0_51830537/article/details/142848187 浏览次数:0次
seo关键词优化软件合作_工业外观设计_广州网站营销seo_软文范例100例

定时器与PWM波

  1. 晶振的作用
  • 晶振(Crystal Oscillator)用于提供一个稳定的时钟信号,帮助处理器和其他硬件设备衡量时间流逝。晶振的频率决定了时钟信号的速率。例如,8 MHz 的晶振每秒产生 8,000,000 次振荡。这些振荡信号用于驱动处理器的内部时钟和定时器模块。
  1. 定时器的工作原理
  • 定时器计数:定时器会通过每次时钟信号来递增或递减计数器(TCNT)。当计数器达到设定的周期(TCNTB),就会发出一个中断信号。定时器的工作周期取决于分频器的值以及晶振的频率。
  • 分频器:分频器用于将时钟信号的频率进行缩减,比如从 64 MHz 缩减到 1 KHz,最终生成一个 1 ms 的时钟周期,用于定时器计数。
  • 定时周期:定时器会从 0 计数到设定的周期值,然后触发中断。当定时器达到设定的周期值时,计数器重置并开始新一轮计数。
  1. 定时器与 PWM 结合
  • PWM(Pulse Width Modulation) 是一种常用于调节设备(如灯光、马达)输出强度的技术,利用定时器生成脉冲波,控制输出信号的占空比。
  • PWM 的基本原理:通过改变脉冲的占空比,可以调节输出信号的强弱。占空比是指信号为高电平的时间与总周期的比值。
  • PWM 的工作过程:
    • 设定两个值:周期(TCNTB)和比较值(TCMPB)。
    • 当定时器计数器的值达到周期值时,计数器重置并开始新一轮计数;当计数器值达到比较值时,输出电平改变。
    • 通过修改比较值 TCMPB 与周期值 TCNTB 之间的关系,可以改变 PWM 波形的占空比。
控制蜂鸣器产生音乐流程
  1. 初始化GPIO为PWM输出

    GPD0CON &= ~0xF;    // 清除 GPD0_0 的配置位
    GPD0CON |= 1<<1;    // 将 GPD0_0 配置为 PWM 输出(TOUT_0)
    
    • GPD0CON:用于控制 GPD0_0 管脚的功能,通过设置 0x2,将其配置为 PWM 输出模式。
  2. PWM定时器配置

    TCFG0 &= ~0xFF;     // 清除 TCFG0 的前8位
    TCFG0 |= 124;       // 设置预分频器为 124
    TCFG1 &= ~0xF;      // 清除 TCFG1 的前4位
    TCFG1 |= 3;         // 设置分频器为 1/8
    TCNTB0 = 100;       // 设置定时器周期寄存器的初始值为 100
    TCMPB0 = 30;        // 设置比较寄存器的值为 30
    
    • TCFG0 和 TCFG1:分别用于设置预分频和分频器。预分频器设置为 124,分频器设置为 1/8。
    • TCNTB0 和 TCMPB0:这两个寄存器用于设定 PWM 波形的周期和占空比。周期寄存器(TCNTB0)决定 PWM 信号的周期,而比较寄存器(TCMPB0)决定高电平时间的长短,从而控制占空比。
  3. 控制 PWM 定时器

    • 定时器初始化
    TCON |= 1<<3;       // 设置定时器为自动重载模式
    TCON &= ~(1<<2);    // 设置不翻转电平
    TCON |= 1<<1;       // 更新 TCNTB 和 TCMPB 到 TCNT 和 TCMP
    TCON &= ~(1<<1);    // 清除更新位
    • 定时器的启动与停止
    TCON |= 1<<0;       // 启动定时器
    TCON &= ~(1<<0);    // 停止定时器
    
    • TCON:用于控制定时器的状态(启动、停止、更新、翻转等)。当设置 TCON 的第 1 位时,定时器会更新 TCNT 和 TCMP 的值,并且立即清除此位以确保正确更新。
  4. 蜂鸣器频率控制

    char yf[] = {0,191,170,152,143,128,114,101};  // 不同频率对应的 PWM 周期值
    
    • yf 数组:存储了蜂鸣器不同音调对应的 PWM 周期值。程序通过循环修改定时器的周期值和占空比,产生不同频率的 PWM 信号,控制蜂鸣器发出不同频率的声音。
  5. 延时函数

    void mdelay(int msec)
    {while(msec--){int cnt = 0x1fff/3;while(cnt--);}
    }
    
    • mdelay():用于产生延时,通过空循环实现。在不同频率的声音之间加入延时,以便让声音可以持续一段时间。
  6. 主函数逻辑

    int main()
    {timer_init();   // 初始化定时器while(1){int i;timer_start();  // 启动定时器for(i = 1; i <= 7; i++){TCNTB0 = yf[i];        // 修改 PWM 周期TCMPB0 = yf[i] / 2;    // 修改 PWM 占空比mdelay(500);           // 等待 500ms,保持蜂鸣器声音}timer_stop();   // 停止定时器mdelay(2 * 1000);  // 停止后等待 2 秒}return 0;
    }
    
    • 调用 timer_init() 初始化定时器。
    • 进入主循环,通过循环设置不同的 PWM 周期和占空比(从 yf 数组中取值)。
    • 使用 timer_start() 启动定时器,蜂鸣器开始发声。
    • 改变 PWM 的周期值和占空比,产生不同的音调。
    • 延时 500 毫秒后,停止定时器并延时 2 秒,再重新开始新的音调。
  7. 整体代码如下

//控制 PWM 定时器 来调节蜂鸣器的频率,使其发出不同的音调
#define	GPD0CON    	*(volatile long*)0x114000A0    // GPD0CON 寄存器的地址,用于配置 GPD0_0 引脚为 PWM 输出模式
#define	TCFG0		*(volatile long*)0x139D0000    // TCFG0 寄存器的地址,用于设置 PWM 定时器的预分频值
#define	TCFG1		*(volatile long*)0x139D0004	  // TCFG1 寄存器的地址,用于设置 PWM 定时器的分频值
#define	TCON		*(volatile long*)0x139D0008	  // TCON 寄存器的地址,用于控制定时器的启动、停止等操作
#define	TCNTB0		*(volatile long*)0x139D000C	  // TCNTB0 寄存器的地址,用于设置定时器的周期(PWM 周期)
#define	TCMPB0		*(volatile long*)0x139D0010	  // TCMPB0 寄存器的地址,用于设置 PWM 占空比void do_irq(void)
{// 中断服务函数,在该代码中并没有实际使用,可以用来处理定时器的中断事件。
}void timer_init(void)
{GPD0CON &= ~0xF;                // 清除 GPD0_0 的配置位,确保只修改低 4 位GPD0CON |= 1<<1;                // 将 GPD0_0 引脚配置为 TOUT_0(PWM 输出模式)TCFG0 &= ~0xFF;                 // 清除 TCFG0 的前 8 位,确保只修改预分频值TCFG0 |= 124;                   // 设置预分频器值为 124,降低定时器输入时钟频率TCFG1 &= ~0xF;                  // 清除 TCFG1 的前 4 位,确保只修改分频值TCFG1 |= 3;                     // 设置分频器为 1/8TCNTB0 = 100;                   // 设置定时器周期寄存器 TCNTB0 的值为 100,这定义了 PWM 信号的总周期TCMPB0 = 30;                    // 设置比较寄存器 TCMPB0 的值为 30,定义占空比,即高电平时间为总周期的 30%TCON |= 1<<3;                   // 设置 TCON 的第 3 位,启用自动重载模式(PWM 波形在到达周期后自动重载)TCON &= ~(1<<2);                // 清除 TCON 的第 2 位,设置为不翻转电平TCON |= 1<<1;                   // 设置 TCON 的第 1 位,将 TCNTB 和 TCMPB 的值更新到 TCNT 和 TCMPTCON &= ~(1<<1);                // 清除 TCON 的第 1 位,确保更新操作完成后立即清零,以防止重复更新
}void timer_start(void)
{TCON |= 1<<0;                   // 设置 TCON 的第 0 位,启动定时器
}void timer_stop(void)
{TCON &=  ~(1<<0);               // 清除 TCON 的第 0 位,停止定时器
}char yf[] = {0,191,170,152,143,128,114,101};  // 预定义的周期值数组,控制蜂鸣器发出不同频率的声音。每个值代表不同的 PWM 周期void mdelay(int msec)
{while(msec--){                  // 循环 msec 次,产生延时int cnt = 0x1fff/3;          // 内部计数器,控制更短时间的延时while(cnt--);                // 空循环实现短时间的延时}
}int main()
{timer_init();                   // 调用定时器初始化函数,设置 PWM 输出while(1){                       // 主循环,持续输出不同频率的声音int i;timer_start();               // 启动定时器,开始输出 PWM 信号for(i = 1; i <= 7; i++){     // 循环遍历 yf 数组中的频率值,从索引 1 到 7TCNTB0 = yf[i];          // 修改定时器的周期寄存器 TCNTB0,设置不同的 PWM 周期TCMPB0 = yf[i] / 2;      // 修改比较寄存器 TCMPB0,设置占空比为周期的一半mdelay(500);             // 等待 500 毫秒,保持当前频率的声音}timer_stop();                // 停止定时器,停止 PWM 信号输出mdelay(2 * 1000);            // 等待 2 秒,然后再次开始新的声音周期}return 0;
}
补充文件
  1. start.S
.global  delay1s          @ 定义全局符号 delay1s,表示延迟函数的入口点
.text                     @ 表示代码段的开始
.global _start            @ 定义全局符号 _start,程序的入口点_start:b		reset                  @ 0x00处的指令,直接跳转到 reset,程序复位时从 reset 开始nop                          @ 0x04 处的空操作,占位符,用于延迟nop                          @ 0x08 处的空操作nop                          @ 0x0C 处的空操作nop                          @ 0x10 处的空操作nop                          @ 0x14 处的空操作ldr 	pc,_irq               @ 0x18 处加载_irq的地址到程序计数器 PC,用于处理中断nop                          @ 0x1C 处的空操作_irq:					.word  irq_handler       @ 定义 _irq 的地址,即中断发生时,跳转到 irq_handler 处理@.word 0x12345678        @ 可选的字数据,用于测试或调试irq_handler:		        @ 中断处理程序的入口sub  lr, lr, #4         @ 调整 LR 寄存器,LR 是中断返回地址,需要减去 4 才能指向中断发生前的指令stmfd  sp!, {r0-r12, lr} @ 将通用寄存器 r0-r12 和链接寄存器 lr 压入栈中,保存现场bl   do_irq             @ 调用 C 函数 do_irq 进行中断处理ldmfd  sp!, {r0-r12, pc}^ @ 从栈中恢复 r0-r12 和 PC 寄存器的值,恢复现场,并返回到中断发生前的位置reset: ldr	r0, =0x40008000       @ 设置异常向量表的起始地址为 0x40008000mcr	p15, 0, r0, c12, c0, 0 @ 将 r0 的值写入 CP15 协处理器的 Vector Base Address Register (VBAR),以设定向量表的地址ldr		r0, =stacktop          @ 获取栈顶地址,stacktop 是一个定义好的符号,r0 中保存栈顶指针/******** svc 模式栈 ********/mov		sp, r0               @ 将栈顶指针装载到 SP 中,切换到 svc 模式sub		r0, #128*4            @ 为 irq 模式保留 512 字节的栈空间/**** irq 模式栈 ***/msr		cpsr, #0xd2           @ 切换到 irq 模式mov		sp, r0               @ 设置 irq 模式的栈指针sub		r0, #128*4            @ 为 irq 模式保留 512 字节的栈空间/*** fiq 模式栈 ***/msr 	cpsr, #0xd1           @ 切换到 fiq 模式mov		sp, r0               @ 设置 fiq 模式的栈指针sub		r0, #0                @ 为 fiq 模式保留 0 字节的栈空间/*** abort 模式栈 ***/msr		cpsr, #0xd7           @ 切换到 abort 模式mov		sp, r0               @ 设置 abort 模式的栈指针sub		r0, #0                @ 为 abort 模式保留 0 字节的栈空间/*** undefined 模式栈 ***/msr		cpsr, #0xdb           @ 切换到 undefined 模式mov		sp, r0               @ 设置 undefined 模式的栈指针sub		r0, #0                @ 为 undefined 模式保留 0 字节的栈空间/*** sys 模式和 usr 模式栈 ***/msr		cpsr, #0x10           @ 切换到 sys/usermode 模式mov		sp, r0               @ 设置 user 模式的栈指针,预留 1024 字节空间b		main                 @ 跳转到 main 函数,开始执行主程序.align	4                      @ 保证对齐到 4 字节边界,优化存储器访问.datastack:	.space  4*512               @ 为所有模式分配 512 字节栈空间
stacktop:.end                           @ 程序结束
  1. map.lds
  2. Makefile
all:arm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o start.o start.Sarm-none-linux-gnueabi-gcc -fno-builtin -nostdinc -c -o main.o main.carm-none-linux-gnueabi-ld start.o main.o -Tmap.lds -o main.elfarm-none-linux-gnueabi-objcopy -O binary  main.elf main.binarm-none-linux-gnueabi-objdump -D main.elf > main.dis
clean:rm -rf *.bak *.o  *.elf  *.bin  *.dis
利用Makefile产生的bin烧录进入开发板即可
关键字:seo关键词优化软件合作_工业外观设计_广州网站营销seo_软文范例100例

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: