ARM进阶 005_1 PWM定时器

article/2025/9/20 8:14:10

一、概述

       脉冲宽度调制 PWM(Pulse Width Modulation),简称脉宽调制。是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,将模拟信号转换为脉波,一般转换后脉波的周期固定,但脉波的占空比会依模拟信号的大小而改变。广泛应用在从测量、通信到功率控制与变换的许多领域中。

      简而言之,PWM是一种对模拟信号电平进行数字编码的方法。

      实质上是定时器的应用。

 

1、定时器的本质

   定时器的本质是计数器,计数器计的是一个均匀脉冲,即计数固定周期的脉冲(固定频率)  

2、定时器的应用   

    在某个时间,电平翻转,则可以获得一个脉冲,新的频率属性(周期T、脉宽比等)都是由定时器决定。通过这个新的频率,可以控制一些外设。

3PMW

   占空比:就是输出的PWM中,高电平保持的时间 与该PWM的时钟周期的时间之比,即

          脉宽比(占空比) = T(高电平)  /  时钟周期 (若为均匀脉冲,则脉宽比为50%。高电平时间越长,脉宽比越大)

4PMW的应用      

       它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用于测量,通信,功率控制与变换等许多领域。脉冲宽度调制(PWM)是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。

       实际上实现的是能量控制   
应用:调光灯,电机控制.....

 

二、PWM定时器

    1、基本概念

        S3C2440A 516 位定时器。其中定时器0123 具有脉宽调制(PWM)功能。定时器4是一个无输出引脚的内部定时器。定时器0还包含用于大电流驱动的死区发生器。

       定时器 01 共用一个8 位预分频器,定时器234 共用另外的8 位预分频器。每个定时器都有一个可以生成5种不同分频信号(1/21/41/81/16TCLK)的时钟分频器。每个定时器模块从相应8位预分频器得到时钟的时钟分频器中得到其自己的时钟信号。8位预分频器是可编程的,并且按存储在TCFG0TCFG1寄存器中的加载值来分频PCLK

       定时计数缓冲寄存器(TCNTBn包含了一个当使能了定时器时的被加载到递减计数器中的初始值。

       定时比较缓冲寄存器(TCMPBn包含了一个被加载到比较寄存器中的与递减计数器相比较的初始值。这种 TCNTBnTCMPBn的双缓冲特征保证了改变频率和占空比时定时器产生稳定的输出。TCMPBn的值是用于脉宽调制PWM)。当递减计数器的值与定时器控制逻辑中的比较寄存器的值相匹配时定时器控制逻辑改变输出电平。因此,比较寄存器决定PWM输出的开启时间(或关闭时间)。

       简言之,定时计数缓冲寄存器(TCNTBn)决定频率 定时比较缓冲寄存器(TCMPBn)决定周期(何时翻转电平)脉宽比由两者同时决定。

特性:
五个 16 位定时器
两个 8 位预分频器和两个 4 位分频器
可编程输出波形的占空比控制(PWM
自动重载模式或单稳脉冲模式
死区发生

  

   2PWM定时器操作    

           1)基本时序操作

                 

          2)自动重载和双缓冲       

                S3C2440A PWM 定时器包含双缓冲功能,允许在不停止当前定时器操作的情况下为下次定时器操作改变重载值。所以即使设置了新的定时器值,当前定时器操作仍然顺利的被完成。
                定时器值可以被写入到定时器计数缓冲寄存器(TCNTBn)中并且可以从定时器计数监视寄存器(TCNTOn)中读取当前定时器的计数值。如果读取TCNTBn,读出的值不是指示当前计数器的状态而是下次定时器持续时间的重载值。
                自动重载操作在 TCNTn到达0 时复制 TCNTBn TCNTn。写入到TCNTBn的该值,只有在TCNTn到达0并且使能了自动重载时才被加载到TCNTn。如果TCNTn变为0 并且自动重载位为0TCNTn不会进一步任何操作 

 

    实例:使用手动更新位和变相位初始化定时器
         当递减计数器到达 0时发生定时器的自动重载操作。所以必须预先由用户定义一个TCNTn的起始值。在这种情况下,必须通过手动更新位加载起始值。以下步骤描述了如何启动一个定时器:
    1) 初始值写入到 TCNTBnTCMPBn中。
    2) 设置相应定时器的手动更新位。推荐你配制变相开/关位。(无论是否使用变换极性)
    3) 设置相应定时器的开始位来启动定时器(并且清除手动更新位)。
         如果定时器被强制停止,TCNTn保持计数器值并且不会从TCNTBn重载。如果需要设置一个新值,执行手动更新。
  注意:
     无论何时 TOUT变相开/关位改变,是否定时器运行中都将改变TOUT逻辑值。因此,最好带手动更新位配制变相开/关位。


