1. Buzzer例程控制原理

由ARM1138原理图可得:Buzzer使用CCP3(对应GPIO-G组0x40026000,4号引脚0x00000010)作为输入引脚;

Buzzer例程结构

涉及的库函数使用绿色粗体表示

SysCtlPeripheralEnable(KEY_PERIPH);  当多个管脚处于同一个端口时,使能单个端口(设备的基地址 SYSCTL_PERIPH_I2C1 、 SYSCTL_PERIPH_PWM 、 SYSCTL_PERIPH_QEI0)

SysCtlPeripheralDisable(KEY_PERIPH);  禁止一个外设(设备的基地址)

GPIOPinTypeGPIOInput(KEY_PORT , KEY_PIN);  设置引脚为输入状态(端口基地址+偏移地址)

GPIOPinRead(KEY_PORT , KEY_PIN);  读取指定管脚上出现的值(端口基地址+偏移地址) 

下面以SysCtlPeripheralDisable(unsigned long ulPeripheral);分析一下函数工作原理(寄存器地址映射原理):

核心的宏:HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) &= ~SYSCTL_PERIPH_MASK(ulPeripheral)

我们以本例中KEY_PERIPH(实际上是SYSCTL_PERIPH_GPIOG)为参数进行说明:如下可见它的值为0x20000040,

等式的左边:

1) 经过第一个宏处理取得上值的高四bits即0x2; (其实是将内存分为8个256M的内存块来管理,看目标寄存器是处于哪一个内存块中);

2) 经过第二个宏处理取得值 SYSCTL_RCGC20x400FE108 列出的偏移量是相对于0x400F.E000的系统控制基址的寄存器地址的十六进制增量。 )即;通过RCGC2寄存器对目标设备进行控制;(每个内存块对应其自己的配置寄存器)

3) 经过第三个宏(*((volatile unsigned long *)(x))),即指向了寄存器RCGC2的空间

等式右边:~(((0x20000040) & 0xffff) << (((0x20000040) & 0x001f0000) >> 16)) = 0xffffffbf (有效的是bf -> 10111111)

为了更好理解右式引入Enable的核心宏表达式

HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) |= SYSCTL_PERIPH_MASK(ulPeripheral);

(((0x20000040) & 0xffff) << (((0x20000040) & 0x001f0000) >> 16)) = 0x00000040 (有效位40-> 01000000)

让我想起了常用的“&=”(某位置0,其余位不变) 还有 “|=”(某位置1,其余位不变)

综上:disable相应外设即是通过配置运行模式下的寄存器RCGC2。同时得 0x20000040 前1字节是为了分块,后2字节是为了配置寄存器的值。

不过前第二字节是为了什么?关键是弄明白这句的意思(((0x20000040) & 0x001f0000) >> 16)? 

然后通过查阅《lm3s1138》的数据手册中对RCGC2寄存器的描述,即可明白整个函数的控制过程。

