关于lm3s811代码全解析_第1页
关于lm3s811代码全解析_第2页
关于lm3s811代码全解析_第3页
关于lm3s811代码全解析_第4页
关于lm3s811代码全解析_第5页
已阅读5页,还剩112页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

*注:未指明返回值的函数为无返回值,资源来自周立功单片机网站

一:GPIO函数

1:voidGPIODirModeSet(unsignedlongulPort,unsignedcharucPins,

unsignedlongulPinlO)

设置所选GPIO端口指定管脚的方向和模式

如GPIODirModeSe(GPIO_PORTA_BASE,GPIO_PIN_2,GPIO_DIR_MODE_IN)函

数设置PA2为输入,但第三个参数为KGPIO_DIR_MODE_HW//硬件控制”时指此

管脚启用第二功能;

2:unsignedlongGPIODirModeGet(unsignedlongulPort,unsignedchar

ucPin)

获取所选GPIO端口指定管脚的方向和模式

如unsignedlongSetValue=GPIODirModeGet(GPIO_PORTA_BASE,GPIO_PIN_2);

返回PA2脚的方向和模式,返回的值为上一个函数第三个参数的取值,分别为

GPIO-DIR_MODE_IN//输入方向

GPI0-DIR-M0DE_0UT//输出方向

GPI0_DIR_M0DE_HW//硬件控制

3:voidGPIOPadConfigSet(unsignedlongulPort,

unsignedcharucPins,

unsignedlongulStrength,

unsignedlongulPadType)

设置所选GPIO端口指定管脚的驱动强度和类型

如GPIOPadConfigSet(GPIO_PORTA_BASE,GPIO-PIN.2,

GPIO-STRENGTH_4MA,GPIO-PIN_TYPE_STD)设置PA2脚的驱动强度为4MA的推

挽输出;

ulStrength:指定输出驱动强度,应当取下列值之一:

GPI0-STRENGTH_2MA//2mA驱动强度

GPI0.STRENGTH_4MA//4mA驱动强度

GP10_STRENGTH_8MA//8mA驱动强度

GPI0_STRENGTH_8MA_SC//带转换速率(SlewRate)控制的8mA驱动

ulPadType:指定管脚类型。应当取下列值之一:

GPTO-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//带弱下拉的开漏

GP1O_PIN_TYPE_ANALOG//模拟比较器

4:voidGPIOPadConfigGet(unsignedlongulPort,

unsignedcharucPin,

unsignedlong*pulStrength,

unsignedlong*pulPadType)

获取所选GPIO端口指定管脚的配置信息

如GPIOPadConfigGet(GPIO-PORTA-BASE,GPIO-PIN_2,pulStrength,

pulPadType);输出驱动强度信息保存到pulStrength指向的地址中,输出驱动

类型信息保存到pulPadType指向的地址中,返回的值为上一个函数设置的内容。

5:voidGPIOPinTypeGPIOInput(unsignedlongulPort,unsignedchar

ucPins)

设置所选GPIO端口指定的管脚为高阻输入模式

如GPIOPinTypeGPIOInput(GPIO-PORTA.BASE,GPIO-PIN.2);设置PA2脚为

高阻输入模式

6:voidGPIOPinTypeGPIOOutput(unsignedlongulPort,unsignedchar

ucPins)

设置所选GPIO端口指定的管脚为推挽输出模式

如GPIOPinTypeGPIOOutput(GP1O_PORTA_BASE,GP1O_PIN_2)设置PA2脚为

推挽输出模式

7:voidGPIOPinTypeGPIOOutputOD(unsignedlongulPort,unsignedchar

ucPins)

设置所选GPIO端口指定的管脚为开漏输出模式

如GPIOPinTypeGPIOOutputOD(GPIO_PORTA_BASE,GPIO_PIN_2)设置PA2为

开漏输出模式

但由于函数5,6,7函数名太长一般做如下简化:

#defineGPIOPinTypelnGPIOPinTypeGPIOInput

#defineGPIOPinTypeOutGPIOPinTypeGPIOOutput

#defineGPIOPinTypeODGPIOPinTypeGPIOOutputOD