上述图显示了以下过程的结果:
1. 使能自动重载功能。设置 TCNTBn  16050+110)并且设置TCMPBn110。置位手动更新位并且配制变相位 (开/关)。 手动更新位分别设置TCNTnTCMPnTCNTBnTCMPBn的值中。 然后分别设置TCNTBnTCMPBn8040+40)和40,以决定下次重载值。
2. 设置启动位,预设手动更新位为0,变相位为关,自动重载位为开。定时器在定时器分辨率内的等待时间后启动递减计数。
3.  TCNTnTCMPn的值相同时,TOUTn的逻辑电平从低电平变为高电平。
4.  TCNTn到达0时, 发出中断请求并且TCNTBn的值加载到暂存器中。 在下一个定时器标记时刻, 重载TCNTn为暂存器(TCNTBn)的值。
5. 中断服务程序(ISR)中,为下一个持续时间分别设置TCNTBnTCMPBn8020+60)和60
6.  TCNTnTCMPn的值相同时,TOUTn的逻辑电平从低电平变为高电平。
7. 当当 TCNTn到达0时,触发一个中断自动重载TCNTnTCNTBn的值。
8. 中断服务程序(ISR)中,禁止自动重载和中断请求以停止定时器。
9.  TCNTnTCMPn的值相同时,TOUTn的逻辑电平从低电平变为高电平。
10. 尽管 TCNTn到达0,但因为禁止了自动重载,所以TCNTn并不会再次重载并且定时器已经停止了。
11. 不再产生中断请求。

 

 

三、实战演练

1、实现蜂鸣器播放音调的功能

area Init,code, readonly
code32
entry
start
ldr sp, =0x34000000
import Main
b Main
stop
b stop
end
#include "2440addr.h"
/*
tclk = pclk / ((pre + 1) * div)
fout = 1kHz
pclk = 50MHz
pre = 15
div = 8
1/fout = count * (1/tclk)
1/fout = count * ((pre+1) * div) / pclk
count = pclk / (fout*(pre+1)* div)
= 50Mhz / (1KHz * 16 * 8)
= 390.625  = 391
*/
/*
*/
#define PCLK 50000000
unsigned int gFre[7] = 
{500, 650, 880, 1000, 1200, 1400, 1600};
void setFre(int fre)
{
// 定时器配置
rTCFG0 |= (15<<0);   // pre = 15
rTCFG1 |= (2<<0);    // div = 8
rTCNTB0 =  PCLK / (fre * 16 * 8); 
rTCMPB0 = rTCNTB0 >> 1;   // 占空比50%开发板
rTCON |= (1<<3) | (1<<1) | (1<<0);  // 自动加载,手动更新,启动定时器。
rTCON &= ~(1<<1);   //  关闭手动加载
}	
void toutIoCfg(void)
{
// 引脚配置
rGPBCON &= ~(3<<0);
rGPBCON |= (2<<0);   // 配置为tout0功能
}
void tout0Init(void)
{
// 引脚配置
rGPBCON &= ~(3<<0);
rGPBCON |= (2<<0);   // 配置为tout0功能
// 定时器配置
rTCFG0 |= (15<<0);   // pre = 15
rTCFG1 |= (2<<0);    // div = 8
rTCNTB0 = 391;        
rTCMPB0 = rTCNTB0 >> 1;   // 占空比50%
rTCON |= (1<<3) | (1<<1) | (1<<0);  // 自动加载,手动更新,启动定时器。
rTCON &= ~(1<<1);   //  关闭手动加载
}
void delay(unsigned int loops)
{
while(loops-->0);
}
void Main(void)
{
int i=0;
toutIoCfg();
while(1)
{
for(i=0; i<7; i++)
{
setFre(gFre[i]);
delay(0x10000000);
}
}
}

 