void SysCtlPeripheralDisable(unsigned long ulPeripheral)
{
//
// Check the arguments.
//
ASSERT((ulPeripheral == SYSCTL_PERIPH_ADC) ||
(ulPeripheral == SYSCTL_PERIPH_CAN0) ||
(ulPeripheral == SYSCTL_PERIPH_CAN1) ||
(ulPeripheral == SYSCTL_PERIPH_CAN2) ||
(ulPeripheral == SYSCTL_PERIPH_COMP0) ||
(ulPeripheral == SYSCTL_PERIPH_COMP1) ||
(ulPeripheral == SYSCTL_PERIPH_COMP2) ||
(ulPeripheral == SYSCTL_PERIPH_ETH) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOA) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOB) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOC) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOD) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOE) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOF) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOG) ||
(ulPeripheral == SYSCTL_PERIPH_GPIOH) ||
(ulPeripheral == SYSCTL_PERIPH_HIBERNATE) ||
(ulPeripheral == SYSCTL_PERIPH_I2C0) ||
(ulPeripheral == SYSCTL_PERIPH_I2C1) ||
(ulPeripheral == SYSCTL_PERIPH_PWM) ||
(ulPeripheral == SYSCTL_PERIPH_QEI0) ||
(ulPeripheral == SYSCTL_PERIPH_QEI1) ||
(ulPeripheral == SYSCTL_PERIPH_SSI0) ||
(ulPeripheral == SYSCTL_PERIPH_SSI1) ||
(ulPeripheral == SYSCTL_PERIPH_TIMER0) ||
(ulPeripheral == SYSCTL_PERIPH_TIMER1) ||
(ulPeripheral == SYSCTL_PERIPH_TIMER2) ||
(ulPeripheral == SYSCTL_PERIPH_TIMER3) ||
(ulPeripheral == SYSCTL_PERIPH_UART0) ||
(ulPeripheral == SYSCTL_PERIPH_UART1) ||
(ulPeripheral == SYSCTL_PERIPH_UART2) ||
(ulPeripheral == SYSCTL_PERIPH_UDMA) ||
(ulPeripheral == SYSCTL_PERIPH_USB0) ||
(ulPeripheral == SYSCTL_PERIPH_WDOG)); //
// Disable this peripheral.
//
HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) &=
~SYSCTL_PERIPH_MASK(ulPeripheral);
} /**************************************************************/ //***********************************************
//
// This macro extracts the array index out of the peripheral number.
//
//***********************************************
#define SYSCTL_PERIPH_INDEX(a) (((a) >> 28) & 0xf) /**************************************************************/ static const unsigned long g_pulRCGCRegs[] =
{
SYSCTL_RCGC0,
SYSCTL_RCGC1,
SYSCTL_RCGC2
}; /**************************************************************/ #define HWREG(x) \
(*((volatile unsigned long *)(x)))
...... /**************************************************************/ #define SYSCTL_PERIPH_MASK(a) (((a) & 0xffff) << (((a) & 0x001f0000) >> 16)) /**************************************************************/
#define SYSCTL_PERIPH_WDOG 0x00000008 // Watchdog
#define SYSCTL_PERIPH_HIBERNATE 0x00000040 // Hibernation module
#define SYSCTL_PERIPH_ADC 0x00100001 // ADC
#define SYSCTL_PERIPH_PWM 0x00100010 // PWM
#define SYSCTL_PERIPH_CAN0 0x00100100 // CAN 0
#define SYSCTL_PERIPH_CAN1 0x00100200 // CAN 1
#define SYSCTL_PERIPH_CAN2 0x00100400 // CAN 2
#define SYSCTL_PERIPH_UART0 0x10000001 // UART 0
#define SYSCTL_PERIPH_UART1 0x10000002 // UART 1
#define SYSCTL_PERIPH_UART2 0x10000004 // UART 2
#ifndef DEPRECATED
#define SYSCTL_PERIPH_SSI 0x10000010 // SSI
#endif
#define SYSCTL_PERIPH_SSI0 0x10000010 // SSI 0
#define SYSCTL_PERIPH_SSI1 0x10000020 // SSI 1
#ifndef DEPRECATED
#define SYSCTL_PERIPH_QEI 0x10000100 // QEI
#endif
#define SYSCTL_PERIPH_QEI0 0x10000100 // QEI 0
#define SYSCTL_PERIPH_QEI1 0x10000200 // QEI 1
#ifndef DEPRECATED
#define SYSCTL_PERIPH_I2C 0x10001000 // I2C
#endif
#define SYSCTL_PERIPH_I2C0 0x10001000 // I2C 0
#define SYSCTL_PERIPH_I2C1 0x10004000 // I2C 1
#define SYSCTL_PERIPH_TIMER0 0x10100001 // Timer 0
#define SYSCTL_PERIPH_TIMER1 0x10100002 // Timer 1
#define SYSCTL_PERIPH_TIMER2 0x10100004 // Timer 2
#define SYSCTL_PERIPH_TIMER3 0x10100008 // Timer 3
#define SYSCTL_PERIPH_COMP0 0x10100100 // Analog comparator 0
#define SYSCTL_PERIPH_COMP1 0x10100200 // Analog comparator 1
#define SYSCTL_PERIPH_COMP2 0x10100400 // Analog comparator 2
#define SYSCTL_PERIPH_GPIOA 0x20000001 // GPIO A
#define SYSCTL_PERIPH_GPIOB 0x20000002 // GPIO B
#define SYSCTL_PERIPH_GPIOC 0x20000004 // GPIO C
#define SYSCTL_PERIPH_GPIOD 0x20000008 // GPIO D
#define SYSCTL_PERIPH_GPIOE 0x20000010 // GPIO E
#define SYSCTL_PERIPH_GPIOF 0x20000020 // GPIO F
#define SYSCTL_PERIPH_GPIOG 0x20000040 // GPIO G
#define SYSCTL_PERIPH_GPIOH 0x20000080 // GPIO H
#define SYSCTL_PERIPH_UDMA 0x20002000 // uDMA
#define SYSCTL_PERIPH_USB0 0x20100001 // USB0
#define SYSCTL_PERIPH_ETH 0x20105000 // ETH
#define SYSCTL_PERIPH_IEEE1588 0x20100100 // IEEE1588
#define SYSCTL_PERIPH_PLL 0x30000010 // PLL
#define SYSCTL_PERIPH_TEMP 0x30000020 // Temperature sensor
#define SYSCTL_PERIPH_MPU 0x30000080 // Cortex M3 MPU

  

