|
青风Hanker TI M4 开发板开发应用教程-----第三章第一节: GPIO 的驱动与开发
[复制链接]
3.1 GPIO 的驱动与开发
3.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-TimeMicrocontrollers)规范,并且支持多达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:开漏输出
当然Cortex M4 TM4C123gh6pz(LM4F232)的寄存器要比51,AVR 的单片机寄存器多一些,他所需用的工作状态也要复杂的多,详细的寄存器配置大家可以查看数据手册,这里就不展开了。
3.12 硬件设计:
实验硬件采用:青风QF-Hanker V2.0 开发板. 开发板中,我们给出了一个用户LED灯。电路如图所示,通过PC7 口进行控制:
图5:硬件电路图
3.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-10 14:30
- //函数功能说明:led 不停的闪动
- //-----------------------------------------------------------------------------
- #include "inc/tm4c123gh6pz.h" //可以不加
- #include //定义字符内型
- #include //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 灯开始闪动。
外设应用:第一节:gpio应用-点亮led.pdf
(391.94 KB, 下载次数: 354)
|
|