加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【第九讲】TMS320F28335开发板之GPIO模块

(2016-04-20 22:11:39)
标签:

杂谈

分类: DSP

这一讲同上一讲一样,先讲解硬件部分,再讲解软件实验部分。

GPIO模块:(通用输入/输出模块)

TMS320F28335对所有数字量IO进行分组,分为A、B、C三组。A组包括GPIO0至GPIO31,B组包括GPIO32至GPIO63,C组包括GPIO64至GPIO87.需要注意的是,虽然GPIO每个引脚多个功能复用,但在同一时刻只能使用其中一个功能。GPIO多路复用(MUX)寄存器来选择对复用引脚的操作。

由于以下涉及到很多的寄存器内部单元与GPIO引脚间的对应关系,文字可能比较抽象。具体安排可以看关于GPIO模块内部各个寄存器的讲解图(从75页开始)。sprufb0d(TMS320x2833x, 2823x System Control and Interrupts)

QQ截图20160112153032.pngQQ截图20160112153045.pngQQ截图20160112153056.png

GPIO MUX寄存器(多路复用寄存器)用来实现GPIO多功能复用引脚的功能模式选择,各个引脚可独立配置在GPIO模式或外设专用功能模式。比如GPIO0有I/O功能和PWM输出功能就可以通过配置MUX来选择其中的一个功能来使用。如果配置在GPIO模式,还需要通过GPIO的方向控制寄存器GPxDIRx为A、B、C)设置GPIO模式作为输入还是作为输出。作为输入时,还可以限制输入信号的脉宽以消除不必要的噪声(通过GPxQSELn、GPACTRL和GPBCTRL寄存器)。

GPxMUXn(32位):多路复用寄存器。(x=A、B、C ,n= 1、2

http://s13/middle/0034sXQLzy73jDUNRG45c&690

每一个引脚由2位控制:

                                      00:通用I/O

                                      01:外设功能1

                                      10:外设功能2

                                      11:外设功能3

GPAMUX1:负责GPIO0~GPIO15的引脚功能选择。

GPAMUX2:负责GPIO16~GPIO31的引脚功能选择。

GPBMUX1:负责GPIO32~GPIO47的引脚功能选择。

GPBMUX2:负责GPIO48~GPIO63的引脚功能选择。

GPCMUX1:负责GPIO64~GPIO79的引脚功能选择。

GPCMUX2:负责GPIO80~GPIO87的引脚功能选择。

GPxDIR(32位):方向控制寄存器x为A、B、C

每个引脚对应1位:

                               0:代表输入

                               1:代表输出

GPADIR:GPIO0~GPIO31

GPBDIR:GPIO32~GPIO63

GPCDIR:GPIO64~GPIO87

1.GPIO模式选择控制(带*目前只需了解即可)

引脚功能分配、输入信号限制和外部中断源(XINT1~XINT7、XNMI)都是由GPIO配置控制寄存器来控制的。

配置GPIO模式有以下几方面:

a.通过GPxMUXn配置引脚功能;

b.对于数字I/O口,通过配置GPxDIR来配置引脚的方向;

c.通过配置GPxCTRLGPxQSELn对输入引脚进行限制

*d.通过配置GPxPUD相应位来使能或禁止内部上拉功能;

*e.通过配置GPIOLPMSEL寄存器来指定实现低功耗模式唤醒的I/O口;

*f.通过配置GPIOXINTxSEL(x=1~7GPIOXNMISEL来指定作为外部中断源的输入引脚。

2.GPIO数据控制(GPIO模式)

如果引脚配置成GPIO模式,有以下四种方式对GPIO引脚进行写操作:

    a.对GPIO的数据寄存器GPxDAT进行写1(输出高电平)或写0(输出低电平);

    b.利用置位寄存器GPxSET写1(写0无效)来输出高电平;

    c.利用清零寄存器GPxCLEAR写1(写0无效)来输出低电平;

    d.利用翻转寄存器GPxTOGGLE寄存器写1(写0无效)来将IO输出电平反转(原来高电平反转为低电平,原来低电平反转为高电平)。

下面就以上出现的几种寄存器简要说明一下:

1).数据寄存器GPxDAT(32位):(x=A、B、C

每个引脚对应1位

GPADAT:GPIO0~GPIO31

GPBDAT:GPIO32~GPIO63

GPCDAT:GPIO64~GPIO87

每个I/O口都有,数据寄存器中的每一位对应于一个GPIO引脚。无论引脚被配置成何种功能(GPIO模式或外设功能),数据寄存器中的相应位都反映了引脚当前状态。向GPxDAT写控制字可以清零或者置位相应的输出锁存器,但不一定被驱动到(被输出到)引脚上,只有当当前引脚为通用I/O口才能驱动引脚;若为外设功能时,则输出锁存器将锁存。

2).置位寄存器GPxSET(32位)x=A、B、C

每个引脚对应1位:

GPASET:GPIO0~GPIO31

GPBSET:GPIO32~GPIO63

GPCSET:GPIO64~GPIO87

用来驱动特定的引脚为高电平,而不干扰其他引脚。当然能否驱动取决于输出锁存器和当前引脚的功能,只有当前引脚为通用I/O口是才能驱动。

3).清零寄存器GPxCLEAR(32位)x=A、B、C

 

