LM3S811寄存器操作有感(GPIO)



这一节我们操作寄存器进行GPIO的应用
1、端口控制寄存器RCGC2
寄存器RCGC2地址为0X400FE108,其功能为:运行模式时钟选通控制
其中5-31位保留   第4位对应GPIOE   第3位对应GPIOD   第2位对应PORTC  第1位对应PORTB  第0位对应PORTA

2、方向寄存器GPIODIR
对GPIO进行操作设置其方向是免不了的
实际地址:PA口为0X40004400 ,PB口为0X40005400,PC口为0X40006400,PD口为0X40007400,PE口为0X40024400(注意)

方向寄存器GPIODIR的  31:8位 保留  0:7位控制GPIO的方向 相应的管脚写0,此管脚为输入,相应的管脚写1,此管脚为输出

3、模式寄存器GPIOAFSEL
实际地址 PA口为0X40004420 ,PB口为0X40005420,PC口为0X40006420,PD口为0X40007420,PE口为0X40024420
模式寄存器GPIOAFSEL的  31:8位 保留 0:7位进行GPIO的模式控制  相应位为0表示此位作为普通IO口,相应位为1表示此位被当做片内外设
(相信学过430的朋友会很明白)
除了5个JTAG管脚(PB7 和 PC[3:0])之外,所有GPIO管脚默认都是输入管脚 (GPIODIR=0 且 GPIOAFSEL=0)。JTAG管脚默认为JTAG功能(GPIOAFSEL=1)

4、GPIO 2-mA 驱动选择GPIODR2R(它允许对端口的每个GPIO信号进行单独配置,而不会影响其他引脚)
实际地址0X40004500  31:8位 保留  0:7位配置输出电流是否为2mA  相应位为0表示不为2mA(默认情况下为2mA,当不为2mA时则可以重新配置为4或8mA),相应位为1表示输出电流为2mA

5、GPIO 4-mA 驱动选择GPIODR4R以及GPIO 8-mA 驱动选择GPIODR8R 其配置方式同GPIODR2R(只是寄存器实际地址不同而已)

在看例程之前先了解一些芯片的锁死问题
如果JTAG管脚在设计中用作GPIO,那么一定要小心了,否则会将芯片锁死,什么叫锁死呢、为什么会锁死?
其实是这样的,正常操作时当给芯片下载程序时JTAG管脚默认为JTAG功能,此时程序可以顺利下载进去,可是当你在程序中加入把JTAG口配置为GPIO功能的语句时,当芯片上电后Flash中的程序会立即执行,这会在瞬间把JTAG口配置为GPIO功能,可想而知你的程序肯定就下载不进去了,因为占用了JTAG口,
当然解决办法是有的,我们可以通过使用一个基于外部或软件的触发器来恢复JTAG功能,就可以避免锁死情况的发生。
具体是这样的:
编写一个按键检测函数,当检测到这个按键按下时执行死循环程序,把这个按键检测函数放在主函数的最开始位置,这时即使把JTAG配置为GPIO也不担心锁住。   
具体操作:先按下复位键,再按下用户定义的按键(按下的同时不要松开复位键),然后放开复位键,再放开用户按键即可。
原理:当按下复位键和用户键时程序从主函数处执行,最开始检测到用户按键的按下而进入死循环,所以下面的程序就再也没有执行了,所以就不会把JTAG配置为GPIO了(程序执行不到这一步了),所以就不会让芯片所死了。

接着看一个GPIO例程
#include  <hw_types.h>

void  JtagWait(void)//我们811板子上用户按键是PC4,按下按键为低电平
{
    HWREG(0x400FE108)|= 0x00000004;                 // 以全字(32位)方式访问硬件寄存器,选通GPIOC 模块的时钟
    HWREGBITW(0X40006400, 4) = 0;                     //PC4设置为输入(按键的输入)   GPIODIR
    HWREGBITW(0X40006420, 4) = 0;                     //PC4设置为通用IO口             GPIOAFSEL
    if(HWREGBITW(0X40006000, 4)==0)                 //0X40006000为PCDATA的地址,读PC4的状态
    while(1);//死循环,等待JTAG连接
}
void  delay(int z)
{
    int x;
    char y;
    for(x=z;x>0;x--)
       for(y=120;y>0;y--);
}
int   main()
{                                                    //!!!!!!!!!!!!!!!!!!!LED连接PD0,低电平点亮
   JtagWait();
   HWREG(0x400FE108)|= 0x00000008;                 // 以全字(32位)方式访问硬件寄存器,选通GPIOD 模块的时钟(用来驱动LED)
   HWREGBITW(0X40007400, 0) = 1;                     //PD0设置为输出                 GPIODIR
   HWREGBITW(0X40007420, 0) = 0;                     //PD0设置为通用IO口             GPIOAFSEL
   while(1)
   {
       //注:向GPIODATA数据寄存器写入数据时其位地址一定要左移两位
       //在写操作过程中,如果与数据位相关联的地址位被设为1,那么GPIODATA寄存器的值将发生变化。
       //如果被清零,那么该寄存器的值将保持不变。
       // ADDR[9:2]       9 8 7 6  5 4 3 2  1 0 (将0xEB的值写入地址GPIODATA+0x098处,u表示没有被写操作改变的数据。 )
                                                                                  
       //          0x098  0 0 1 0  0 1 1 0  1 0

       //           0xEB  1 1 1 0  1 0 1 1

       // GPIODATA  u u 1 u  u 0 1 u
       //如果使用PD0驱动LED,则0x01<<2=0x04;如果使用PD1驱动LED,则0x02<<2=0x08;如果PD0和PD1都进行驱动,则0x03<<2=0x0c;依此规律
       HWREGBITW(0X40007000+0x00000004, 0) = 1;//PD0=1,熄灭LED  0X40007000为PDDATA地址
       delay(100);
       HWREGBITW(0X40007000+0x00000004, 0) = 0;//PD0=0,点亮LED
       delay(100);
   }
}

如有不正确的地方还请指正。
    

                                                   

  • 建议你试用下TI的StellarisWare软件工具包~~

    //系统频率设置;采用主振荡器; 外接6M晶振;不分频;

           SysCtlClockSet(SYSCTL_USE_OSC|  

                  SYSCTL_OSC_MAIN|  

      SYSCTL_XTAL_6MHZ|  

                  SYSCTL_SYSDIV_1);

    //使能PB,PD口;  

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

    //设PD口为输出模式;          

    GPIODirModeSet(GPIO_PORTB_BASE,GPIO_PIN_0,GPIO_DIR_MODE_OUT);

            //进入LED亮灭死循环;

     while(1)

      {

         //点亮LED1;  

      GPIOPinWrite(GPIO_PORTB_BASE,LED1,LED1);

         //延时1秒;

    SysCtlDelay(SysCtlClockGet()/3);

     //熄灭LED1;

      GPIOPinWrite(GPIO_PORTB_BASE,LED1,~LED1);

         //延时1秒;

          SysCtlDelay(SysCtlClockGet()/3);

    }