TQ210裸机编程(8)——PWM

事实上,要使TQ210板子上的蜂鸣器发声是非常容易的,因为天嵌给TQ210的蜂鸣器为有源蜂鸣器,只要给蜂鸣器供电,蜂鸣器就会发出固定频率的声音。

TQ210板子上的蜂鸣器接在TOUT1引脚,只要给它高电平,蜂鸣器就会发声。

如下代码:

/* 配置GPD0[1]为输出 */
	GPD0CON &= ~(0xF << 4);
	GPD0CON |= 1 << 4;
	/* GPD0[1]输出高电平即可使蜂鸣器发声 */
	GPD0DAT |= 1 << 1;

S5PV210包含5个32位的脉宽调制定时器。这些定时器都可产生中断。每个定时器可选择输入时钟为PCLK或SCLK_PWM。


定时器的操作比较简单,下面列出操作步骤:

1、设置TCFG0寄存器:配置定时器的一级分频值

1、设置TCFG1寄存器:配置定时器的二级分频值

3、设置TCNTBn寄存器:递减计数器缓冲寄存器

3、设置TCMPBn寄存器:比较缓冲寄存器

4、设置TCON寄存器:

(1)手动更新on(执行后,CPU会把TCNTBn的值加载到递减计数器中)

(2)手动更新off、自动重载、启动定时器

当递减计数器的值减到和TCMPBn的值相等时,则翻转输出引脚极性;

当递减计数器的值减到0时,如果使能了定时器中断则产生中断,如果使能了自动重载则重载TCNTBn的值到递减计数器,开始重新计数


频率计算:

我之前的时钟配置为PCLK_PSYS=66MHz,这里就由它为定时器提供时钟源。

Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value}

我的配置为:prescaler value = 65

                      divider value = 8

Timer Input Clock Frequency = 66MHz / (65 + 1) / 8 = 125000
假设输出频率为n,则
TCNTB1 = 1125000 / n

比如输出1Hz,占空比为50%

TCNTB1 = 125000 / 1;
TCMPB1 = TCNTB1 / 2;


具体代码如下:

start.S

.global _start					/* 声明一个全局的标号 */
_start:

	bl clock_init

	bl main						/* 跳转到C函数去执行 */

halt:
	b halt


clock.c

#define APLLCON0		*((volatile unsigned int *)0xE0100100)
#define MPLLCON			*((volatile unsigned int *)0xE0100108)
#define EPLLCON0		*((volatile unsigned int *)0xE0100110)
#define VPLLCON			*((volatile unsigned int *)0xE0100120)
#define CLK_SRC0 		*((volatile unsigned int *)0xE0100200)
#define CLK_DIV0		*((volatile unsigned int *)0xE0100300)
#define CLK_DIV1		*((volatile unsigned int *)0xE0100304)
#define CLK_DIV2		*((volatile unsigned int *)0xE0100308)
#define CLK_DIV3		*((volatile unsigned int *)0xE010030C)

