wanqin_002 发表于 2013-9-24 11:11:29

青风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口的操作有了整体的了解。                     图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),并具有很高的输入等效阻抗。                                                                                                                图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驱动。                                                  图3:推挽输出   3.开漏输出(OutputOD) 如图4所示,为GPIO管脚在开漏输出模式下的等效结构示意图。开漏输出和推挽输出相比结构基本相同,但只有下拉晶体管T1而没有上拉晶体管。同样,T1实际上也是多组可编程选择的晶体管。开漏输出的实际作用就是一个开关,输出“1”时断开、输出“0”时连接到GND(有一定内阻)。回读功能:读到的仍是输出锁存器的状态,而不是外部管脚Pin的状态。因此开漏输出模式是不能用来输入的。                                                       图4:开漏输出当然CortexM4TM4C123gh6pz(LM4F232)的寄存器要比51,AVR的单片机寄存器多一些,他所需用的工作状态也要复杂的多,详细的寄存器配置大家可以查看数据手册,这里就不展开了。4.12 硬件设计:   实验硬件采用:青风 QF-HankerV2.0开发板. 开发板中,我们给出了一个用户LED灯。电路如图所示,通过PC7口进行控制:                                             
                                                      图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:设置管脚输出是高电平还是低电平。那么下面我们开始编写程序:首先建立工程项目目录如下图所示,具体的建立要求的方法见上一章的快速入门:由于我们需要使用库函数,因此除了调用我们写的主函数,再就是需要添加封装好的driverlib.lib库函数,这样整个工程项目就建立好了,下面就是来编写主函数了。       主函数要使用库函数内的函数定义,因此需要调用如下一些函数库头文件://-----------------------------------------------------------------------------// 文件名    : led闪烁// 作者      : 青风// ARM内核   : Cortex-M4// 使用芯片: LM4F232H5QD/tm4c123gh6pz// 开发环境: KEIL// 版本记录:2013-6-1014: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所在端口PCGPIOPinTypeGPIOOutput(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灯开始闪动。

页: [1]
查看完整版本: 青风tm4c讲座第三讲:gpio的驱动,点亮led灯