(1)JTAG_Wait();  //防止JTAG失效;按住KEY2然后复位,程序会进入死循环。

防止JTAG失效这句话真是太含蓄了(很烦这个词,刚开始被说得云里雾里的),其实就是防止JTAG管脚被复用为GPIO管脚时在某些特定情况(详见手册)下被锁死(无法下载程序)的情况。关于防锁死程序原理:http://blog.163.com/liyupeng_china/blog/static/18464392820125199343114/

注意:由于所有的位都在复位时都会清零,因此在默认的情况下,这些GPIO线路设置GPIO模式。所以为保险起见,应加入下面的代码。以等待速度较慢的JTAG先对相应的GPIO复用脚设置为JTAG的模式。

void JTAG_Wait(void)
{
SysCtlPeripheralEnable(KEY_PERIPH); //使能KEY所在的GPIO端口,从刚才的分析即是使RCGC2 GPIOG位置1
GPIOPinTypeGPIOInput(KEY_PORT , KEY_PIN); // 设置KEY所在管脚为输入
if ( GPIOPinRead(KEY_PORT , KEY_PIN) == 0x00 ) // 如果复位时按下KEY,则进入
{
for (;;); // 死循环,以等待JTAG连接
}
SysCtlPeripheralDisable(KEY_PERIPH); // 禁止KEY所在的GPIO端口,使RCGC2 GPIOG位置0
}

  

(2)SystemInit();

下面分析一下下面的初始化函数都干了什么事(前3个函数)。

1.SysCtlLDOSet(); 控制LDO

LDO的作用:查了好些资料,也没弄明白LDO在1138中的具体作用,如果只是稳压,那么输出2.5V电压是做什么的?

2.SysCtlClockSet(); 设置系统时钟

ulConfig 参数是几个不同值的逻辑或,这些值中的某些值组合成组,其中只有一组值能被选用。

1)系统时钟分频器:SYSCTL_SYSDIV_1、SYSCTL_ SYSDIV_2、SYSCTL_SYSDIV_3 、 …、SYSCTL_SYSDIV_64 (在 Sandstorm-class 器 件 中 , 只 有SYSCTL_SYSDIV_1 到 SYSCTL_SYSDIV_16 是有效的。)

