您的位置 首页 方案

ARM 学习笔记七 (PWM实验)

PWM-脉宽调制。我的理解是通过控制一个计数器来实现不同脉宽的输出,从而驱动蜂鸣器发出不同的声音。本实验用到的寄存器如下:GPBCON–…

PWM-脉宽调制。我的了解是经过操控一个计数器来完成不同脉宽的输出,然后驱动蜂鸣器宣布不同的声响。

本试验用到的寄存器如下:

GPBCON — I/O端口装备寄存器 B
00=Input 01=Output 10=PWM 11=Reserved

GPBDAT — I/O端口数据寄存器 B

GPFUP –I/O端口上拉电阻使能寄存器 B
0=Enable 1=Disabled

TCFG0 — 时钟装备寄存器0 (主要是设置预分频)
定时器输入时钟频率=PCLK/{预分频}/{切割值}
{预分频}=1~255
{切割值}=2,4,8,16,32
Address: 0x51000000
Reset value:0x00000000
[7:0]:These 8 bits determine prescaler value for Timer0 and 1

TCFG1 –时钟装备寄存器1(主要是设置切割值)
Address: 0x51000004
Reset value:0x00000000
[3:0]:Select MUX input for PWM Timer0
0000=1/2 0001=1/4 0010=1/8
0011=1/16 01XX=External TCLK0

TCON — 时钟操控寄存器
Address:0x51000008
Reset value:0x00000000
[0]: Determine start/stop for Timer0 (设置发动/中止)
0=Stop 1=Start for Timer0
[1]: Determine the manual update for Timer0 (设置答应手动修正计数)
0=No operation 1=Update TCNTB0 & TCMPB0
[2]: Determine the output inverter on/off for Timer0 (设置中止)
0=Inverter off 1=Inverter on for TOUT0
[3]: Determine auto reload on/off for timer0
0=One-shot 1=Interval mode(auto reload)
[4]: Determine the dead zone operation
0=Disable 1=Enable

TCNTB0 — timer0计数缓存寄存器
Address:0x5100000c
Reset value:0x00000000
[15:0]:Set count buffer value for Timer0

TCMPB0 — timer0比较缓存寄存器
Address:0x51000010
Reset value:0x00000000
[15:0]:Set compare buffer value for Timer0

试验办法:
1.按下k1键,使TOUT0递加占空比

2.按下k2键,使TOUT0递减占空比

3.按下k3键,中止输出

//代码1—参阅阿南的比如,这个简略

#include “2410addr.h”

#define KEY1 (1<<1) // rGPF[1] =1 ;
#define KEY2 (1<<4) // rGPF[4] =1 ;
#define KEY3 (1<<2) // rGPF[2] =1 ;

unsigned short freq =0;

//===========================[ SYSTEM ]===================================================
//static int delayLoopCount = 400;
static int delayLoopCount = FCLK/10000/10;

void Delay(int time)
{
// time=0: adjust the Delay function by WatchDog timer.
// time>0: the number of loop time
// resolution of time is 100us.
int i,adjust=0;
if(time==0)
{
time = 200;
adjust = 1;
delayLoopCount = 400;
//PCLK/1M,Watch-dog disable,1/64,interrupt disable,reset disable
rWTCON = ((PCLK/1000000-1)<<8)|(2<<3);
rWTDAT = 0xffff; //for first update
rWTCNT = 0xffff; //resolution=64us @any PCLK
rWTCON = ((PCLK/1000000-1)<<8)|(2<<3)|(1<<5); //Watch-dog timer start
}
for(;time>0;time–)
for(i=0;i if(adjust==1)
{
rWTCON = ((PCLK/1000000-1)<<8)|(2<<3); //Watch-dog timer stop
i = 0xffff – rWTCNT; //1count->64us, 200*400 cycle runtime = 64*i us
delayLoopCount = 8000000/(i*64); //200*400:64*i=1*x:100 -> x=80000*100/(64*i)
}
}

void PWM_Ini(unsigned short cycle,unsigned short duty){

if(duty > cycle) duty = cycle;

//定时器输入时钟频率=PCLK/{预分频}/{切割值}
rTCFG0 =0x64; //设置预分频为100
rTCFG1 =0x0;//设置切割值为1/2

rTCNTB0 =cycle;
rTCMPB0 =duty;


rTCON = 0x0A;//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, stop timer 0
//000 01010
rTCON = 0x09;//disable deadzone, auto-reload, inv-off, no operation, start timer 0
//1001
}

void PWM_Stop(){
freq = 2000;
rGPBCON = 0x0;
rGPBDAT = 0x0;
}

void PWM_Output(int number){

if ( number > 0 ){
if ( freq < 255 )
freq += 16;
else
freq = 0;
}

if ( number < 0 ){
if ( freq >= 16 )
freq -= 16;
else
freq = 0;
}

rTCMPB0=freq;
}

void Main(void){

rGPFUP = 0xf800;// KEY [7:0] => PU En
rGPFCON=0xfcc0; //KEY[7:0] => INPUT;

rGPBCON = 0x0;
rGPBCON = 0x02;//TOUT0为输出端口

PWM_Ini(255,freq);

Delay(0);

while (1){

if ( !(rGPFDAT & KEY1) ){
Delay(1000);
//if (rGPGDAT & KEY1) continue;
PWM_Output(1);
}

if ( !(rGPFDAT & KEY2) ){
Delay(1000);
//if (rGPGDAT & KEY2) continue;
PWM_Output(-1);
}

if ( !(rGPFDAT & KEY3) ){
Delay(1000);
//if (rGPGDAT & KEY3) continue;
PWM_Stop();
}

}
}

上面的比如便是按键去抖功用没能调试出来。

//代码2—参阅开发板带的比如,这个欠好了解

#define GLOBAL_CLK 1

#include “def.h”
#include “2440addr.h”
#include “option.h”

#define KEY1 (1<<1) // rGPF[1] =1 ;
#define KEY2 (1<<4) // rGPF[4] =1 ;
#define KEY3 (1<<2) // rGPF[2] =1 ;

static unsigned int freq;

void PWM_Ini(){

ChangeClockDivider(3,1); //取得PCLK=67.5MHz
ChangeMPllValue(127,2,1);

rGPFUP = 0xf800;// KEY [7:0] => PU En
rGPFCON=0xfcc0; //KEY[7:0] => INPUT;
}

void PWM_Stop(){
freq = 2000;
rGPBCON = 0x0;
rGPBDAT = 0x0;
}

void PWM_Output(int number){

rGPBCON = 0x0;
rGPBCON = 0x02;//TOUT0为输出端口
//rGPBUP = 0x01;//制止上拉电阻

//定时器输入时钟频率=PCLK/{预分频}/{切割值}
rTCFG0 =0x64; //设置预分频为100
rTCFG1 =0x0;//设置切割值为1/2


if ( number > 0 ){
if ( freq < 20000 )
freq += number;
else
freq = 2000;
}

if ( number < 0 ){
if ( freq > 300 )
freq -= number;
else
freq = 2000;
}


rTCNTB0 =freq;
rTCMPB0 =rTCNTB0>>1;


rTCON = 0x0B;//disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0
//000 01011
rTCON &= ~2;//clear manual update bit
}

void Main(void){

freq = 2000;

PWM_Ini();

while (1){

if ( !(rGPFDAT & KEY1) )
PWM_Output(100);

if ( !(rGPFDAT & KEY2) )
PWM_Output(-100);

if ( !(rGPFDAT & KEY3) )
PWM_Stop();

}
}

这个比如每次都要从头设置PGB端口。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/fangan/264275.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部