8:voidGPIOPinTypeADC(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为ADC功能

这个函数只对有adc功能复用的管脚有用如LM3s811的1,2,3,4脚。。

9:voidGPIOPinTypeCAN(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为CAN功能

10:voidGPIOPinTypeComparator(unsignedlongulPort,unsignedchar

ucPins)

设置所选GPIO端口指定的管脚为CAN功能

11:voidGPIOPinTypeComparator(unsignedlongulPort,unsignedchar

ucPins)

设置所选GPIO端口指定的管脚为模拟比较器功能

12:voidGPIOPinTypeI2C(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为12c功能

13:voidGPIOPinTypePWM(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为PWM功能

14:voidGPIOPinTypeQEI(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为QEI功能

15:voidGPIOPinTypeSSI(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为SSI功能

16:voidGPIOPinTypeTimer(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为Timer的CCP功能

17:voidGPIOPinTypeUART(unsignedlongulPort,unsignedcharucPins)

设置所选GPIO端口指定的管脚为UART功能

18:voidGPIOPinTypeUSBDigital(unsignedlongulPort,unsignedchar

ucPins)

设置所选GPIO端口指定的管脚为USB数字功能

对GPIO管脚的读写操作是通过函数GPIOPinWrite()和GPIOPinRead()

实现的,这是两个非常重要而且很常用的库函数。

19:voidGPIOPinWrite(unsignedlongulPort,unsignedcharucPins,

unsignedcharucVa1);

向所选GPIO端口的指定管脚写入一个值,以更新管脚状态,ucVal:写入

指定管脚的值

注:ucPins指定的管脚对应的ucVal当中的位如果是1,则置位相应的管

脚,如果是0,则清零相应的管脚;ucPins未指定的管脚不受影响。

如GPIOPinWrite(GPIO-PORTA_BASE,GPIO-PIN.3,0x00);//清除PA3

GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_5,OxFF);//置位PB5

GPIOPinWrite(GPIO_PORTD_BASE,GPIO-PIN-2|GPIO-PIN_6,OxFF);//同

时置位PD2、PD6

GPTOPinWrite(GPIO-PORTA_BASE,OxFF,ucData);//变量ucData输出到

PA0-PA7

20:longGPIOPinRead(unsignedlongulPort,unsignedcharucPins)

读取所选GPIO端口指定管脚的值,返回1个位组合的字节。该字节提供了

由ucPins指定管脚的状态,对应的位值表示GPIO管脚的高低状态。ucPins未

指定的管脚位值是0。返回值已强制转换为long型,因此位31:8应该忽略。这

个函数应该在相应管脚已经设置为输出状态的情况下,由于GPIO得管脚结构我

们知道在输出模式下,不管是开漏还是推挽用此函数读回来的值都是管脚的输出

锁存值,

如//读取PA4,返回值保存在ucData里,可能的值是0x00或0x10

ucData=GPIOPinRead(GPIO_PORTA_BASE,GPI0_PIN_4);

//同时读取PB1、PB2和PB6,返回PBLPB2和PB6的位组合保存在ucData

ucData=GPIOPinRead(GPIO-PORTB.BASE,GPIO-PIN.l|GPIO-PTN.2I

GPIO-PIN-6);

//读取整个PF端口

ucData=GPIOPinRead(GPIO-PORTF.BASE,OxFF);

在Stellaris系列ARM里,每个GPIO管脚都可以作为外部中断输入。中

断的触发类型分为边沿触发和电平触发两大类,共5种,用起来非常灵活。配

置GPIO管脚的中断触发方式可以通过调用函数GPIOIntTypeSet()来实现,函

数GPIOlntTypeGet()用来获取配置情况。函数GPIOPinlntEnable()和

GPIOPinIntDisable()用来使能和禁止GPIO管脚中断。函数

GPIOPinIntStatus()用来获取GPIO管脚的中断状态.在同一个GPIO端口上,

8个GPIO管脚的中断向量都是共用的。如果同时配置了同一端口上的多个管脚

中断,则可以先利用函数GPIOPinIntStatus()读取中断状态,再进一步确认

具体是哪个管脚产生的中断请求。函数GPIOPinIntClear()用来及时清除GPIO

管脚的中断状态。函GPIOPortIntRegister()用来注册一个GPIO端口中断服务

函数,而注销的方法是调用函数GPlOPortlntUnregister()。

2012CSDN网站六大类职位火热招聘中!点击了解英特尔云计算2012年1月当

选微软MVP的CSDN会员名单揭晓!

Im3s811学习笔记(四)[gpio]

分类:cortexm32011-08-0315:24295人阅读评论(0)收藏举报

今天主要是熟悉下gpio的一些应用。最简单的就是LED灯的控制。

下面的例子就拿L5来说明吧。

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//enablegpiob

GPIOPinTypeGPIOOutput(GPIO-PORTB-BASE,GPIO-PIN-O);//setPBOoutput

还有一种模式设置的方法GPIODirModeSet(GPIO_PORTB_BASE,GPIO_PIN_0,

GPIO_DIR_MODE_OUT);//这个方案可以设置多个引脚,参数2为位引脚的或

控制LED灯地亮灭,就是往引脚写入值

ledstatus=GPIOPinRead(GPIO_PORTD_BASE,GPIO_PIN_0);

GPIOPinWrite(GPIO-PORTD.BASE,GPIO-PIN_0,GPIO-PIN_0&Cledstatus));

上面的程序是读取L5对应管脚的值,然后使灯地状态进行翻转。

这里说下GPIOPinWriteO该函数的用法。

GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_1,GPIO_PIN_1);

GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_1,_GPIO_PIN_1);

例程上常用上面的方法。主要也就是你要让哪个管脚置一,参数3的值中管脚对

应的位必须置一。

如下各条指令都能点亮响应端口(假设已经都定义成输出了)。

GPIOPinWrite(GPIO-PORTD-BASE,GPIO-PIN-O,1);

GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_1,2);

GPIOPinWrite(GPIO-PORTD.BASE,GPIO-PIN.2,4);

GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_3,8);

GPIOPinWrite(GPIO-PORTD.BASE,GPIO-PIN.4,0x10);

GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_5,0x20);