2)外部晶体频率:SYSCTL_XTAL_1MHZ 、SYSCTL_XTAL_1_84MHZ 、 SYSCTL_XTAL_2MHZ 、 SYSCTL_XTAL_2_45MHZ 、SYSCTL_XTAL_3_57MHZ 、 SYSCTL_XTAL_3_68MH 、 SYSCTL_XTAL_4MHZ 、SYSCTL_XTAL_4_09MHZ 、 SYSCTL_XTAL_4_91MHZ 、 SYSCTL_XTAL_5MHZ 、SYSCTL_XTAL_5_12MHZ 、 SYSCTL_XTAL_6MHZ 、 SYSCTL_XTAL_6_14MHZ 、SYSCTL_XTAL_7_37MHZ 、 SYSCTL_XTAL_8MHZ 、 SYSCTL_XTAL_8_19MHZ 、SYSCTL_XTAL_10MHZ 、 SYSCTL_XTAL_12MHZ 、 SYSCTL_XTAL_12_2MHZ 、SYSCTL_XTAL_13_5MHZ 、 SYSCTL_XTAL_14_3MHZ 、 SYSCTL_XTAL_16MHZ 或SYSCTL_XTAL_16_3MHZ (低于 SYSCTL_XTAL_3_57MHZ 的值在 PLL 被操作时无效。在Sandstorm-class 和 Fury-class 器件中,高于 SYSCTL_XTAL_8_19MHZ 的值是无效的。)

3)振荡器源:SYSCTL_OSC_MAIN 、 SYSCTL_OSC_INT 、SYSCTL_OSC_INT4、SYSCTL_OSC_INT30 或 SYSCTL_OSC_EXT32 (在 Standstorm-class器件中,SYSCTL_OSC_INT30 和 SYSCTL_OSC_EXT32 是无效的。SYSCTL_OSC_EXT32只可用于具有休眠模式的器件,并只在休眠模块已被使能时有效。)

使用 SYSCTL_USE_OSC | SYSCTL_OSC_MAIN 来选择由主振荡器提 供 系 统 时 钟 。 为 了 使 系 统 时 钟 由 PLL 来 提 供 , 请 使 用 SYSCTL_USE_PLL |SYSCTL_OSC_MAIN,并根据 SYSCTL_XTAL_xxx 值选择合适的晶体。

3.SysCtlClockGet(); 获取系统时钟

void  SystemInit(void)
{
SysCtlLDOSet(SYSCTL_LDO_2_50V); // 设置LDO输出电压 SysCtlClockSet(SYSCTL_USE_OSC | // 系统时钟设置,采用主振荡器
SYSCTL_OSC_MAIN |
SYSCTL_XTAL_6MHZ |
SYSCTL_SYSDIV_1); TheSysClock = SysCtlClockGet(); // 获取系统时钟,单位:Hz BuzzerInit(); // 蜂鸣器初始化
}
void  BuzzerInit(void)
{
SysCtlPeriEnable(CCP3_PERIPH); // 使能CCP3所在的GPIO端口(GPIOG)
GPIOPinTypeTimer(CCP3_PORT , CCP3_PIN); // 配置CCP3所在管脚(G4)为Timer功能(定时器1 TimerB) SysCtlPeriEnable(SYSCTL_PERIPH_TIMER1); // 使能TIMER1模块 TimerConfigure(TIMER1_BASE , // 配置Timer1B为16位PWM
TIMER_CFG_16_BIT_PAIR | TIMER_CFG_B_PWM);
}

1138芯片资料有关定时器的设置过程:

(3)具体功能实现