2、实现蜂鸣器播放音乐 《大海》 的功能

	AREA Init,CODE,READONLY
ENTRY
CODE32
;IMPORT	Eint_Irq
import	Main
EXPORT	__ENTRY
__ENTRY
start
b		reset_handler
nop
b		swi_handler
nop
nop
nop
b		irq_handler
nop
reset_handler
;ldr    r0 , =0x53000000
;mov    r1 , #0x0
;str    r1 , [r0]
ldr r0,=0x34000000
mov	sp, r0
sub r0, r0, #0x500
mrs		r1, cpsr
bic		r1, r1, #0x1f
orr		r1, r1, #0x12
msr		cpsr_c, r1
mov sp, r0
sub r0, r0, #0x500
mrs		r1, cpsr
bic 	r1, r1, #0x1f
bic 	r1, r1, #0x80
orr 	r1, r1, #0x1f
msr		cpsr_c, r1
mov		sp, r0
b		Main
stop	
b		stop
irq_handler
sub		lr, lr, #4
stmfd	sp!, {r0-r12, lr}
ldr		r1, =0x56000014
ldr		r0, =0
str		r0, [r1]
;bl	Eint_Irq
ldmfd sp!, {r0-r12, pc}^
;import c_swi_handler
swi_handler
stmfd	sp!, {r0-r12, lr}
ldr		r0, [lr, #-4]
bic		r0, r0, #0xff000000
;bl		c_swi_handler
ldmfd	sp!, {r0-r12, pc}^
export	asmdelay	
asmdelay
;mov		r7, #0x1000000
mov		r7, r0
del_loop
sub		r7, r7, #1
cmp		r7, #0
bne		del_loop
mov		pc, lr
END
#define rGPBCON    (*(volatile unsigned *)0x56000010)	//Port B control
#define rGPBDAT    (*(volatile unsigned *)0x56000014)	//Port B data
#define rGPBUP     (*(volatile unsigned *)0x56000018)	//Pull-up control B
#define rTCFG0  (*(volatile unsigned *)0x51000000)	//Timer 0 configuration
#define rTCFG1  (*(volatile unsigned *)0x51000004)	//Timer 1 configuration
#define rTCON   (*(volatile unsigned *)0x51000008)	//Timer control
#define rTCNTB0 (*(volatile unsigned *)0x5100000c)	//Timer count buffer 0
#define rTCMPB0 (*(volatile unsigned *)0x51000010)	//Timer compare buffer 0
#define rTCNTO0 (*(volatile unsigned *)0x51000014)	//Timer count observation 0
#define PCLK	50000000
void Buzzer_init(void)
{
rGPBCON &= ~3;			//set GPB0 as tout0, pwm output
rGPBCON |= 2;
rTCFG0 &= ~0xff;
rTCFG0 |= 15;			//prescaler = 15+1
rTCFG1 &= ~0xf;
rTCFG1 |= 2;			//mux = 1/8
rTCNTB0 = (PCLK>>7)/1000;
rTCMPB0 = rTCNTB0>>1;	// 50%
rTCON &= ~0x1f;
rTCON |= 0xb;			//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
rTCON &= ~2;			//clear manual update bit
}
void Buzzer_Freq_Set( unsigned int freq )
{
rTCNTB0 = (PCLK>>7)/freq;
rTCMPB0 = rTCNTB0>>1;	// 50%
}
void Buzzer_Stop( void )
{
rGPBCON &= ~3;			//set GPB0 as output
rGPBCON |= 1;
rGPBDAT &= ~1;
}
/*
* 调用该函数, 可以控制蜂鸣器响起, 原理是使能了PWM的TOU1功能为动重装模式
*/
void beep_on( void )
{
rTCON = (1<<0) | (1<<3);//clear manual update bit
}
/*
* 调用该函数, 可以控制蜂鸣器响起, 原理是停止了PWM的TOU1功能
*/
void beep_off( void )
{
rTCON &= ~1;
}
//音阶频率表
const unsigned int yinyue[3][7]
={
262,  294,  330,  349,  392,  440,  494,  //低音
523,  587,  659,  698,  784,  880,  988,  //中音
1046, 1174, 1318, 1396, 1568, 1760, 1975  //高音
};
/*
* 大海的简谱, 如果大海能够.....
*/
const unsigned char dahai[] =
{
0x13,  0x15 , 0x16, 0x16, 0x16, 0x16, 0x21, 0x16, 0x15, 0x15, 0x16, 0x15,  //哀愁
0x13,  0x12 , 0x11, 0x11, 0x11, 0x11, 0x12, 0x13,
0x13,  0x12 , 0x11, 0x11, 0x11, 0x11, 0x21, 0x16, 0x15, 0x15, 0x16, 0x15,
0x13,  0x15,  0x16, 0x21, 0x21, 0x16, 0x15, 0x15,//飘远
};
/*
* 大海的简谱, 控制每一个音的时间 1为长时间 4为短时间
*/
const unsigned char time[] =
{
4,		4,   4,     2,    4 ,   2,    4,     4,    4,    2,    4,    2 ,//哀愁
4,      4,   4,     2,    4,    2,    2,     1,
4,      4,   4,     2,    4,    2,    4,     4,     4,   2,    4,    2,
4,      4,   2,      4,   2,     4,   4,     1  //飘远
};
//主函数
int Main(void)
{
unsigned int loop = 0;   //循环控制变量
unsigned int a = 0;      //计算高中低音使用的变量
unsigned int b = 0;		 //计算do re mi ....使用的变量
unsigned int delay = 0;  //计算每一个音延时使用的变量
//GPH0.GPH0CON = (GPH0.GPH0CON) & ~(0x3f<<1); //初始化key1-key6的引脚功能为输入
Buzzer_init();   //初始化PWM硬件, 此刻没有启动PWM
//while( 	( GPH0.GPH0DAT & (0x3ful<<1) )  == (0x3ful<<1) );//等待有任意一个按键被按下,程序才会向下
while(1)
{
//循环播放 音乐
for(loop=0; loop>4;       		    //计算出高低音
b = (dahai[loop] & 0x0f )-1;  	    //计算出DO RE MI FA SO LA XI
delay = 0x6500000ul/time[loop];	    //计算出每个音的播放间隔时间
Buzzer_Freq_Set( yinyue[a][b] ); //重新设定频率
beep_on();			//发出一个音
asmdelay(delay);  //播放延时
beep_off();         //关闭蜂鸣器, 每个音播放完成后有间隔感
asmdelay(0x20);   //关闭蜂鸣器
}
asmdelay(1000000);  //播放延时
}
}


http://chatgpt.dhexx.cn/article/39tcC2pb.shtml

相关文章

ARM-(一)定时器:PWM定时器,看门狗WTD定时器

定时器Timer 总结PWMPWM简介PWM实现过程 以三星芯片S5P6818_Datasheet为例&#xff1a; soc&#xff1a;S5P6818 core&#xff1a;A53 总结 定时器设计思路&#xff1a; &#xff08;1&#xff09;时钟源(主频) --> 预分频(一级) --> 选择分频(二级) …&#xff1a;得到…

OMAPL138 + SPARTAN6 DSP+ARM+FPGA开发例程

目 录 本例程基于信迈OMAPL138SPARTAN6评估板开发。 开发板准备 16 查看仿真器驱动是否正常安装 17程序加载和烧写 19 基于仿真器的程序加载和烧写 19 设置工程配置文件信息 19测试仿真器是否正常连接 20加载 GEL 文件 21CCS 连接开发板 CPU 22查看 CPU 版本号 23加载文件烧写程…

LV.9 ARM体系结构与接口技术

1 计算机硬件基础 Day1-1 底层课程导学 课程回顾 1.编程基础 1.C语言基础 2.C高级及Linux 3.数据结构 2.应用开发 1.IO 2.进程 3.网络编程 3.底层开发 1.ARM 2.系统移植 3.驱动开发 嵌入式系统分层 操作系统的作用 向下管理硬件、向上提供接口(API) 应用开发 即使用系统提…

嵌入式系统考试复习(武昌首义学院)

第一章 1. 从计算机技术应用的角度&#xff08;嵌入式系统的定义&#xff09;&#xff08;背&#xff09;&#xff08;书P1&#xff09; 嵌入式系统是指以应用为中心&#xff0c;以计算机技术为基础&#xff0c;软硬件可减裁&#xff0c;适应应用系统对功能、可靠性、成本、体…

ARM(笔记)

ARM接口技术 ARM接口技术 : 芯片内部 向外扩展 ​ ARM: 架构 芯片 公司 ​ 汇编 - C语言 系统移植 Linux 驱动开发 一、ARM系统硬件组成和运行原理 1.硬件组成(手机为例) ​ &#xff08;1&#xff09;flash储存器&#xff1a;存储程序 ​ 特点&#xff1a;永久的保存…

STM8 学习笔记13:PWM

PWM Gitee 空间跳转&#xff1a;https://gitee.com/galoc/stm8.git 1 概述 PWM也叫脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。频率、周期、占空比。 1.1 PWM 频率 是指在 1 秒钟内&#xff0c;信号从高电平到低电平再回到高电平的…

Xming X Server 配置和使用

Xming X Server 配置和使用 Linux以及各种Unix like的操作系统现在都用基于X Window图形界面. 这个东西虽然块头比较大, 效率不太高, 导致Linux的3D游戏一直没什么动静, 但是, 它接口良好, 扩展性和可移植性都很好, 最重要的是具有网络透明性, 所以我们就可以很方便的远程启动…

【Ubuntu20.04 LTS】WSL1+Xming配置图形界面

文章目录 一、配置1、 win10上 安装 Xming2、WSL1上 Bash安装 Xfce4 二、应用1、点击win10左下角搜索XLaunch2、WSL1的终端中输入以下命令启动bash 一、配置 1、 win10上 安装 Xming https://sourceforge.net/projects/xming/ https://jaist.dl.sourceforge.net/project/xmin…

windows 命令行ssh + Xming打开虚拟机的图形界面应用

windows中使用OpenSSH提供的ssh作ssh client&#xff0c;使用xming作Xserver。 ubuntu虚拟机运行了ssh server。 执行如下命令&#xff0c;一直失败。 ssh -X snowflakes192.168.150.132 查阅发现ssh中貌似会自动设置DISPLAY为localhost:10.0 那么使用如下命令重新启动xmin…

win10+Xming+Xshell显示远程linux服务器的图形程序窗口

第一步&#xff1a;安装Xshell 破解版安装教程&#xff1a; Xshell的下载与使用 - 知乎 第二步&#xff1a;安装Xming 1. 在bing页面搜索Xming&#xff0c;进入官网 2. 直接download 3. 下载完毕&#xff0c;点开安装包&#xff0c;直接按默认设置一路点击next完成安装。 …

容器docker(CentOS8)使用SSH配合Xming显示图形GUI界面

Xshell7安装在win7x64里,容器CentOS8的宿主机是ubuntu18.04(安装在VMware里) docker search cobaltstrike docker pull xrsec/cobaltstrike 在ubuntu里启动docker: setsid docker run -it --name cs45 -e passwd"admin888" -e server_ip"127.7.7.2" -e s…

xming+shell启动linux应用程序注意事项(xming不能启动)

xming和xshell组合起来显示linux服务器的界面网上教程很多&#xff0c;大家可以自行查找&#xff0c;但是这里有部分细节大多数文章都没有提到。当多个用户工作在同一个linux server下&#xff0c;以下设置需要修改&#xff0c;否则xming不能启动。 注意上方的Display number&a…

xming登录linux图形中文乱码,putty+xming远程登录Linux图形界面

Linux 本身是没有图形化界面的&#xff0c;所谓的图形化界面系统只不过中 Linux 下的应用程序。这一点和 Windows 不一样。Windows 从 Windows 95 开始&#xff0c;图形界面就直接在系统内核中实现了&#xff0c;是操作系统不可或缺的一部分。Linux 的图形化界面&#xff0c;底…

Pycharm、xshell、xming连接远程服务器图形界面显示

Pycharm、xshell、xming连接远程服务器图形界面显示 1.配置远程接释器 这个网上好多教程都是可用的&#xff0c;不再多说&#xff0c; 2.xshell连接到远程主机 使用xshell连接到远程主机&#xff0c;使用echo $DISPLAY查看本机显示端口。不出意外本机打开的第一个xshell连接…

xming2

转载于:https://www.cnblogs.com/243920934qq/p/6074700.html

Vscode+Xming连接远程服务器图形化界面GUI

本机配置 首先在本机安装Xming Xming配置 安装后启动XLaunch&#xff0c;设置Display number 将远程服务器的IP添加进X0.hosts文件 VS code配置 安装插件Remote X11和Remote X11 (SSH) 打开SSH配置文件 添加 ForwardAgent yesForwardX11 yesForwardX11Trusted yes远程服…

XMing + XShell 打开Linux服务器网页界面

1、修改X0.hosts文件 修改为服务器的ip地址 2、打开XLaunch、XMing 打开XLaunch后一路 下一步>下一步>完成 打开XMing 3、XShell连接服务器 连接服务器的时候SSH->隧道&#xff0c;√上转发X11连接到&#xff0c;选择X DISPLAY&#xff0c;点击确定 4、XShell命…

Xming连接无桌面linux,[转帖]windows+xshell+xming访问非桌面版Linux服务器

1、Linux服务器 (1)安装Firefox&#xff0c;目录为&#xff1a;/usr/local/firefox (2) 配置ssh #vi /etc/ssh/sshd_config 取消下面一行的注释——如果没有这一行则手动添加之&#xff1a; X11Forwrding yes 这样配置的作用就是允许SSH的X转发。 从SourceForge下载Xming-setup…

Xming + SecureCRT 在Windows下远程Linux主机的X11图形转发

1. 在windows上安装Xming(下一步下一步即可)&#xff0c;一般安装完会自动开启&#xff08;右下角有个Xming的图标&#xff09; 2. 关掉Xming&#xff08;右击图标退出&#xff09; 3. 打开XLaunch&#xff0c;点击下一步 ——> 下一步&#xff0c;把No Access Contro…

vscode 通过 X11/Xming 转发显示远程 GUI 窗口

Xming安装配置 一、vscode 通过 X11/Xming 转发显示远程 GUI 窗口1.1 Xming 安装1.2 配置1.2.1 客户端配置1. 安装 X11 插件2. vscode 中对 X11 进行相关设置 1.2.2 服务器配置 二、vscode 有关 python 的 launch.json 配置文件三、相关问题及解决办法 一、vscode 通过 X11/Xmi…