(声明:该学习心得是本人通过学习周立功的相关资料后的个人理解后的笔记,由于本人水平有限,也许会有错误或是偏差,若想要保证准确无误,建议自己去下相关资料学习,本心得只供参考,若有错误之处,敬请指出,万分感谢。鉴于我所看的资料以前论坛里已有人上传过,故不再这里再次上传,想要的可以到论坛里找找,也可以到周立功网站去下载:http://www.zlgmcu.com/luminary/exploitation_guide.asp)
一.GPIO口
LM3S的GPIO口给我的第一个感受就是他的功能不像51那样的单一,用户可以通过改变他的配置来改变他的工作方式,也可以通过软件设置来改变他的作用,一个普通的IO口既可以用作普通IO口用,也可以通过软件设置为I2C,CAN等功能。
1.工作模式的多样化
常用的工作模式有:高阻输入,推挽输出,开漏输出。高阻输入具有很高的等效输入阻抗,他能将缓慢变化的或是畸变的输入信号整成比较理想的矩形信号。推挽输出和开漏输出结构差不多,只是推挽输出比开漏输出多出一个晶体管,还有一个就是开漏输出没有内部上拉,所以用的时候要外接一个上拉。该部分可以通过以下函数来设置。
(1)函数GPIOPinTypeGPIOInput( )
设置所选GPIO端口指定的管脚为高阻输入模式
void GPIOPinTypeGPIOInput(unsigned long ulPort, unsigned char ucPins)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
(2)函数GPIOPinTypeGPIOOutput( )
设置所选GPIO端口指定的管脚为推挽输出模式
GPIOPinTypeGPIOOutput(unsigned long ulPort, unsigned char ucPins)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
(3)函数GPIOPinTypeGPIOOutputOD( )
设置所选GPIO端口指定的管脚为开漏输出模式
GPIOPinTypeGPIOOutputOD(unsigned long ulPort, unsigned char ucPins)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
2.驱动能力的软件设置
在推挽输出的工作模式下,可以由用户设置输出电流为2mA,4mA,8mA,以及带转换速率控制的8mA驱动。该部分设置可以通过函数GPIOPadConfigSet( )来设置。
void GPIOPadConfigSet(unsigned long ulPort, unsigned char ucPins, unsigned long ulStrength, unsigned long ulPadType)
设置所选GPIO端口指定管脚的驱动强度和类型
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
ulStrength:指定输出驱动强度,应当取下列值之一:
GPIO_STRENGTH_2MA // 2mA驱动强度
GPIO_STRENGTH_4MA // 4mA驱动强度
GPIO_STRENGTH_8MA // 8mA驱动强度
GPIO_STRENGTH_8MA_SC // 带转换速率(Slew Rate)控制的8mA驱
ulPadType:指定管脚类型。应当取下列值之一:
GPIO_PIN_TYPE_STD // 推挽
GPIO_PIN_TYPE_STD_WPU // 带弱上拉的推挽
GPIO_PIN_TYPE_STD_WPD // 带弱下拉的推挽
GPIO_PIN_TYPE_OD // 开漏
GPIO_PIN_TYPE_OD_WPU // 带弱上拉的开漏
GPIO_PIN_TYPE_OD_WPD // 带弱下拉的开漏
GPIO_PIN_TYPE_ANALOG // 模拟比较器
3.管脚内部接有钳位二极管
GPIO口内接有钳位二极管,以保证电压不致与过大或过小,保证输入电压在3.9V以下。若想要提高IO口的电压,可以通过接一个二极管,然后再接一个上拉电阻后接5V,其电压可达到4.5V.
4.GPIO口的节能化
51的IO口是只要上电的话就会有点压,可以工作,但是LM3S的则要用户对GPIO口进行使能后才能工作,也就是说没有使能的GPIO口是不能工作的,这样做会增加使用的复杂度,但是在另一方面,就是由于这样的设置使得LM3S能达到很低的功耗。该部分可以通过函数SysCtlPeripheralEnable()来对所需的IO口进行使能。
6.GPIO口的读写操作
该部分可以通过以下函数来实现:
(1)函数GPIOPinWrite( )
向所选GPIO端口的指定管脚写入一个值,以更新管脚状态
void GPIOPinWrite(unsigned long ulPort, unsigned char ucPins, unsigned char ucVal)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
ucVal:写入指定管脚的值
(2)函数GPIOPinRead( )
读取所选GPIO端口指定管脚的值
long GPIOPinRead(unsigned long ulPort, unsigned char ucPins)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
对GPIO口的操作流程: (1)防止JTAG失效函数 (2)时钟初始化(设置LDO输出电压,系统时钟设置)(3)使能所要使用的IO口(4) 设置该IO口为输入还是输出 (5)然后就是对IO口的读写操作啦。
二.中断控制
1.使能GPIO口
方法如上面所示,使能要用的GPIO口,并设置为输入。
2.设置中断方式
中断方式分为边沿触发、电平触发两大类,共5种。使用函数GPIOIntTypeSet( )来进行设置。
设置所选GPIO端口指定管脚的中断触发类型
void GPIOIntTypeSet(unsigned long ulPort, unsigned char ucPins, unsigned long ulIntType)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
ulIntType:指定中断触发机制的类型,应当取下列值之一:
GPIO_FALLING_EDGE // 下降沿触发中断
GPIO_RISING_EDGE // 上升沿触发中断
GPIO_BOTH_EDGES // 双边沿触发中断(上升沿和下降沿都会触发中断)
GPIO_LOW_LEVEL // 低电平触发中断
GPIO_HIGH_LEVEL // 高电平触发中断
3.中断的使能(开中断)
(1)使能外设具体中断
使用函数GPIOPinIntEnable( )来实现。
使能所选GPIO端口指定管脚的中断
void GPIOPinIntEnable(unsigned long ulPort, unsigned char ucPins)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
(2)使能片内外设的总中断
使用函数IntEnable( )来实现
使能一个片内外设的中断
void IntEnable(unsigned long ulInterrupt)
ulInterrupt:指定被使能的片内外设中断
(3)使能处理器总中断
使用函数IntMasterEnable( )来实现
使能处理器中断
tBoolean IntMasterEnable(void)
4.编写中断服务函数
(1)中断函数的命名
命名方法有两种,一种是使用GCC下的标准名称,也就是说该中断函数的名字已经是规定好了的,只要拿了用就行。另一种是有用户命名,但是该种方法相对较复杂,需要对新命名的函数进行注册。
(2)中断函数的编写
进入中断函数后首先要进行的工作是对中断状态的查询。因为一个具体的片内外设可能存在多个子中断源,但是都共用同一个中断向量,所以通过查询来确定究竟是哪一个管脚发生了中断。
(2.1)中断查询函数GPIOPinIntStatus( )
获取所选GPIO端口所有管脚的中断状态
long GPIOPinIntStatus(unsigned long ulPort, tBoolean bMasked)
ulPort:所选GPIO端口的基址
bMasked:屏蔽标志,如果是true则返回屏蔽的中断状态,如果是false则返回原始的中断状态
(2.2)中断清除
在进入其中断服务函数后,中断状态并不能自动清除,为防止在退出中断服务函数时会立即再次触发中断而造成混乱,故需对中断进行清除。
中断清除函GPIOPinIntClear( )
清除所选GPIO端口指定管脚的中断
void GPIOPinIntClear(unsigned long ulPort, unsigned char ucPins)
ulPort:所选GPIO端口的基址
ucPins:指定管脚的位组合表示
5.中断优先级
可以通过软件来设置异常的优先级,称为软件优先级。它只可以改变可调整优先级的异常,即除了复位、NMI 和硬件故障异常外,其它中断的优先级都可以通过寄存器配置。异常一旦指定软件优先级后,硬件优先级则无效。软件优先级的设置对复位,NMI,和硬故障无效。它们的优先级始终比其他中断要高。复位(优先级-3),NMI(优先级-2),和硬故障(优先级-1)。用户可设置的最高优先级为0 号优先级,其仅次于复位,NMI 以及硬件故障的第4 优先级。
(1)中断方式
Cortex-M3 处理器其异常可以通过占先、末尾连锁和迟来等处理来降低中断的延迟。这四种方式最大的差别在于中断出现的时刻不同,具体区别如下表所示。
(2)中断优先级的设置
使用函数IntPrioritySet( )来管理一个片内外设的优先级。
函数IntPrioritySet( )
设置一个中断的优先级
void IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority)
ulInterrupt:指定的中断源,具体取值请参考表1.6的描述
ucPriority:要设定的优先级,应当取值(0~7) << 5,数值越小优先级越高
三.系统控制
1.LDO
LDO是“Low Drop-Out”的缩写,是一种线性直流电源稳压器。LDO的显著特点是输入与输出之间的低压差,能达到数百毫伏,而传统线性稳压器(如7805)一般在1.5V以上。外部输入的3.3V电压经过LDO后产生的2.5V电压为芯片内部供电。
LDO输出电压默认值是2.50V,通过软件可以在2.25~2.75V之间调节,步进50mV。通过函数SysCtlLDOSet( )进行设置。
函数SysCtlLDOSet( )
设置LDO的输出电压
void SysCtlLDOSet(unsigned long ulVoltage)
ulVoltage:要设置的LDO输出电压,应当取下列值之一:
SYSCTL_LDO_2_25V // LDO输出2.25V
SYSCTL_LDO_2_30V // LDO输出2.30V
....
2.时钟控制
LM3S615时钟来源是主振荡器(MOSC)或12MHz内部振荡器(IOSC),最终产生的系统时钟(System Clock)用Cortex-M3处理器内核以及大多数片内外设,PWM(脉宽调制)时钟在系统时钟基础上进一步分频获得,ADC(模-数换)时钟是恒定分频的16.667MHz输出(要求必须启用锁相环PLL)。
Sandstorm家族上电默认采用MOSC,如果不接晶振也不提供外部振荡信号输入,则无法启动。Fury和DustDevil家族上电默认采用IOSC,如果软件上没有配置MOSC,则外部晶振不会起振。
LM3S1138芯片的时钟系统要比LM3S615复杂些。时钟来源除了MOSC和IOSC以外,还可以是30KHz内部振荡器(INT30),以及来自冬眠模块的32.768kHz外部有源振荡器(EXT32)。ADC时钟有两个来源可以选择。
对于集成有冬眠模块(Hibernation Module)的型号(Sandstorm家族都没有冬眠模块),在冬眠备用电源管脚VBAT正常供电的情况下,可以从冬眠专用的晶振管脚XOSC0输入32.768KHz的外部有源振荡信号(不直接支持32.768KHz晶体)作为系统时钟源。
Stellaris系列ARM内部集成有一个PLL(Phase Locked Loop,锁相环)。PLL输出频率固定为400MH(Sandstorm家族为200MHz),误差±1%。如果选用PLL,则MOSC频率必须在3.579545~8.192MHz之间才能使PLL精确地输出400MHz。
注意:由于Cortex-M3内核最高运行频率为50MHz,因此如果要使用PLL,则至少要进行4以上的分频(硬件会自动阻止错误的软件配置)。启用PLL后,系统功耗将明显增大。
注意:在所有型号中,不论PLL输出是200MHz还是400MHz,只要分频数相同,则对PLL的分频结果都是一样的,统一按照200MHz进行计算。
时钟设置函数数SysCtlClockSet( )
系统时钟设置
void SysCtlClockSet(unsigned long ulConfig)
ulConfig:时钟配置字,应当取下列各组数值之间的“或运算”组合形式:
系统时钟分频值 SYSCTL_SYSDIV_1 // 振荡器不分频(不可用于PLL)
SYSCTL_SYSDIV_2 // 振荡器 2分频(不可用于PLL)
....
使用OSC还是PLL SYSCTL_USE_PLL // 采用锁相环PLL作为系统时钟源
SYSCTL_USE_OSC // 采用OSC(主振荡器或内部振荡器)作为系统时钟源
OSC时钟源选择 SYSCTL_OSC_MAIN // 主振荡器作为OSC
SYSCTL_OSC_INT // 内部12MHz振荡器作为OSC
SYSCTL_OSC_INT4 // 内部12MHz振荡器4分频后作为OSC
SYSCTL_OSC_INT30 // 内部30KHz振荡器作为OSC
SYSCTL_OSC_EXT32 // 外接32.768KHz有源振荡器作为OSC
外接晶体频率 SYSCTL_XTAL_1MHZ // 外接晶体 1MHz
SYSCTL_XTAL_1_84MHZ // 外接晶体 1.8432MHz
....
振荡源禁止 SYSCTL_INT_OSC_DIS // 禁止内部振荡器
SYSCTL_MAIN_OSC_DIS // 禁止主振荡器
注:禁止不用的振荡器可以节省功耗。为了能够使用外部时钟源,主振荡器必须被使能,试图禁止正在为芯片提供时钟的振荡器会被硬件阻止。
3.复位控制
复位分为:上电复位(POR),外部复位(EXT),软件复位(SW),看门狗复位(WDT),掉电复位(BOR),LDO复位(LDO)。
4.外设控制
Stellaris系列ARM所有片内外设只有在使能后才可以工作,如果直接对一个尚未使能的外设进行操作,则会进入硬故障中断。使能片内外设的函数是SysCtlPeripheralEnable( 。。如果一个片内外设暂时不被使用,则可以用函数SysCtlPeripheralDisable( )将其禁止,以节省功耗。
四.系统节拍定时
SysTick是一个简单的系统时钟节拍计数器(和51的计数器很像),它属于ARM Cortex-M3内核嵌套向量中断控制器NVIC里的一个功能单元,而非片内外设。可以作为定时器来使用。工作时每经过1个系统时钟周期,计数值就减1。计数到0时,SysTick计数器自动重装初值并继续运行,同时申请中断。
SysTick相对来说简单点,只要弄懂以下几个函数就会操作啦
(1)函数SysTickPeriodSet( )
设置SysTick计数器的周期值
void SysTickPeriodSet(unsigned long ulPeriod)
ulPeriod:是SysTick计数器每个周期的时钟节拍数,取值1~16777216
(2)函数SysTickEnable( )
使能SysTick计数器,开始倒计数
void SysTickEnable(void)
(3)函数SysTickIntEnable( )
使能SysTick中断
void SysTickIntEnable(void)
注:在SysTick中断服务函数SysTick_ISR( )里不需要进行对中断状态的读取和清除中断,因为硬件会自动清除SysTick中断状态
五.通用定时器
...请稍后