void clock_init()
{
	/* 1、设置PLL_LOCK寄存器(这里使用默认值) */
	/* 2、设置PLL_CON寄存器(使用芯片手册推荐的值) */
	APLLCON0	= (1 << 0) | (3 << 8) | (125 << 16) | (1 << 31);	/* FOUTAPLL = 1000MHz */
	MPLLCON 	= (1 << 0) | (12 << 8) | (667 << 16) | (1 << 31);	/* FOUTMPLL = 667MHz */
	EPLLCON0 	= (1 << 0) | (12 << 8) | (667 << 16) | (1 << 31);	/* FOUTEPLL = 96MHz */
	VPLLCON 	= (3 << 0) | (6 << 8) | (108 << 16) | (1 << 31);	/* FOUTVPLL = 54MHz */
	
	/* 3、选择PLL为时钟输出 */
	/* MOUT_MSYS = SCLKAPLL = 1000MHz
	** MOUT_DSYS = SCLKMPLL = 667MHz
	** MOUT_PSYS = SCLKMPLL = 667MHz
	*/
	CLK_SRC0 = (1 << 0) | (1 << 4) | (1 << 8) | (1 << 12);
	
	/* 4、设置系统时钟分频值 */
	/* freq(ARMCLK) = MOUT_MSYS / (APLL_RATIO + 1) = 1000MHz / (0 + 1) = 1000MHz
	** freq(HCLK_MSYS) = ARMCLK / (HCLK_MSYS_RATIO + 1) = 1000MHz / (4 + 1) = 200MHz
	** freq(PCLK_MSYS) = HCLK_MSYS / (PCLK_MSYS_RATIO + 1) = 200MHz / (1 + 1) = 100MHz
	** freq(HCLK_DSYS) = MOUT_DSYS / (HCLK_DSYS_RATIO + 1) = 667 / (3 + 1) = 166MHz
	** freq(PCLK_DSYS) = HCLK_DSYS / (PCLK_DSYS_RATIO + 1) = 166 / (1 + 1) = 83MHz
	** freq(HCLK_PSYS) = MOUT_PSYS / (HCLK_PSYS_RATIO + 1) = 667 / (4 + 1) = 133MHz
	** freq(PCLK_PSYS) = HCLK_PSYS / (PCLK_PSYS_RATIO + 1) = 133 / (1 + 1) = 66MHz
	*/
	CLK_DIV0 = (0 << 0) | (4 << 8) | (1 << 12) | (3 << 16) | (1 << 20) | (4 << 24) | (1 << 28);
}

main.c

#define GPD0CON				*((volatile unsigned int *)0xE02000A0)
#define GPD0DAT				*((volatile unsigned int *)0xE02000A4)

#define TCFG0				*((volatile unsigned int *)0xE2500000)
#define TCFG1				*((volatile unsigned int *)0xE2500004)
#define TCON				*((volatile unsigned int *)0xE2500008)
#define TCNTB1				*((volatile unsigned int *)0xE2500018)
#define TCMPB1				*((volatile unsigned int *)0xE250001C)
#define TCNTO1				*((volatile unsigned int *)0xE2500020)

int main()
{
#if 0
	/* 配置GPD0[1]为输出 */
	GPD0CON &= ~(0xF << 4);
	GPD0CON |= 1 << 4;
	/* GPD0[1]输出高电平即可使蜂鸣器发声 */
	GPD0DAT |= 1 << 1;
#endif
	/* 配置GPD0[1]为定时器1输出:TOUT1 */
	GPD0CON &= ~(0xF << 4);
	GPD0CON |= 2 << 4;

	/*
	** 配置定时器输入频率
	** Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / {divider value} 
	** = 66MHz / (65 + 1) / 8 = 125000
	** 假设输出频率为n,则
	** TCNTB1 = 1125000 / n
	*/
	TCFG0 = 65;
	TCFG1 = 3 << 4;

	/* 产生1Hz,占空比为50%的输出频率 */
	TCNTB1 = 125000 / 1;
	TCMPB1 = TCNTB1 / 2;

	TCON = (1 << 9);	/* 手动更新on */
	TCON = (1 << 8) | (1 << 11);	/* 启动定时器/手动更新off/自动重载 */

	while (1);
	
	return 0;
}


Makefile

beeper.bin: start.o clock.o main.o
	arm-linux-ld -Ttext 0xD0020010 -o key.elf $^
	arm-linux-objcopy -O binary key.elf $@
	arm-linux-objdump -D key.elf > key.dis
	
%.o : %.c
	arm-linux-gcc -c $< -o $@
%.o : %.S
	arm-linux-gcc -c $< -o $@
	
clean:
	rm *.o *.elf *.bin *.dis

烧写过程见《TQ210裸机编程(5)——系统时钟配置》

转载请注明来源:http://blog.csdn.net/zjhsucceed_329/

QQ:809205580

技术交流群:153530783 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗-永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值