ARM1138@PWM例程分析的更多相关文章

  1. Video Processing subsystem例程分析

    Video Processing subsystem例程分析 1.memory_ss模块 slave端口: S00: 连接设备: microblaze_ss----M_AXI_DC 时钟来源: S01 ...

  2. linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】

    转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等. 用户空间函数原型:int ioctl(int f ...

  3. 2.1 摄像头V4L2驱动框架分析

    学习目标:学习V4L2(V4L2:vidio for linux version 2)摄像头驱动框架,分析vivi.c(虚拟视频硬件相关)驱动源码程序,总结V4L2硬件相关的驱动的步骤:  一.V4L ...

  4. FPGA实战操作(2) -- PCIe总线(例程设计分析)

    1.框架总览 平台:vivado 2016.4 FPGA:A7 在实际应用中,我们几乎不可能自己去编写接口协议,所以在IP核的例程上进行修改来适用于项目是个不错的选择. 通过vivado 中有关PCI ...

  5. [nRF51822] 14、浅谈蓝牙低功耗(BLE)的几种常见的应用场景及架构(科普类干货)

    蓝牙在短距离无线通信领域占据举足轻重的地位—— 从手机.平板.PC到车载设备, 到耳机.游戏手柄.音响.电视, 再到手环.电子秤.智能医疗器械(血糖仪.数字血压计.血气计.数字脉搏/心率监视器.数字体 ...

  6. 浅谈蓝牙低功耗(BLE)的几种常见的应用场景及架构(转载)

    转载来至beautifulzzzz,网址http://www.cnblogs.com/zjutlitao/,推荐学习 蓝牙在短距离无线通信领域占据举足轻重的地位—— 从手机.平板.PC到车载设备, 到 ...

  7. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  8. 《Linux程序设计》--读书笔记---第十三章进程间通信:管道

    管道:进程可以通过它交换更有用的数据. 我们通常是把一个进程的输出通过管道连接到另一个进程的输入: 对shell命令来说,命令的连接是通过管道字符来完成的: cmd1    |     cmd2 sh ...

  9. 初解DLL基本知识

    1.DLL基本理论 在Windows操作系统中,几乎所有的内容都是以DLL的形式存在的. 1.DLL基本概念 语言程序要从目标代码(.obj)外部引用函数,可以通过俩种途径实现——静态链接和动态链接. ...

随机推荐

  1. Xlistview的values下的界面

    <!-- 下拉刷新,上拉加载更多 -->    <string name="xlistview_header_hint_normal">下拉刷新</s ...

  2. Git搭建团队开发环境操作演练

    模拟创建远程git仓库 1.首先创建如下目录结构: /Users/hujh/Desktop/GitTest2/GitServer/weibo weibo是我们要创建的项目 2.切换目录 $ cd /U ...

  3. 根据username查找user

    返回的是一个list<User>,不过验证密码的时候,要求返回是一个user对象,如果用uniqueresult,这个是过时的方法,如果用getResultList 会得到一个列表,get ...

  4. objectARX 获取ucs的X方向

    struct resbuf var; acedGetVar(_T("UCSXDIR"), &var);//获取用户坐标系下X方向量 ver = asVec3d(var.re ...

  5. hdu 2047

    PS:又是上课偷懒..去递推.. 代码: #include "stdio.h"#include "math.h"long long dp[55];long lo ...

  6. UIkit框架之UItextfield

    1.继承链:UIcontrol:UIview:UIresponder:NSObject 2.成为第一响应者:[text becomeFirstResponder];  //让该文本成为第一响应者 3. ...

  7. 偶遇makeblock

    上周出去吃饭在公交站牌上看到一家叫“创客工场”的公司在打招聘广告,当时在想这公司有钱啊,广告都打到这儿了,也没细想让韩总扫了一下他们的二维码,回来搜了一下这个公司,我靠,是做开源硬件的:再一看各种机器 ...

  8. 开源软件项目管理系统招设计/开发。。。。。Zend Framework2架构 svn://735.ikwb.com/pms

    开源软件项目管理系统招设计/开发.....Zend Framework2架构svn://735.ikwb.com/pms

  9. windows 命令修改IP

    修改ip: netsh -c interface ip set address name="本地连接" source=static addr=192.168.11.100 mask ...

  10. Android白天/夜间模式Day/Night Mode标准原生SDK实现

     Android白天/夜间模式Day/Night Mode标准原生SDK实现 章节A:Android实现白天/夜间模式主要控制器在于UiModeManager,UiModeManager是Andr ...