GPIOPinWrite(GPIO-PORTD.BASE,GPIO-PIN.6,0x40);

GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_7,0x80);

下面我主要讲述下键控LED的流程,其实就是利用按键中断控制灯的亮灭。

首先是配置KEY。

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);//EnableGPIOC

GPIOPinIntEnable(GPIO-PORTC-BASE,GPIO-PIN.4);//EnableGPIOCpin4

GPIOPinTypeGPIOInput(GPIO_PORTC_BASE,GPI0_PIN_4);//setthepinmodeis

input

GPIOIntTypeSet(GPIO-PORTC-BASE,GPIO_PIN_4,GPIO_LOW_LEVEL);//set

interrupttypeislowFallingedge

IntEnable(INT-GPIOC);//enableGPIOCinterrupt

下面是按键中断的处理函数

voiduserkey-handler(void)

(

unsignedcharucVal;

unsignedlongulStatus;

ulStatus=GPIOPinlntStatus(GPIO_PORTC_BASE,true);//getgpioc

interruptstatus

GPIOPinlntClear(GPIO_PORTC_BASE,ulStatus);//clearinterruptstatus

if(ulStatus&GPIO-PIN_4)//如果KEY的中断状态有效

ucVal=GPIOPinRead(GPIO-PORTD_BASE,GPIO_PIN_0);//翻转LED

GPIOPinWrite(GPIO-PORTD_BASE,GPIO-PIN-O,~ucVal);

SysCtlDelay(10*(SysCtIClockGet0/3000));//延时约)0ms,消除按键

抖动

while(GPIOPinRead(GPIO-PORTC.BASE,GPIO_PIN_4)==0x00);//等待KEY

抬起

SysCtlDelay(10*(SysCtIClockGet0/3000));//延时约10ms,消除松键

抖动

)

)

既然用到了SysCtlDelayO函数。在这里也顺道分析下。

#ifdefined(ewarm)||defined(DOXYGEN)〃iar环境下

void

SysCt1Delay(unsignedlongulCount)

