Discuz! Board
标题: 青风tm4c讲座第三讲:gpio的驱动,点亮led灯 [打印本页]
作者: wanqin_002 时间: 2013-9-24 11:11
标题: 青风tm4c讲座第三讲:gpio的驱动,点亮led灯
本帖最后由 wanqin_002 于 2013-9-24 11:14 编辑
4.1 GPIO的驱动与开发 4.11 原理分析:
大家之前学习过51单片机,也使用过IO口。与51的IO进行对比,Cortex M4的IO配置有点区别。51不需要设置IO口为输入或者输出,除了做为输入捕获,基本就是作为输出端口进行使用了。而Cortex M4的IO口有多种状态需要设置,那么下面我们就一一道来:
I/O(Input/Output)接口是一颗微控制器必须具备的最基本外设功能。在TM4C系列ARM里,所有I/O都是通用的,称为GPIO(General Purpose Input/Output)。 GPIO模块由14个物理GPIO块组成,一块对应一个GPIO端口(PA、PB、PC、PD、PE、PF、PG、PH、PJ、PK、PL、PM、PN、PP)。每个GPIO端口包含多个管脚,如PA端口是PA0~PA7。GPIO模块遵循FiRM(Foundation IP for Real-Time Microcontrollers)规范,并且支持多达105个可编程输入/输出管脚(具体取决于与GPIO复用的外设的使用情况)。
下图给出了GPIO模块各个端口相应寄存器的结构图,大家看懂这个结构图,也就对GPIO口的操作有了整体的了解。
[attach]41[/attach]
图1:数字/模拟IO结构图
比如:port control寄存器控制端口输入和输出,Date control控制数据量。详细的说明大家参考datasheet。如果TI没有给出函数库,那么编写程序进行寄存器配置就是很重要的一环。
在inc/tm4c123gh6pz.h文件中对tm4c123gh6pz(LM4F232)寄存器进行了全面的配置,TI的这个头文件采取的是一次列举的方式分配寄存器地址的。有的32位ARM的头文件则采取的是结构体的方式分配地址的。
那么谈到GPIO的使用,我们最重点注意的还是IO端口状态的配置。GPIO的寄存器配置常用的有:
数据寄存器操作,数据方向操作,中断操作,端口模式操作 等等。
如果大家直接操作响应寄存器是可以的,但是TI配备了完整的函数库,使用函数库进行操作就变的很简单了。这也是我们下面的软件编程中要详细介绍的。
在TM4C系列ARM里,GPIO管脚可以被配置为多种工作模式,其中有3种比较常用:高阻输入、推挽输出、开漏输出。这三种模式,大家在模电数电中已经有过了解了:
1. 高阻输入(Input)
如图2所示,为GPIO管脚在高阻输入模式下的等效结构示意图。这是一个管脚的情况,其它管脚的结构也是同样的。输入模式的结构比较简单,就是一个带有施密特触发输入(Schmitt-triggered input)的三态缓冲器(U1),并具有很高的输入等效阻抗。
[attach]42[/attach]
图2:高阻输入
2.推挽输出(Output)
如图3所示,为GPIO管脚在推挽输出模式下的等效结构示意图。U1是输出锁存器,执行GPIO管脚写操作时,在写脉冲(Write Pulse)的作用下,数据被锁存到Q和/Q。T1和T2构成CMOS反相器,T1导通或T2导通时都表现出较低的阻抗,但T1和T2不会同时导通或同时关闭,最后形成的是推挽输出。在Stellaris系列ARM里,T1和T2实际上是多组可编程选择的晶体管,驱动能力可配置为2mA、4mA、8mA,以及带转换速率(Slew Rate)控制的8mA驱动。
[attach]43[/attach]
图3:推挽输出
3.开漏输出(OutputOD)
如图4所示,为GPIO管脚在开漏输出模式下的等效结构示意图。开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到GND(有一定内阻)。回读功能:读到的仍是输出锁存器的状态,而不是外部管脚Pin的状态。因此开漏输出模式是不能用来输入的。
[attach]44[/attach]
图4:开漏输出
当然Cortex M4 TM4C123gh6pz(LM4F232)的寄存器要比51,AVR的单片机寄存器多一些,他所需用的工作状态也要复杂的多,详细的寄存器配置大家可以查看数据手册,这里就不展开了。
4.12 硬件设计:
实验硬件采用:青风 QF-Hanker V2.0开发板. 开发板中,我们给出了一个用户LED灯。电路如图所示,通过PC7口进行控制:
[attach]45[/attach]
图5:硬件电路图
4.13软件设计:
学会使用TI的函数库进行编程。我们过去编写51等单片机时是直接配置寄存器的,使用函数库这种方法对于越来越复杂的MCU是非常必须的。Cortex M4内部的寄存器比较多,如果去慢慢了解寄存器需要花费大量的时间。而直接使用TI封装好的函数库能够大大减少入门时间,开发者可以集中精力于项目功能的实现,大大缩短了开发时间。当然有时间深入研究的朋友也可以编写自己的函数库,一句话,怎么方便怎么来。
大家可以查看TI外设函数库驱动文档,对函数库进行详细了解。这里先介绍结构GPIO端口常用的函数:
1.GPIOPadConfigSet 设置指定管脚的配置。
函数原型: GPIOPadConfigSet(unsigned long ulPort,
unsigned char ucPins,
unsigned long ulStrength,
unsigned long ulPinType)
参数:
ulPort是GPIO端口的基址。
ucPins是特定管脚的位组合(bit-packed)表示。
ulStrength指定输出驱动强度。
ulPinType指定管脚类型。
描述:
这个函数设置所选GPIO端口指定管脚的驱动强度和类型。对于配置用作输入端口的管脚,端口按照要求配置,但是对输入唯一真正的影响是上拉或下拉终端的配置。
参数ulStrength可以是下面的一个值:
GPIO_STRENGTH_2MA;
GPIO_STRENGTH_4MA;
GPIO_STRENGTH_8MA;
GPIO_STRENGTH_8MA_SC。
在上面的值中,GPIO_STRENGTH_xMA指示2、4或8mA的输出驱动强度;而GPIO_OUT_STRENGTH_8MA_SC指定了带斜率控制(slew control)的8mA输出驱动。
参数ulPinType可以是下面的其中一个值:
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。
在上面的值中,GPIO_PIN_TYPE_STD*指定一个推挽管脚,GPIO_PIN_TYPE_OD*指定一个开漏管脚,*_WPU指定一个弱上拉,*_WPD指定一个弱下拉,GPIO_PIN_TYPE_ANALOG指定一个模拟输入(对于比较器来说)。管脚用一个位组合(bit-packed)的字节来指定,在这个字节中,置位的位用来识别被访问的管脚,字节的位0代表GPIO端口管脚0、位1代表GPIO端口管脚1等等。
2.GPIODirModeSet:设置指定管脚的方向和模式。
函数原型:void
GPIODirModeSet(unsigned long ulPort,
unsigned char ucPins,
unsigned long ulPinIO)
参数:
ulPort是GPIO端口的基址。
ucPins是管脚的位组合(bit-packed)。
ulPinIO是管脚方向“与/或”模式。
描述:
这个函数在软件控制下将所选GPIO端口的指定管脚设置成输入或输出,或者,也可以将管脚设置成由硬件来控制。
参数ulPinIO是一个枚举数据类型,它可以是下面的其中一个值:
� GPIO_DIR_MODE_IN;
� GPIO_DIR_MODE_OUT;
� GPIO_DIR_MODE_HW。
在上面的值中,GPIO_DIR_MODE_IN表明管脚将被编程用作一个软件控制的输入,GPIO_DIR_MODE_OUT表明管脚将被编程用作一个软件控制的输出,GPIO_DIR_MODE_HW表明管脚将被设置成由硬件进行控制。
管脚用一个位组合(bit-packed)的字节来指定,这里的每个字节,置位的位用来识别被访问的管脚,字节的位0代表GPIO端口管脚0、位1代表GPIO端口管脚1等等。
3.GPIOPinWrite向指定管脚写入一个值。
函数原型:
void
GPIOPinWrite(unsigned long ulPort,
unsigned char ucPins,
unsigned char ucVal)
参数:
ulPort是GPIO端口的基址。
ucPins是管脚的位组合(bit-packed)表示。
ucVal是写入到指定管脚的值。
描述:
将对应的位值写入ucPins指定的输出管脚。向配置用作输入的管脚写入一个值不会产生任何影响。
管脚用一个位组合(bit-packed)的字节来指定,在这个字节中,置位的位用来识别被访问的管脚,字节的位0代表GPIO端口管脚0、位1代表GPIO端口管脚1等等。
下面我们就来点亮其中led灯,并且不停闪烁,也就是把IO管脚定义为输出:
点亮一个led灯的过程我们可以归纳如下:
1:配置系统时钟和使能GPIO端口外设,也就是开GPIO功能。
2:配置GPIO端口驱动电流大小和管脚模式
3:设置管脚为输出管脚。
4:设置管脚输出是高电平还是低电平。
那么下面我们开始编写程序:
首先建立工程项目目录如下图所示,具体的建立要求的方法见上一章的快速入门:
[attach]46[/attach]
由于我们需要使用库函数,因此除了调用我们写的主函数,再就是需要添加封装好的driverlib.lib库函数,这样整个工程项目就建立好了,下面就是来编写主函数了。
主函数要使用库函数内的函数定义,因此需要调用如下一些函数库头文件:
//-----------------------------------------------------------------------------
// 文件名 : led闪烁
// 作者 : 青风
// ARM内核 : Cortex-M4
// 使用芯片 : LM4F232H5QD/tm4c123gh6pz
// 开发环境 : KEIL
// 版本记录 : 2013-6-10 14:30
//函数功能说明:led不停的闪动
//-----------------------------------------------------------------------------
#include "inc/tm4c123gh6pz.h" //可以不加
#include <stdint.h> //定义字符内型
#include <stdbool.h> //0/1的定义
#include "inc/hw_types.h" //一些位带操作的宏定义
#include "inc/hw_memmap.h" //外设基地址的定义
#include "driverlib/sysctl.h" //系统时钟
#include "driverlib/gpio.h" //gpio定义
/**********************************************/
/* 函数功能;简单的延迟函数 */
/* 入口参数:无 */
/**********************************************/
void delay()
{
int i,j;
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++);
}
}
/**********************************************/
/* 函数功能;主函数 */
/* 入口参数:无 */
/**********************************************/
int main(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); //系统时钟设置
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC); // 使能LED所在端口PC
GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, GPIO_PIN_7);
//配置PN.7为led灯输出
while(1)
{
GPIOPinWrite(GPIO_PORTC_BASE,GPIO_PIN_7,0); //灭灯
delay();//延迟
GPIOPinWrite(GPIO_PORTC_BASE,GPIO_PIN_7,GPIO_PIN_7);//亮灯
delay(); //延迟
}
}
下载成功后:led灯开始闪动。
[attach]40[/attach]
欢迎光临 Discuz! Board (http://qfv8.com/) |
Powered by Discuz! X3 |