每个引脚对应1位:

GPACLEAR:GPIO0~GPIO31

GPBCLEAR:GPIO32~GPIO63

GPCCLEAR:GPIO64~GPIO87

用来驱动特定的引脚为低电平,而不干扰其他引脚。当然能否驱动取决于输出锁存器和当前引脚的功能,只有当前引脚为通用I/O口是才能驱动。

4).翻转寄存器GPxTOGGLE(32位)x=A、B、C

 

每个引脚对应1位:

GPATOGGLE:GPIO0~GPIO31

GPBTOGGLE:GPIO32~GPIO63

GPCTOGGLE:GPIO64~GPIO87

这个同上,只是会驱动指定引脚电平反转。

3.输入限制(采样滤波)

通过配置GPAQSEL1、GPAQSEL2、GPBQSEL1和GPBQSEL2来为每一个GPIO引脚设置输入限制的类型。对于通用GPIO输入引脚,输入限制可以设置成仅与SYSCLKOUT信号同步,或者通过一个采样窗限制。对于配置成外设输入的引脚,输入限制除了可以为与SYSCLKOUT信号同步或者由一个采样窗限制之外,还可以是异步的。

a.无同步(输入异步)

该模式用于外设不需要输入同步,或者外设可以提供同步的情况下。如果引脚作为通用GPIO输入引脚,则异步选项是无效的,且输入限制默认为与SYSCLKOUT同步。

b.仅与SYSCLKOUT同步

这是所有引脚复位时的默认限制模式。因为输入信号是异步的,所以需要一个SYSCLKOUT的延迟,DSP的输入才会发生变化。输入信号将不再受其他输入限制。

c.用采样窗限制