(

__asm("subsrO,#l\nH

"bne.nSysCtlDelay\nn

"bxlrH);

)

#endif

#ifdefined(codered)IIdefined(gcc)IIdefined(sourcerygxx)//codered.

gcc、sourcerygcc环境下

void--.attribute--((naked))

SysCt1Delay(unsignedlongulCount)

(

__asm("subsrO,#l\nH

"bneSysCtlDelay\nn

"bxlrH);

)

#endif

#ifdefined(rvmdk)|Idefined(--ARMCC_VERSION)//kei1MDK环境下

一asmvoid

SysCt1Delay(unsignedlongulCount)

(

subsrO,#1;

bneSysCtIDelay;

bxIr;

)

#endif

#ifdefined(ccs)//ccs

volatileunsignedlongg_ulIniineCCSWorkaround;

void

SysCtIDelay(unsignedlongulCount)

(

--asm("delay?:subsrO,#l\n"

"bne.ndelay?\n"

"bxlr\nn);

//

//ThisisneededtokeepTIcompilerfromoptimizingawaythiscode.

//

g_ulIniineCCSWorkaround+=ulCount;

)

#endif

SysCtlDelayO执行了3个汇编语句,运行时间3个始终周期。函数说明上:The

looptakes3cycles/loop.

1、在主晶振6MHz的情况下

SysCtIDelay(2);delaytime=2*3*(1/6000000)=lus

SysCtIDelay(10*(TheSysClock/3000));delaytime=10*(6000000/3000)

*3*(1/6000000)=10ms

2、在主晶振8MHz的情况下

SysCtIDelay(2);delaytime=2*3*(1/8000000)=0.75us

SysCtlDelay(10*(TheSysClock/3000));delaytime=10*(8000000/3000)

*3*(1/8000000)=10ms

由此可以看出无论是多大的晶振,都是除以3000。SysCtlDelayClO*

(TheSysClock/3000));这种写法也方便移植

Im3s811点亮LED或流水灯程序1急求!!!!

2010-8-617:41

提问者:luxiahua427511悬赏分:5浏览次数:525次

谢谢了啊!刚开始学ARM又没有实际的程序!谢谢帮忙了

210239343luxiahua427511luxiahua427511Im3s811点亮LED0

15I

推荐答案

2010-8-1512:34

#include"systemlnit.h"

//定义LED

#defineLED-PERIPHSYSCTL_PERIPH_GPTOA

#defineLED.PORTGPIO_PORTA_BASE

#defineLED-PINGPIO-PIN.2

//主函数(程序入口)

intmain(void)

(

jtagWait();//防止

"AG失效,重要!

clocklnit();//时钟

初始化:晶振,6MHz

SysCtlPeriEnable(LED-PERIPH);//使能

LED所在的GPIO端口

GPIOPinTypeOut(LED.PORT,LED-PIN);//设置

LED所在管脚为输出

for(;;)

(

GPIOPinWrite(LED_PORT,LED-PIN,0x00);//点亮LED

//SysCtlDelay(1000000);//延时

SysCtlDelayClOOO*(SysCtIClockGet()/36000));//延时

1000ms

GPIOPinWrite(LED_PORT,LED-PIN,OxFF);//熄灭LED

//SysCtlDelay(lOOOOOO);//延时

SysCtlDelayClOOO*(SysCtIClockGet()/3000));//延时

1000ms

)

最基本的一个例程,已调试通过(systemlnit.C的口该一下,8n没G口的)。

你可以去zig网站上去找找资料,那里的例程很多,很适合新手。我也才刚刚开

始学,一起努力了。

0

评论

回复:青风和大家一起学Stellaris系列ARM——九.ADC转换。

程序演示:

分别完成三种ADC变化:程序一:内部温度测试;程序二:单端采样;程序三:

差分采样;

内部温度测试:

在Stellaris系列的ADC模块里,附带了一个内置的温度传感器,能够随时检

测芯片的温度。该温度传感器可以有以下用途:

1测试用:在单独测试ADC模块的功能时,而不必提供外部的模拟信号源

2测量芯片自身温度,防止可能出现的过温(高温应用场合必备)

3估算环境温度:芯片温度总是比环境温度略高,如果通过实验找到这个差值,

则可以进行软件修正

4在随机算法里可以提供随机数种子

内部温度传感器提供了模拟温度读取操作和参考电压。输出终端SENSO的电压

通过以下等式计算得到:

SENSO=2.7-(T+55)/75

ADC温度传感器温度-电压关系

一个实用的ADC温度转换公式。假设温度电压SENSO对应的ADC采样值为N,

2.7V对应Nl,(T+55)/75对应N2。

已知:

N1x(3/1024)=2.7

N2x(3/1024)=(T+55)/75

由此得到:

N=Nl-N2=2.7/(3/1024)-((T+55)/75)/(3/1024)

解得:

T=(151040-225xN)/1024

结论:ADC配置为温度传感器模式后,只要得到10位采样值N,就能推算出摄

氏温度T。

程序标注:

#include"inc/hw_memmap.h"

#include"inc/hw-types.h"

#include"driver1ib/adc.h"

#include"driver1ib/gpio.h"

#include"driverlib/sysctl.h"

#include"utiIs/uartstdio.h"

void

InitConsole(void)

(

//

//初始化GPIO外设

//

SysCtlPeripheralEnable(SYSCTL.PERIPH-GPIOA);

//

//配置化串口外设

//

GPIOPinConfigure(GPIO-PAO.UORX);

GPIOPinConfigure(GPIO_PAl_UOTX);

//

//配置串口管脚

//

GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_OIGPIO_PIN_1);

//

//初始化串口

//

UARTStdioInit(O);

}

int

main(void)

(

//

//T设置数组读取ADCFIFO

//

unsignedlongulADCO-Value[1];

//

//设置温度转换变量

//unsignedlongulTemp-ValueC;

unsignedlongulTemp-ValueF;

//

//设置PLL,ADC的时钟必须要16MHz

//

SysCtlClockSet(SYSCTL_SYSDIV_10ISYSCTL_USE_PLLISYSCTL-OSC-MAIN

SYSCTL_XTAL_16MHZ);

//

//初始化开发板端口

//

InitConsole();

//

//串口显示

//

UARTprintf("ADC->\n");

UARTprintf("Type:InternalTemperatureSensor\n");

UARTprintf("Samples:One\n");

UARTprintf("UpdateRate:250ms\n");

UARTprintf("InputPin:Internaltemperaturesensor\n\n");

//

//ADCO外设初始化

//

SysCtlPeripheralEnable(SYSCTL-PERIPH-ADCO);

//

//配置ADCO,采样序列3,ADC处理器触发,优先级为0

//

ADCSequenceConfigure(ADCO_BASE,3,ADJTRIGGER.PROCESSOR,0);

//

//温度传感,中断使能,对列结束选择,无ADC通道

//

ADCSequenceStepConfigure(ADCO-BASE,3,0,ADC-CTL-TSI/\DC_CTL_IE

ADC-CTL.END);//

//

//使能ADC采样

//

ADCSequenceEnable(ADCO-BASE,3);/

//

////ADC中断清除

//

ADCIntClear(ADCO-BASE,3);

//

〃设置温度显示

//

while(1)

(

//

//ADC处理器触发

//

ADCProcessorTrigger(ADCO-BASE,3);

//

//获取中断状态

//

while(!ADCIntStatus(ADCO-BASE,3,false))

//

//获取ADC采样数据

//

ADCSequenceDataGet(ADCO-BASE,3,ulADCO-Value);

//

//计算温度C

//

ulTemp.ValueC=((1475*1023)-(2250*ulADCO.Value[0]))/10230;

//

//计算温度F

//

ulTemp-ValueF=((ulTemp-ValueC*9)+160)/5;

//

//串口显示

//

UARTprintf("Temperature=%3d*Cor%3d*F\r",ulTemp-ValueC,

ulTemp-ValueF);

//

//时钟延迟

//

SysCtlDelayCSysCtlClockGet()/12);

)

}

