s5p6818PWM驱动蜂鸣器实验

s5p6818PWM驱动蜂鸣器实验

一, PWM 概念

PWM (Pulse Width Modulation ):脉冲宽度调制解调器。

阈值:就是输出的 PWM 中,高饱和保持的时间与该PWM 的时钟周期的时间之比。

脉冲:方波

宽度调制:方波的周期和占空比可以调节。

占空比:一个周期内,高电平占整个周期的百分比。

比如:高电平0.5s 低电平0.5 周期 1s 占空比:50%

蜂鸣器种类:

1)有源蜂鸣器:

​ 蜂鸣器内部有一个震荡源,蜂鸣器内部有电流流过蜂鸣器发声,

​ 没有电流流过蜂鸣器不发声。

2)无源蜂鸣器:

​ 蜂鸣器内部没有震荡源,

​ 通过编程的方式让蜂鸣器以一定的频率震荡蜂鸣器即可发声,

​ 否则不发声。

F5P6818是有缘蜂鸣器

二, PWM 应用

它是利用调制的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛的测量,通信,功率控制与变换等许多领域。脉冲宽度调制( PWM )是一种对模拟信号通过改进的计数器的使用,方波的替代被调制变成对一个具体模拟信号的可以进行编码。

常见应用有:电机控制, DAC 输出等。

三, S5P6818PWM 概述

S5P6818 有5 路32 位PWM 定时器。这些定时器为ARM 子系统提供外部中断。另外,计时器0,1,2,3,包括PWM 功能并且驱动外部I / O 引脚。PWM 定时器0 有一个Timer4 是外部定时器没有输出指针。可选的死区产生器,支持驱动大电流设备的能力。

定时器使用 APB-PCLK 作为时钟源。定时器0 和1 共享一个8 位可编程的预分频器,位PCLK 提供第一级分频。定时器2,3 和4 共享另外一个8 位预分频器。每个定时器有自己私有的时钟分配器,提供一个二级时钟分频(分频数值 1,2,4,8,16 )。

每个定时器都有一个 32 位递减计数器,通过计时器时钟驱动。递减计数器初始值加载从TCNTB0 。当递减计数器到达0 时,定时器中断请求产生并通知CPU ,定时器操作完成。当定时器递减计数器到达0 时,相对应的TCNTBn 中的值自动加载到递减计数器中开始下一个周期。然而,如果计时器停止,例如,通过清除计时器TCONn 的使能位,在定时器运行时,TCNTBn 中的值不在加载到定时器中。

PWM 功能使用TCMPB0寄存器的值。定时器控制逻辑改变输出并转换到定时器控制逻辑。因此,比较寄存器决定PWM 输出的高电平时间。

四, S5P6818 框图

在这里插入图片描述

五, S5P6818 PWM 控制蜂鸣器

硬件电路图

在这里插入图片描述

六,相关寄存器分析

1.分析芯片手册

在这里插入图片描述

2.分析GPIO章节–GPIOxALTFN0

在这里插入图片描述在这里插入图片描述
设置GPIOC14引脚为PWM功能, GPIOCALTFN0[29:28] = 10

基本地址:0xC001_C000h(PWM)

地址=基地址+ C020h,复位值= 0x0000_0000

3.分析PWM章节

在这里插入图片描述

4.分析PWM章节–TCFG0

在这里插入图片描述

基本地址:0xC001_8000h(PWM)

地址=基地址+ 0x00h,复位值= 0x0000_0101

Timer Input Clock Frequency = PCLK/({prescaler value + 1})/{divider value}
{prescaler value} = 1 to 255
{divider value} = 1, 2, 4, 8, 16
Dead Zone Length = 0 to 254

定时器输入时钟频率 = PCLK /({预分频器值+ 1})/ {分频器值}

{预分频器值} = 1至255

{divider value} = 1,2,4,8,16

死区长度= 0至254

**注意:**如果将死区长度设置为“ n”,则实际死区长度为“ n +1”(n = 0至254)。PCLK的源时钟为BLK_MIF中的BUS_DPLL

5.分析PWM章节–TCFG1

在这里插入图片描述

基本地址:0xC001_8000h(PWM)

地址=基地址+ 0x40h,复位值= 0x0000_0000

设置PWM定时器的二级分频值

选择PWM定时器2的复用输入

0000 = 1/1 (一分频)

0001 = 1/2 (二分频)

0010 = 1/4(四分频)

0011 = 1/8 (8分频)

0100 = 1/16 (16分频)

0101 =外部TCLK1

0110 =外部TCLK1

0111 =外部TCLK1

6.分析PWM章节–TCON

在这里插入图片描述
在这里插入图片描述

TCON:PWM定时器控制寄存器

Base Address: 0xC001_8000h (PWM)
Address = Base Address + 0x08h, Reset Value = 0x0000_0000

基本地址:0xC001_8000h(PWM)

地址=基地址+ 0x80h,复位值= 0x0000_0000

TCON[15]:定时器2的自动重载的开和关

​ 0:只加载一次 1:自动重载 将TCNTBn中的值加载的递减计数器中

TCON[14]:定时器2输出翻转的开和关

​ 0:关闭翻转 1:打开翻转 PWM方波的初始状态
在这里插入图片描述

