【北京迅为】iTOP-4412精英版使用手册-第六十一章 PWM操作
iTOP-4412开发板【精英版】搭载三星Exynos四核处理器,配备1GB内存,4GB固态硬盘EMMC存储,兼具快速读取与大容量,纵使海量思考也能及时处理。配备三星S5M8767电源管理。配备Android、Linux+Qt、Ubuntu操作系统,开启学习、研发的全新方式。Exynos4412开发板处理器成功应用于三星GALAXYS3,联想K860,魅族MX2等热门产品当中,并取得巨大成功。功耗控制以及强劲的性能一直为业内称道,超过5000万片的出货量,足以证明其稳定性与可用性。已成为三星官方推广的处理器之一,并承诺长期供货。
第六十一章 PWM操作
61.1 PWM定时器介绍
4412 时钟为我们提供了 PWM 定时器,在 4412 中共有 5 个 32 位的定时器,这些定时器可发送中断信号给 ARM 子系统。另外,定时器 0、1、2、3 包含了脉冲宽度调制,并可驱动其拓展的 I/O。PWM 对定时器 0 有可选的 dead-zone 功能,以支持大电流设备。要注意的是定时器 4 是内置不接外部引脚的。一般用于定时器功能。定时器 0 与定时器 1 共用一个 8位预分频器,定时器 2、定时器 3 与定时器 4 共用一另一个 8 位预分频器,每个定时器都有一个时钟分频器,时钟分频器有 5 种分频输出(1/2、1/4、 1/8 、1/16 和外部时钟 TCLK)。另外,定时器可选择时钟源,定时器 0-4 都可以选择外部的时钟源,如 PWM_TCLK。
当时钟被使能后,定时器计数缓冲寄存器(TCNTBn)把计数器初始值下载到递减计数器中。定时器比较缓冲寄存器(TCMPBn)把其初始值下载到比较寄存器中,并将该值与递减计数器的值进行比较。当递减计数器和比较寄存器值相同时,输出电平翻转。递减计数器减至 0 后,输出电平再次翻转,完成一个输出周期。这种基于 TCNTBn 和 TCMPBn 的双缓冲特性使定时器在频率和占空比变化时能产生稳定的输出。
每个定时器都有一个专用的由定时器时钟驱动的 16 位递减计数器。当递减计数器的计数值达到 0 时,就会产生定时器中断请求来通知CPU定时器操作完成。当定时器递减计数器达到0的时候,如果设置了 Auto-Reload 功能,相应的 TCNTBn 的值会自动重载到递减计数器中以继续下次操作。然而,如果定时器停止了,比如在定时器运行时清除 TCON 中定时器使能位,TCNTBn 的值不会被重载到递减计数器中。
TCMPBn 的值用于脉冲宽度调制(PWM)。当定时器的递减计数器的值和比较寄存器的值相匹配的时候,定时器控制逻辑将改变输出电平。因此,比较寄存器决定了 PWM 输出的开关时间。
PWM定时器的特点如下:
1)5个32位定时器;
2)2个8位 PCLK 分频器提供一级预分,5个2级分频器用来预分外部时钟;
3)可编程选择 PWM 独立通道。
4)4个独立的可编程的控制及支持校验的PWM通道。
5)静态配置:PWM 停止;
6)动态配置:PWM 启动;
7)支持自动重装模式及触发脉冲模式;
8)一个外部启动引脚。
9)两个 PWM 输出可带 Dead-Zone 发生器。
10)中断发生器。

61.2 PWM控制定时器实验
配置步骤:
1.GPD0_0 设置为 pwm 输出 GPD0CON[0]=0x02
2.TCFG0 预分频(1-255)
3.TCFG1 分频(1.2.4.8.16)
4.设置占空比:TCMPB0 和 TCNTB0(TCMPB0<TCNTB0)
5.设置自动重载,开启定时器等
6.TCON 寄存器实验代码:
实验代码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
//#include <mach/gpio-bank.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
//#include "gps.h"
#include <linux/delay.h>struct {
unsigned int TCFG0;
unsigned int TCFG1;
unsigned int TCON;
unsigned int TCNTB0;
unsigned int TCMPB0;
unsigned int TCNTO0;
unsigned int TCNTB1;
unsigned int TCMPB1;
unsigned int TCNTO1;
unsigned int TCNTB2;
unsigned int TCMPB2;
unsigned int TCNTO2;
unsigned int TCNTB3;
unsigned int TCMPB3;
unsigned int TCNTO3;
unsigned int TCNTB4;
unsigned int TCNTO4;
unsigned int TINT_CSTAT;
}*PWM;volatile unsigned long virt_addr,virt_addr_gpio,phys_addr,phys_addr_gpio;//用于存放虚拟地址和物理地址
volatile unsigned long *GPD0CON,*GPD0PUD;void addr_init(void)
{
phys_addr = 0x139D0000;
virt_addr = (unsigned long)ioremap(phys_addr,0x32);
PWM = (unsigned long*)(virt_addr+0x00);
phys_addr_gpio = 0x11400000+0xA0;
virt_addr_gpio = (unsigned long)ioremap(phys_addr_gpio,0x10);
GPD0CON = (unsigned long*)(virt_addr_gpio+0x00);
GPD0PUD = (unsigned long*)(virt_addr_gpio+0x00A8-0x00A0);
}void pwm_init(void)
{
addr_init();
*GPD0CON = *GPD0CON&(~(0xf))|0x2;
*GPD0PUD = *GPD0PUD&(~(0xf));
//预分频 1-254 + 1
(*PWM).TCFG0 = (*PWM).TCFG0 &(~(0xff))|0xf9;
//分频 1.2.4.8.16
(*PWM).TCFG1 = (*PWM).TCFG1 &(~(0xf))|0x2;
//设置占空比
(*PWM).TCMPB0 = 50;
(*PWM).TCNTB0 = 100;
//设置手动加载,开启定时器
(*PWM).TCON = (*PWM).TCON & (~(0xf)) | 0x1 | 0x2;
}static void beep_on(void)
{
//开启自动重载
(*PWM).TCON = (*PWM).TCON & (~(0xf)) | 0x1 | 0x8;
}static int iTop4412_PWM_init(void)
{
pwm_init();
beep_on();
return 0;
}static void beep_off(void)
{
(*PWM).TCON = (*PWM).TCON & (~(0xf)) | 0x0;
//定时器结束之后,输出的是高电平还是低电平?
*GPD0CON = *GPD0CON&(~(0xf))|0x0;
}
static void iTop4412_PWM_exit(void)
{
beep_off();
}module_init(iTop4412_PWM_init);
module_exit(iTop4412_PWM_exit);
MODULE_LICENSE("GPL");代码分析:
1.开启自动重载
2.设置 TCNTBn 和 TCMPBn 寄存器
3.手动设置
4.设置自动翻转,更新 TCNTBn 和 TCMPBn 寄存器
5.再次设置 TCNTBn 和 TCMPBn 寄存器(双缓冲再次更新)
6.定时器开启
7.TCNTBn--,TCNTBn=TCMPBn,翻转
8.TCNTn=0,产生中断
9.自动重载
10.TCNTBn--,TCNTBn=TCMPBn,翻转
11.TCNTn=0,产生中断
12.自动重载,产生中断。然后关闭自动重载
13.TCNTBn--,TCNTBn=TCMPBn,翻转
14.TCNTn=0,关闭自动重载,不再产生中断
15.自动重载关闭,停止。