运行结果:

LM3s811防止Jtag失效的源代码

(2011-05-2114:20:16)

转载▼

标签:分类:LM3

Im3s811

杂谈

voidJtagWait(void)

unsignedlongi;

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);//使能KEY、LED所在的PC

端口

GPIOPinTypeGPIOInput(GPIO-PORTC.BASE,GPIO-PIN-4);//设置KEY所在管脚

PC4为输入

GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE,GPIO_PIN_5);//设置LED所在管

脚PC5为输出

if(GPIOPinRead(GPIO-PORTC.BASE,GPI0_PIN_4)==0x00)//若复位或上电

时按下KEY,则进入

(

while(l)//死循环,以等待JTAG连接,LED闪烁

{

for(i=0;i<200000;i++);

GPIOPinWrite(GPIO_PORTC_BASE,GPIO_PIN_5,GPIO_PIN_5);〃点亮LED

for(i=0;i<200000;i++);

GPIOPinWrite(GPIO-PORTC-BASE,GPIO_PIN_5,_GPIO_PIN_5);〃熄灭LED

}

)

SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOC);//禁止KEY所在的GPIO

端口

}

模数转换器(ADC)外设用于将连续的模拟电压转换成离散的数字量。

Stellaris系列ARM集成有一个分辨率为10位的ADC模块,支持4/16个输入通

道,以及一个内部温度传感器。Lm3s811支持4个输入通道,Im3s9b96支持16

个输入通道。每个ADC模块包含4个可编程的序列发生器。每个采样序列均对完

全可配置的输入源、触发事件、中断的产生和序列优先级提供灵活的编程。

Stellaris系列ARM的ADC通过使用一种基于序列(sequence-based)的可编

程方法来收集采样数据,取代了传统ADC模块使用的单次采样或双采样的方法。

每个采样序列均为一系列程序化的连续(back-to-back)采样,使得ADC可以从

多个输入源中收集数据,而无需控制器对其进行重新配置或处理。

对本下811和9B96的结构图:

811ADC结构图

9B96ADC结构图

对比2个系列的ADC结构图,大家可以发现:基本相差不大,触发条件完全相同:

具有:比较器,定时器,GPIO,PWM的触发条件。

同时具有4个可编程序列发生器,相对应的SS中断。不同的是9B96的ADC可以

产生相应的PWM触发信号。811不支持外部参考电压,因此硬件方面:

811用于ADC方面的只有4个管脚了。分别代表4个输入通道。

您好!jtagwait是用于防止JTAG失效锁定,其作用主要是针对48脚和64

脚的系列芯片,而现在的100脚的系列芯片已经支持JTAG解锁,所以可以不使

用jtagwait来检测。

而jtagwait是防止用户对JTAG调试接口的相关引脚进行误操作,使软件不能利

用JTAC调试功能,而微控制器在上电后,先执行jtagwait检测程序,来检测某

引脚电平,并进入WHILE⑴;循环,从而使得LMFLASHPROGRAMMER软件可以通

过JTAG连接上微控制器,进而将用户程序擦除,恢复其正常的JTAG调试功能。

LM3S系列JTAG口当10用的解锁

LM3S系列ARM的JTAG口原本是跟10口复用的,当GPIO用时跟一般GPIO没什

么不同。一般只在CPIO口不够用或者做产品不希望用户随意更新固件时,会把

JTAG口当GPIO口来用。如果将JTAG那5根线用作CPIO功能,芯片就会被锁住,

不过要注意,锁住后JTAG就再也不起作用了。解决被锁的办法有两个:

一是下载程序时留有恢复措施,只需启用即可恢复。

如果没有加预防锁死的代码,就只能用Luminary的LMLINK来解锁。很遗憾的

是Sandstorm系列(LM3Sxxx)只支持部分类型,解锁功能也不是很稳定,LM3Sxxxx

才能很好解锁,不过可以试试看。如果有高人看得懂它的时序再写出上位机应该

ULINK也解得了。实在打不开只能找流明诺瑞或更换芯片了。