TCON[13]:定时器2的手动更新位

​ 0:关闭手动更新 1:打开手动更新 给TCNTB和TCMPB赋值时需要手动更新

TCON[12]:定时器2的使能和禁止位

​ 0:停止PWM定时器 1:开启PWM定时器

7.分析PWM章节–TCNTB2

在这里插入图片描述

Base Address: 0xC001_8000h (PWM)
Address = Base Address + 0x24h, Reset Value = 0x0000_0000

基地址:0xC001_8000h(PWM)

地址 = 基地址 + 0x24h,复位地址0x0000_0000

8.分析PWM章节–TCMPB2

在这里插入图片描述

Base Address: 0xC001_8000h (PWM)
Address = Base Address + 0x28h, Reset Value = 0x0000_0000

基地址:0xC001_8000h (PWM)

地址 = 基地址 + 0x28h,复位地址 = 0x0000_0000

7.编写代码

pwm.c
#include "pwm.h"

void hal_pwm_init()
{
	//1.设置GPIOC14引脚为PWM功能  GPIOCALTFN0[29:28] = 0b10
	GPIOC.ALTFN0 &= ~(3 << 28);
	GPIOC.ALTFN0 |= (2 << 28);
	//2.设置对PCLK时钟的一级分频值,进行250分频  TCFG0[15:8] = 249
	PWM.TCFG0 &= ~(0xFF << 8);
	PWM.TCFG0 |= (249 << 8);
	//3.设置对PCLK时钟的二级分频值,进行2分频  TCFG1[11:8] = 0b0001
	PWM.TCFG1 &= ~(0xF << 8);
	PWM.TCFG1 |= (1 << 8);
}
void hal_pwm_switch(int cnt, int cmp, pwm_stu st)
{
	if (st == ON){
		hal_pwm_init();
		//4.设置TCNTB2的初始值,确定PWM方波的最终周期
		//设置置TCNTB2 = 300-1   PWM方波的频率为1000Hz
		PWM.TCNTB2 = cnt;
		//5.设置TCMPB2的初始值值,确定PWM方波的占空比
		//	设置TCMPB2 = 150-1
		PWM.TCMPB2 = cmp;
		//6.打开电平翻转功能  TCON[14] = 0b1
		PWM.TCON |= (1 << 14);
		//7.第一个周期是开启手动加载TCNTB2和TCMPB2到递减计数器中
		//TCON[13] = 0b1 
		PWM.TCON |= (1 << 13);
		//8.开启自动加载  TCON[15] = 0b1
		PWM.TCON |= (1 << 15);
		//9.关闭手动加载   TCON[13] = 0b0
		PWM.TCON &= ~(1 << 13);
		//10.使能PWM定时器2  TCON[12] = 0b1 
		PWM.TCON |= (1 << 12);
		//	到此PWM控制器就可以产生一个方波,通过GPIOC14引脚输出。
	} else {
		PWM.TCON &= ~(1 << 15);	
		PWM.TCON &= ~(1 << 12);
		GPIOC.ALTFN0 &= ~(3 << 28);
		GPIOC.ALTFN0 |= (1 << 28);
		GPIOC.OUTENB |= (1 << 14);
		GPIOC.OUTENB &= (~(1 << 14));
	}
}

pwm.h
#ifndef __PWM_H__
#define __PWM_H__
#include "s5p6818_pwm.h"
typedef enum {
	OFF = 0,
	ON,
}pwm_stu;
void hal_pwm_init();
void hal_pwm_switch(int cnt, int cmp, pwm_stu st);

#endif // __PWM_H__
s5p6818_pwm.h
#ifndef ___S5P6818_PWM_H_
#define ___S5P6818_PWM_H_

/************* PWM ******************/
typedef struct {
	uint32 TCFG0;
	uint32 TCFG1;
	uint32 TCON;
	uint32 TCNTB0;
	uint32 TCMPB0;
	uint32 TCNTO0;
	uint32 TCNTB1;
	uint32 TCMPB1;
	uint32 TCNTO1;
	uint32 TCNTB2;
	uint32 TCMPB2;
	uint32 TCNTO2;
	uint32 TCNTB3;
	uint32 TCMPB3;
	uint32 TCNTO3;
	uint32 TCNTB4;
	uint32 TCNTO4;
	uint32 TINT_CSTAT;
}pwm;

#define PWM       (* (volatile pwm *)0xC0018000)


#endif

main.c
#include "pwm.h"
int main()
{
	hal_led_init();
	hal_pwm_init();
	while(1)
	{
		printf("pwm test!\n");
		hal_pwm_switch(299, 149, ON);
		delay_ms(1000);
		hal_pwm_switch(299, 149, OFF);
		delay_ms(1000);
	}
	return 0;
}
delay.c
#include "delay.h"

void delay_ms(unsigned int ms)
{
	unsigned int i,j;
	for(i = 0; i < ms; i++)
		for(j = 0; j < 1800; j++);
}

delay.h
#ifndef __DELAY_H__
#define __DELAY_H__

void delay_ms(unsigned int ms);

#endif //__DELAY_H__

8.下载调试。

下载调试请看这个帖子最后调试步骤。

  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值