该模式中,信号首先与系统时钟SYSCLKOUT同步,然后在输入允许变化之前使用特定个数的时钟周期来作为输入限制。该类型的限制中需要指定两个参数分别为采样周期(信号多久被采样一次)和要采样的点数。下面具体介绍:

     i.采样周期。由GPxCTRL(x=A、B中的QUALPRDn来确定,其同时对一组8个引脚输入的采样周期进行配置,所以这8个引脚的信号采样周期一定是相同的。例如,GPIO0~GPIO7的采样周期由GPACTRL[QUALPRD0]配置,GPIO8~GPIO15由GPACTRL[QUALPRD1]配置。

    ii.采样点数。由限制选择寄存器(GPAQSEL1、GPAQSEL2、GPBQSEL1和GPBQSEL2)来配置,可以配置成3或6,默认是1,。当输入在3个或6个采样点内均相同时,输入才被DSP认可。采样窗的宽度即输入信号被采样的时间的宽度。

上面讲了有那么多,可能有些人不理解那些寄存器的含义,下面一 一解释一下:

a.GPxCTRL(32位):限制控制寄存器。(x=A、B)         决定采样周期

http://s13/middle/0034sXQLzy73jDUQ61Cbc&690


GPxCTRL寄存器单元内部被分成4组,分别是QUALPRD0~QUALPRD3(8位),每组8位,该8位对应8个GPIO引脚,有着各自相同的时钟周期。不同组之间时钟周期可以相同可以不同。

主要负责控制采样周期,GPACTRL负责GPIO0~GPIO31的采样周期,具体由QUALPRDn(n=0~3)来控制采样周期;GPBCTRL负责GPIO32~GPIO63的采样周期,具体由QUALPRDn(n=0~3)来控制采样周期。

采样周期=2*QUALPRDn(转化为十进制)*SYSCLKOUT(系统时钟)

b.GPxQSELn(32位):限制选择寄存器。(x=A、B n=1、2)        决定采样点数

http://s1/middle/&690

http://s15/middle/0034sXQLzy73jDVBmZ8ee&690

http://s14/middle/0034sXQLzy73jDVCxqd9d&690

决定了输入引脚的输入限制类型。GPAQSEL1控制GPIO0~GPIO15的输入限制类型,GPAQSEL2控制GPIO16~GPIO31的输入限制类型,GPBQSEL1控制GPIO32~GPIO47的输入限制类型,GPBQSEL2控制GPIO48~GPIO63的输入限制类型。其中,每个GPxQSELn寄存器32位,每个GPIO引脚的输入限制字是2位

                                                  00,代表仅与SYSCLKOUT同步;

                                                  01,代表采用3个采样点的采样窗限制;

                                                  10,代表采用6个采样点的采样窗限制;

                                                  11,代表异步,只适用于引脚被配置为外设功能,对于设置为通用GPIO的                                                                                                                                                                                                                                      引脚来说,该项与00相同。

        *c.GPxPUD(32位):GPIO上拉禁止寄存器x=A、B 、C

QQ截图20160115125937.png


*************************************************************************************************************************

上面讲完硬件理论部分,下面开始实验软件部分。

实验部分只是带大家了解一下这部分编程所需要的各种寄存器,这次以项目Example_2833xGpioToggle为例进行讲解

1.Example_2833xGpioToggle.c 【GPIO输出电平翻转实验】

 


  1. // TI File $Revision: /main/8 $
  2. // Checkin $Date: April 21, 2008 15:42:43 $
  3. //###########################################################################
  4. //
  5. // FILE: Example_2833xGpioToggle.c
  6. //
  7. // TITLE: DSP2833x Device GPIO toggle test program.
  8. //
  9. // ASSUMPTIONS:
  10. //
  11. // This program requires the DSP2833x header files.
  12. //
  13. // ALL OF THE I/O'S TOGGLE IN THIS PROGRAM. MAKE SURE
  14. // THIS WILL NOT DAMAGE YOUR HARDWARE BEFORE RUNNING THIS
  15. // EXAMPLE.
  16. //
  17. // Monitor desired pins on an oscilloscope.
  18. //
  19. // As supplied, this project is configured for "boot to SARAM"
  20. // operation. The 2833x Boot Mode table is shown below.
  21. // For information on configuring the boot mode of an eZdsp,
  22. // please refer to the documentation included with the eZdsp,
  23. //
  24. // $Boot_Table:
  25. //
  26. // GPIO87 GPIO86 GPIO85 GPIO84
  27. // XA15 XA14 XA13 XA12
  28. // PU PU PU PU
  29. // ==========================================
  30. // 1 1 1 1 Jump to Flash
  31. // 1 1 1 0 SCI-A boot
  32. // 1 1 0 1 SPI-A boot
  33. // 1 1 0 0 I2C-A boot
  34. // 1 0 1 1 eCAN-A boot
  35. // 1 0 1 0 McBSP-A boot
  36. // 1 0 0 1 Jump to XINTF x16
  37. // 1 0 0 0 Jump to XINTF x32
  38. // 0 1 1 1 Jump to OTP
  39. // 0 1 1 0 Parallel GPIO I/O boot
  40. // 0 1 0 1 Parallel XINTF boot
  41. // 0 1 0 0 Jump to SARAM <- "boot to SARAM"
  42. // 0 0 1 1 Branch to check boot mode
  43. // 0 0 1 0 Boot to flash, bypass ADC cal
  44. // 0 0 0 1 Boot to SARAM, bypass ADC cal
  45. // 0 0 0 0 Boot to SCI-A, bypass ADC cal
  46. // Boot_Table_End$
  47. //
  48. // DESCRIPTION:
  49. //
  50. // Three different examples are included. Select the example
  51. // (data, set/clear or toggle) to execute before compiling using
  52. // the #define statements found at the top of the code.
  53. //
  54. //
  55. // Toggle all of the GPIO PORT pins
  56. //
  57. // The pins can be observed using Oscilloscope.
  58. //
  59. //
  60. //###########################################################################
  61. // $TI Release: DSP2833x/DSP2823x Header Files V1.20 $
  62. // $Release Date: August 1, 2008 $
  63. //###########################################################################
  64. #include "DSP28x_Project.h" // Device Headerfile and Examples Include File
  65. // Select the example to compile in. Only one example should be set as 1
  66. // the rest should be set as 0.
  67. #define EXAMPLE1 1 // Use DATA registers to toggle I/O's 1.//这部分学过C语言的都清楚 
  68. #define EXAMPLE2 0 // Use SET/CLEAR registers to toggle I/O's //这部分是宏定义,那这三个
  69. #define EXAMPLE3 0 // Use TOGGLE registers to toggle I/O's //变量的作用可以在下面找
  70. // Prototype statements for functions found within this file.
  71. void delay_loop(void); 10.//函数的声明
  72. void Gpio_select(void);
  73. void Gpio_example1(void);
  74. void Gpio_example2(void);
  75. void Gpio_example3(void);
  76. void main(void)
  77. {
  78. // Step 1. Initialize System Control:
  79. // PLL, WatchDog, enable Peripheral Clocks
  80. // This example function is found in the DSP2833x_SysCtrl.c file.
  81. InitSysCtrl();
  82. // Step 2. Initalize GPIO:
  83. // This example function is found in the DSP2833x_Gpio.c file and
  84. // illustrates how to set the GPIO to it's default state.
  85. // InitGpio(); // Skipped for this example
  86. // For this example use the following configuration:
  87. Gpio_select(); //对GPIO进行操作,具体可以看下面该函数的定义
  88. // Step 3. Clear all interrupts and initialize PIE vector table:
  89. // Disable CPU interrupts
  90. DINT;
  91. // Initialize PIE control registers to their default state.
  92. // The default state is all PIE interrupts disabled and flags
  93. // are cleared.
  94. // This function is found in the DSP2833x_PieCtrl.c file.
  95. InitPieCtrl();
  96. // Disable CPU interrupts and clear all CPU interrupt flags:
  97. IER = 0x0000;
  98. IFR = 0x0000;
  99. // Initialize the PIE vector table with pointers to the shell Interrupt
  100. // Service Routines (ISR).
  101. // This will populate the entire table, even if the interrupt
  102. // is not used in this example. This is useful for debug purposes.
  103. // The shell ISR routines are found in DSP2833x_DefaultIsr.c.
  104. // This function is found in DSP2833x_PieVect.c.
  105. InitPieVectTable();
  106. // Step 4. Initialize all the Device Peripherals:
  107. // This function is found in DSP2833x_InitPeripherals.c
  108. // InitPeripherals(); // Not required for this example
  109. // Step 5. User specific code:
  110. #if EXAMPLE1 2.//这里开始对应上面的宏定义
  111. //由于上面只有EXAMPLE1=1,所以只执行EXAMPL                                                   //E1对应的条件语句,从而条用函数Gpio_example1()
  112. // This example uses DATA registers to toggle I/O's
  113. Gpio_example1();
  114. #endif // - EXAMPLE1
  115. #if EXAMPLE2
  116. // This example uses SET/CLEAR registers to toggle I/O's
  117. Gpio_example2();
  118. #endif
  119. #if EXAMPLE3
  120. // This example uses TOGGLE registers to toggle I/O's
  121. Gpio_example3();
  122. #endif
  123. }
  124. void delay_loop()
  125. {
  126. short i;
  127. for (i = 0; i < 1000; i++) {}
  128. }
  129. void Gpio_example1(void) 3.//这里EXAMPLE1跳转过来的函数
  130. {
  131. // Example 1:
  132. // Toggle I/Os using DATA registers
  133. for(;;)
  134. {
  135. GpioDataRegs.GPADAT.all =0xAAAA; 4.//这里写入GPADAT,是对GPIO0~GPIO31作为通用I/O口时的引脚的状态。这里只写了低16位1010 1010 1010 1010,高16位为0000 0000 0000 0000
  136. delay_loop();
  137. GpioDataRegs.GPADAT.all =0x5555; //这里同上,将低16位写入0101 0101 0101 0101
  138. delay_loop();
  139. }
  140. }
  141. void Gpio_example2(void)
  142. {
  143. // Example 2:
  144. // Toggle I/Os using SET/CLEAR registers
  145. for(;;)
  146. {
  147. GpioDataRegs.GPASET.all =0xAAAA; 5.//这里是通过GPASET来驱动引脚GPIO0~GPIO31相应位为高电平
  148. GpioDataRegs.GPACLEAR.all =0x5555; 6.//这里通过GPACLEAR来驱动引脚GPIO0~GPIO31相应位为低电平
  149. delay_loop();
  150. GpioDataRegs.GPACLEAR.all =0xAAAA;
  151. GpioDataRegs.GPASET.all =0x5555;
  152. delay_loop();
  153. }
  154. }
  155. void Gpio_example3(void)
  156. {
  157. // Example 2:
  158. // Toggle I/Os using TOGGLE registers
  159. // Set pins to a known state
  160. GpioDataRegs.GPASET.all =0xAAAA;
  161. GpioDataRegs.GPACLEAR.all =0x5555;
  162. // Use TOGGLE registers to flip the state of
  163. // the pins.
  164. // Any bit set to a 1 will flip state (toggle)
  165. // Any bit set to a 0 will not toggle.
  166. for(;;)
  167. {
  168. GpioDataRegs.GPATOGGLE.all =0xFFFF; 7.//通过利用GPATOGGLE 来驱动GPIO0~GPIO31使引脚低16位电平反转
  169. delay_loop();
  170. }
  171. }
  172. void Gpio_select(void)
  173. {
  174. EALLOW;
  175. GpioCtrlRegs.GPAMUX1.all = 0x00000000; // All GPIO 8.//这部分是GPIO功能选择的配置,这里配置的全是作为通用GPIO口来使用
  176. GpioCtrlRegs.GPAMUX2.all = 0x00000000; // All GPIO
  177. GpioCtrlRegs.GPAMUX1.all = 0x00000000; // All GPIO
  178. GpioCtrlRegs.GPADIR.all 0x0FFF;   // GPIO0~GPIO11 outputs 9.//这里配置通用I/O口的输入输出方向
  179. EDIS;
  180. }
  181. //===========================================================================
  182. // No more.
  183. //===========================================================================

 

下面来实际操作一下,顺便再教大家一些观察变量的方法

具体载入项目我就不多说了,这里我就直接演示以后需要做的

1.下面是我已经加载好的项目


2.我们前面已经看过主函数了,我们在函数里将所有GPIO全部作为通用I/O口来使用,同时将GPIO作为输出口,我们在GPxDAT里面定义了初值用来驱动GPIO,所以我们这里就要监测GPxDAT能否正确装入初值。

首先,按照以前实验所讲的,想要监测什么就将该变量加入到“Add Watch Expression”当中。我们这里监测的变量是“GpioDataRegs.GPADAT.all



3.从上面能够看出,在还未运行之前,GpioDataRegs.GPACLEAR.all VALUE是一个随机数,为了更直观的观察,我们将VALUE的显示方式改成16进制。右键“VALUE”下面的值:



4.我们这里对GPxDAT进行了两次赋值,为了更好的观察变化,我们在两次赋值语句的地方加上断点(程序运行到断点时自动停下,再运行才能继续运行)。在该语句前双击就可以加上断点,再双击就取消断点。

http://s2/middle/0034sXQLzy73jDWuAyB01&690


5.下面开始运行,注意看“Watch”内的值

运行前:


第一次运行后:

http://s10/middle/0034sXQLzy73jDWVzRfa9&690

第二次运行后:

http://s8/middle/0034sXQLzy73jDWWEPd37&690


最后,在这里特别提醒一下,这也是我在写该教程时所遇到的,相信许多初学者都可能会遇到。虽然TMS320F28335开发板有着相同的特点,但是不同厂家生产的开发板内部GPIO等引脚的分布不一样(这一点需要看产品所附带的硬件原理图)。像我这里遇到的就是,我的GPIO12~GPIO15端口开发板上是作为四个独立按键,所以是作为通用输入的,默认输入高电平。而我原先用的程序里面(从上面也能看出来):

下面这是原来的:

GpioCtrlRegs.GPADIR.all 0xFFFF;   // All outputs

修改后:

GpioCtrlRegs.GPADIR.all 0x0FFF;   // GPIO0~GPIO11 outputs 

修改之前将GPIO12~GPIO15配置成输出,这个不太合理,因此我将GPIO12~GPIO15仍改成输入(这就类似GPIO60、GPIO61、GPIO2~GPIO7作为LED1~8输出,而不能作为输入一样)因此

GpioDataRegs.GPADAT.all    =0xAAAA; 

GpioDataRegs.GPADAT.all    =0x5555; 

也改成:

GpioDataRegs.GPADAT.all    =0x0AAA; 

GpioDataRegs.GPADAT.all    =0x0555; 

由于加载的项目不一定完全符合自己的开发板,所以以后在学习中遇到问题,希望大家能够分析自己的开发板的硬件差异来解决问题。

好,这一讲结束~






0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有