下面是一段lordor兄使用LM3SXXXSmartBoard演示板恢复JTAG的演示代码:

voidInit-cpu(void)

〃初始化系统时钟设置

SysCtlClockSet(SYSCTL_USE_OSCISYSCTL-OSC-MAINISYSCTL_XTAL_6MHZ);

/******************************GPI0B初始化

〃使能GPIOB模块

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);

////////////////////////////////////////////////////

/〃〃〃〃〃锁定演示:如果设置为GPIO,则JTAG不起作用了

〃按键检测

if(GPIOPinRead(KEYPORT,KD)//如果为高电平

GPIODirModeSet(PH5.PORT,PH5,GPIO-DIR_MODE_IN);//JTAG

if(GPIOPinRead(KEYPORT,K2))//如果为高电平

GPIODirModeSet(PH6.PORT,PH6,GPIO-DIR_MODE_IN);

GPIODirModeSet(PH7.PORT,PH7,GPIO-DIR_MODE_IN);

GPIODirModeSet(PH8-PORT,PH8,GPIO-DIR_MODE_IN);

GPIODirModeSet(PH9.PORT,PH9,GPIO-DIR_MODE_IN);

}

//设置GPIOB口的B4为输出引脚

GPIODirModeSet(LED.PORT,LED1,GPIO-DIR_MODE_OUT);

〃设置连接LED1的引脚为高电平

GPIOPinWrite(LED_PORT,LED1,LED1);

)

说明:下载后,可以发现用JTAG无法通信了。要取消,同时按住K1及K2健,

重开机就可以取消锁定功能了。--bylordor

最后,贴上用Luminary的LMLINK来解锁LM3Sxxxx的方法。

网站六大类职位火热招聘中!点击了解英特尔云计算2012年1月当选微软MVP

的CSDN会员名单揭晓!

LM3SAPI函数解读范例

2010-03-0309:01784人阅读评论⑶收藏举报

jtagWait()函数解读

1.通常在主函数的开始都要调用jtagWait。函数,如工程模版的主函数,

intmain(void)

(

jtagWaitO;//防止JTAG失效,重要!

clocklnit0;//时钟初始化:晶振,6MHz

for(;;)

)

2.关于函数的解释,先要找到函数的定义,可以在函数的调用处指向函数名后

右键选择"Gotodefinitionof…”。

函数jtagWait0在systemlnit.c文件中,其功能是防止JTAG接口失效。

函数定义:

voidjtagWait(void)

(

SysCtIPeriEnable(KEY.PERIPH);//使能KEY所在的GPIO端口

GPIOPinTypeln(KEY-PORT,KEY-PIN);//设置KEY所在管脚为输入

if(GPIOPinRead(KEY-PORT,KEY.PIN)==0x00)//若复位时按下KEY,则进

(

for//死循环,以等待JTAG连接

)

SysCtlPeriDisable(KEY.PERIPH);//禁止KEY所在的GPIO端口

)

/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////

1111

①第一个函数SysCtlPeriEnableO的功能是使能外围设备,原名是

SysCtlPeripheralEnable(),用#define替换是为了使用的方便,该函数在

sysctl.c文件中,可以先加入该文件以便使用"Gotodefinitionof…”找

到其定义。其定义为:

VoidSysCtlPeripheralEnable(unsignedlongulPeripheral)

ASSERT(SysCt1PeripheralVaiid(ulPeripheral));//Checkthearguments.

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

SYSCTL-PERIPH-MASK(ulPeriphera1);//Enablethisperipheral.

)

该函数中的ASSERT。是一个宏,其定义在debug,h中,其作用是计算括号

中的表达式,为0则程序报告错误并终止执行,非0则继续向下执行。函数

SysCtlPeripheralValidO用于判断传入参数的有效性,即判断是否为该函数可

以处理的外围设备,是则返回真,否则返回假,在调用中传入参数KEY_PERIPH,

其实为SYSCTL_PERIPH_GPIOG,其值为0x20000040,该值不是寄存器的地址,暂

时不清楚该值的意义。

HWREGO又是定义的一个宏,在文件hw-types,h中,其定义为:

#defineHWREG(x)(*((volatileunsignedlong*)(x)))

其中(volatileunsignedlong*)(x)是将x强制转换为无符号长整型的指针,

*((volatileunsignedlong*)(x))是引用该指针所指向的存储单元,例如

HWREG(0x20000000)=1;就是向地址为0x20000000的存储单元写入L

传入HWREG()的参数为

g_pulRCGCRegs[SYSCTL-PERIPH.INDEX(u1Peripheral)].

首先看g-PulRCGCRegs口,这是一个静态只读的无符号长整型数组,其定义

为:

staticconstunsignedlongg-pulSCGCRegs[]=

(

SYSCTL.SCGCO,//0x400FE110

SYSCTL.SCGCl,//0x400FE114

SYSCTL-SCGC2//0x400FE118

);

这其实是三个睡眠模式时钟选通控制寄存器,每个位控制一个给定接口、功能、

或单元的时钟使能,如果置位,则对应的单元接收时钟并运行,否则,对应的单

元不使用时钟并禁止(节能),这些位的复位状态都为。(不使用时钟),即所有

功能单元都禁止,应用所需的端口需通过软件来使能。分了三个寄存器来管理所

有接口、功能、或单元的时钟。SYSCTL_SCGC0=0x400FE110表示寄存器的地址。

再看SYSCTL_PERIPH_INDEX(ulPeriphera1),此处的

ulPeripheral=KEY_PERIPH=SYSCTL_PERIPH_GPIOG=0x20000040。

SYSCTL_PERIPH_INDEX()的定义为:

#defineSYSCTL_PERIPH_INDEX(a)(((a)»28)&Oxf),此处计算结果

SYSCTL_PERIPH_INDEX(0x20000040)=2,而g_pulSCGCRegs[2]正好是睡眠模式时

钟选通控制寄存器2(SCGC2),正好是控制GPIOA—GPIOH的时钟使能。因此不

难猜想SYSCTL_PERIPH」NDEX(a)是为了选择寄存器SCGCO,SCGC1,SCGC2中的

一个。

因此HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)])意思就是

选中寄存器SCGC2,整句的意思是要改写该寄存器的值。于是继续看后半句

SYSCTL_PERIPH_MASK(ulPeripheral),当然1=是复合赋值a|=b相当于a=aIb。

#defineSYSCTL-PERIPH-MASK(a)(((a)&Oxffff)«(((a)&OxOOlfOOOO)»

16)),该句比较复杂,暂时不知道为什么要这样写,但此处计算结果

SYSCTL_PERIPH_MASK(0x20000040)=0x0040,因此

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

SYSCTL_PERIPH_MASK(ulPeriphera1);

一句的目的是将寄存器SCGC2的第6位GPIOG置1而使能GPIOG端口。另外,再

看一下SCGC2的定义如下:

76543210

GPIOHGPIOGGPIOFGPIOEGPIODGPIOCGPIOBGPIOA

这就不难理解为什么有如下定义

#defineSYSCTL.PERIPH.GPIOA0x20000001//GPIOA

#defineSYSCTL_PERIPH_GPIOB0x20000002//GPIOB

#defineSYSCTL_PERIPH_GPIOC0x20000004//GPIOC

#defineSYSCTL_PERIPH_GPIOD0x20000008//GPIOD

#defineSYSCTL_PERIPH_GPIOE0x20000010//GPIOE

#defineSYSCTL.PERIPH_GPIOF0x20000020//GPIOF

#defineSYSCTL_PERIPH_GPIOG0x20000040//GPIOG本例中使用

#defineSYSCTL_PERIPH_GPIOH0x20000080//GPIOH

/////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////

////

②第二个函数GPIOPinTyp函n()其实为GPIOPinTypeGPIOInput(),该函数在

gpio.c文件中,其定义为:

VoidGPIOPinTypeGPIOInput(unsignedlongulPort,unsignedcharucPins)

(

ASSERT(GPIOBaseValid(ulPort));//Checkthearguments.

GPIODirModeSet(ulPort,ucPins,GPIO-DIR_MODE_IN);//Makethepin(s)be

inputs.

GPIOPadConfigSet(ulPort,ucPins,GPIO-STRENGTH_2MA,

GPIO-PIN_TYPE_STD);

//Setthepad(s)forstandardpush-pulloperation.

)

调用该函数时传入的参数为ulPort=GPI0_P0RTG_BASE=0x40026000和

ucPins=GPI0_PIN_5=0x00000020.

第一句有关ASSERT。宏的应用如前所述,不再赘述。

现在来看第二句GPIODirModeSet(ulPort,ucPins,GPI0.DIR一MODEJN);其

中新的参数GPIO-DIR.MODE.IN=0x00000000,该函数的目的是要将GPIOG的第5

个管脚置为输入。该函数也在gpio.c文件中,其定义为:

VoidGPIODirModeSet(unsignedlongulPort,unsignedcharucPins,unsigned

longulPinlO)

(

ASSERT(GPIOBaseValid(ulPort));

ASSERT((ulPinlO==GPIO_DIR_MODE_IN)II(ulPinlO==GPIO_DIR_MODE_OUT)

II

(ulPinlO==GPIO-DIR.MODE.HW));//Checkthearguments.

HWREG(ulPort+GPIO_O_DIR)=((ulPinlO&1)?

(HWREG(ulPort+GPIO-O-DIR)|ucPins):

(HWREG(ulPort+GPIO_O_DIR)&-(ucPins)));

HWREG(ulPort+GPIO_O_AFSEL)=((ulPinlO&2)?

(HWREG(ulPort+GPIO-O-AFSEL)|ucPins):

(HWREG(ulPort+GPIO_O_AFSEL)&

(ucPins)));//Setthepindirectionandmode.

}

同上,前两句不再赘述,第三句赋值表达式的左边为HWREG(ulPort+

GPIO-O-DIR),此处ulPort==GPIO_PORTG_BASE=0x40026000,是GPIOG块的基

地址,每个块都有相同的GPIO寄存器,因此可以用BASE+OFFSET的方式寻址各

个块的寄存器,GPIO_O_DIR=0x00000400,表明GPIO方向寄存器GPIODIR的偏

移量为0x400,因此HWREG(ulPort+GPIO_O_DIR)寻址到了GPIOG的寄存器

GPIODIR,该寄存器是数据方向寄存器,GPIODIR寄存器中设为1的位将相应的

管脚配置成输出,而设为0的位将相应的管脚配置成输入,所有位在复位时都会

被清零,即默认情况下所有GPIO管脚都是输入。赋值号右边是一个条件表达式,

条件为(ulPinlO&1),ulPinlO为传入的第三个参数,为0则置为输入管脚,

为1则置为输出管脚,此处传入GPIO_D管脚0DEJN=0x00000000,因此条件为

假,所以会将(HWREG(ulPort+GPIO_O_DIR)&-(ucPins))的值写入寄存器

GPIODIR,下面分析如何实现,HWREG(ulPort+GPIO_O_DIR)取出GPIODIR的值,

此处的ucPins=GPIO_PIN_5=0x00000020,取反后只有第5位为0,其余位为P

与原值相与后把第5为清0,然后送回寄存器。

第四句与第三句形式一样,不再详细分析,只简单说明其作用,HWREG(ulPort

+GPI0_0-AFSEL)为选中GPI0备用功能选择(GPIOAFSEL)寄存器,向该寄存器

中的任意位写“1”表示选择该GPIO线路所对应的硬件控制(功能)。由于所有

的位都在复位时都会清零,因此在默认的情况下,并无GPI0线被设为硬件控制

(功能)。而参数ulPinlO有三种选择,如下:

#defineGPIO_DIR_MODE_IN0x00000000//PinisaGPIOinput

#defineGPIO_DIR_MODE_OUT0x00000001//PinisaGPIOoutput

#defineGPIO-DIR-MODE-HW0x00000002//Pinisaperipheralfunction

因此ulPinI0=2时则将GPIOAFSEL寄存器的相应位置1,表示选择其硬件控制功

能。本例中第5位清0。

③第三个函数为GPIOPinReadO,猜想其功能为读取某端口某管脚的状态,该

函数也在gpio.c中,其定义为:

LongGPIOPinRead(unsignedlongulPort,unsignedcharucPins)

(

ASSERT(GPIOBaseValid(ulPort));

return(HWREG(ulPort+(GPIO-O-DATA+(ucPins«2))));//Returnthepin

value(s).

}

其中HWREG(ulPort+(GPIO_O_DATA+(ucPins«2)))这句很重要,体现

了一种利用地址线屏蔽而实现可对任意位操作的机制,将地址总线的位[9:2]用

作屏蔽位,在读操作过程中,如果与数据位相关联的地址位被设为1,那么读取

该值,如果与数据位相关联的地址位被设为0,那么不管它的实际值是什么,都

将该值读作0。下面结合本例解释,将各个参数的值代入为HWREG(0x40026000+

(0x000+(0x00000020«2))),结果为HWREG(0x40026080)。

ADDR[9:2]9876543210

0x0800010000000

GPIODATA76543210

如上表所示,GPIODATA寄存器中除第5位外,其余都被屏蔽,可以只读出

第5位的状态。

④第四个函数SysCtlPeriDisable()的原型为void

SysCt1PeripheralDisable(unsignedlongulPeripheral),在sysctl.c文件中,

其定义为:

VoidSysCtlPeripheralDisable(unsignedlongulPeripheral)

ASSERT(SysCtlPeripheralValid(ulPeripheral));

HWREG(g_pu1RCGCRegs[SYSCTL_PERIPH_INDEX(ulPeriphera1)])&=

-SYSCTL_PERIPH_MASK(ulPeripheral);//Disablethisperipheral.

)

其形式和SysCt1PeripheralEnable()相似,不再赘述。

2012CSDN网站六大类职位火热招聘中!点击了解英特尔云计算2012年1月当

选微软MVP的CSDN会员名单揭晓!

一、使用UART库函数介绍

1,函数:UARTConfigSetExpClk()

功能:UART配置(要求提供明确的时钟速率)

原型:voidUARTConfigSetExpClk(unsignedlongulBase,unsignedlong

ulUARTClk,

unsignedlongulBaud,unsignedlongulConfig)

参数:ulBase:UART端口的基址,取值UART0一BASE、UART1.BASE或UART2.BASE

ulUARTClk:提供给UART模块的时钟速率,即系

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论