zoukankan      html  css  js  c++  java
  • S3C2440的GPIO编程

    一、初步认识S3C2440A

    【S3C2440A简介】

    S3C2440A是三星公司推出的基于ARM920t内核的32/16位RISC微处理器。主要用于手持设备和中高端电子产品中。它内部集成16k数据cashe、16k指令cashe,内存管理单元MMU,4KBSRAM(片内内存), nandflash控制器,LCD控制器,USB控制器,中断控制器,支持60个中断源,4通道PWM定时器,1个看门狗定时器。24个外部中断源,两通道SPI。具有PLL片上时钟发生器。片内集成RTC实时时钟芯片。8通道10位的A/D转换器,4通道DMA、系统主频400MHZ,最高533MHZ,通过软件设置。130个多用输入输出口。3通道UART。

    二、2440的GPIO口及其控制方法

    2440有130个通用输入输出口(GPIO口),分为GPA、GPB、GPC、GPD、GPE、GPF、GPG、GPH、GPI、GPJ共9组,每个端口有三组寄存器来控制,分别是GPxCON(GPx设置寄存器,用于设置引脚是输入、输出、还是其他功能)、GPxDAT (GPx数据寄存器,用于读写引脚的电平值)、GPxUP(GPx上拉电阻寄存器,用于确定引是否使用上拉电阻)

    GPxCON寄存器的功能]:GPx配置寄存器用于确定x端口(x取B~J)是输入、输出、还是其他功能。通过写此寄存器来配置相应引脚的功能,其中每两位控制一个引脚的功能。特别要注意的是2440上电复位后GPIO都默认为输出模式。

    [D1:D0]=[0:0] 输入功能

    [D1:D0]=[0:1] 输出功能

    [D1:D0]=[1 :0] 特殊功能 (中断,PWM,UART、AD。。。。)

    [D1:D0]=[1 :1] 未定义其功能

    [GPxDAT寄存器的功能]:当引脚被设置为输出时,它的每一位控制一个引脚输出高电平还是低电平低,当引脚设置为输入时,可以通过读次寄存器的值来判断对应引脚电平的高低。

    [GPxUP上拉电阻使能寄存器的功能]:GPxUP寄存器的m位用于确定X端口(B~J)的第m个引脚是否用上拉电阻,[m位]=1:不适用上拉电阻[m位]=0:使用上拉电阻。

    上拉、下拉电阻的作用是当GPIO口既不是高电平、也不是低电平、而是高阻状态时,由上拉电阻把引脚的电平确定为一个确定的值(高或低)。

    三、GPIO实验(led、蜂鸣器、键盘)

    一:首先,搭建好开发环境:

    开发环境建议windowsXP(如果是win7建议换装XP系统,后续很多软件不兼容),安装好usb下载驱动、usb转串口驱动、和keil4集成开发环境。硬件上需要usb转串口线、usb下载线、以及电源线,(因为刚买到的板子一般都已经预装了bootloader因此JTAG暂时没用)。

    二:添加启动文件:

    这儿我们要把2440当单片机来使用,但是不同的是2440一上电,系统的看门狗定时器是开着的,它会倒数计时,3秒不去关它,它就会让系统重启。而且CPU外接的64KSDRAM(内存)未初始化不能用,只能用片内的4KRAM,所以还需要初始化系统SDRAM,而且刚一上电系统的主频12M很低,可以通过软件来提高主频。因此,在编写mian()函数前首先要编写系统的初始化代码。具体地说来就是要1:关闭看门狗(必做)2:初始化内存(视情况而定,选做)3:设置系统主频(选作)4:设置好堆栈,调用main()函数(必做)。详细代码及解释如下,如果难以理解,其实keil4编译器已经帮我们写好了启动代码head.s,直接点击是添加即可。

    n 2440启动代码:

    [原理]2440一上电,系统的看门狗定时器是开着的,它会倒数计时,3秒不去关它, 它就会让系统重启。而且CPU外接的64KSDRAM(内存)未初始化不能用, 只能用片内的4KRAM,所以还需要初始化系统SDRAM,而且刚一上电系统的 主频12M很低,可以通过软件来提高主频。因此,在编写mian()函数前首 先要编写系统的初始化代码

    [步骤]:

    1:关闭看门狗(必做)

      2:初始化SDRAM(选作)

          3:初始化系统时钟 (选作)

    4:设置好堆栈调用main()函数(必做

    /***************************************************************************************************/

    实验1:GPIO输入操作之——控制4个led

    [原理]:硬件上led1~led4分别接2440的GPB5,GPB6,GPB7,GPB8,低电平点亮led。

    软件上GPBCON寄存器两位控制1个引脚为输入输出还是其它功能

    GPBDAT寄存器写0对应引脚输出低电平写1对应引脚输出高电平。

    [步骤]:1:设置GPBCON寄存器为输出模式,往寄存器里面写00为输入01为输入

              2:写GPBDAT中的某一位为1输出高电平,写0输出低电平。

    /********************************************************************************************/

    练习1:用软件延时方法让四个led闪烁

    /*********************************************************************************************/

    /*宏定义,定义GPBCON寄存器GPBDAT寄存器,可以直接包含系统提供的库函数,包含头文件即可#incldue<s3c2440.h>*/

    #define GPBCON   (*(volatile unsigned long *) 0x56000010)

    #define GPBDAT   (*(volatile unsigned long *) 0x56000014)

    #define uint unsigned int

    /*延时函数*/

    void delay(uint aa)

    {

    uint i,j;

    for(i=50000;i>0;i--)

    for(j=aa;j>0;j--)

    {}

    }

    /*主函数*/

    void main(void)

    {

    GPBCON=0x15400;//GPB5~GPB8全部设置为输出模式0001 0101 0100 0000 0000

    while(1)

    {

    GPBDAT=0x00000001;//GPB5~GPB8全部输出高电平,4个led全亮

    delay(300);

    GPBDAT=0x000001e0;//GPB5~GPB8全部输出高电平,4个led全灭 

    delay(300);

    }

    }

    /*********************************************************************************************/

    练习2:用数组实现流水灯

    /*********************************************************************************************/

    #include<s3c2440.h>

    #define uint unsigned int

    uint led[]={0x000001c0,0x000001a0,0x00000160,0x000000e0};

    void delay(uint aa);

    int main(void)

    {

    char i;

    GPBCON=0x00015400;//01 0101 0100 0000 0000

    while(1)

    {

    for(i=0;i<4;i++)

    {

    GPBDAT=led[i];

    delay(300);

    }

    }

    return 0;

    }

    void delay(uint aa)

    {

    uint i,j;

    for(i=50000;i>0;i--)

    for(j=aa;j>0;j--)

    {}

    }

    注意:led数组的类型不能是unsigned char型,因为数组值大于uchar型,数据溢出,导致程序出错。

    /*********************************************************************************************/

    练习3:蜂鸣器滴滴的鸣叫实验

    /***************************************************************************************************/

    #include<s3c2440.h>

    #define uint unsigned int

    #define beep_on  0x00000001

    #define beep_off 0x00000000

    void delay(uint aa);

    int main()

    {

    GPBCON=0x00000001;

    while(1)

    {

    GPBDAT=beep_on;

    delay(100);

    GPBDAT=beep_off;

    delay(100);

    }

    return 0;

    }

    void delay(uint aa)

    {

    uint i,j;

    for(i=50000;i>0;i--)

    for(j=aa;j>0;j--)

    {}

    }

    /***************************************************************************************************/

    练习4:通过循环左移右移实现流水灯

    /*********************************************************************************************/

    #include<s3c2440.h>

    #define uint unsigned int

    #define uchar unsigned char

    void delay(uint aa);

    void main(void)

    {

    uint i,j;

    GPBCON=0x00015400;

    while(1)

    {

    for(i=5;i<=8;i++)

    {

    GPBDAT=~(1<<i);

    delay(100);

    }

    }

    }

    void delay(uint aa)

    {

    uint i,j;

    for(i=60000;i>0;i--)

    for(j=aa;j>0;j--)

    {}

    }

    /*********************************************************************************************/

    GPIO操作之---6个独立按键驱动

    [原理]:低电平按键按下

    六个输入引脚: EINT8   ---- (GPG0)  --- K1

    * EINT11  ---- (GPG3)  --- K2

    * EINT13  ---- (GPG5)  --- K3

    * EINT14  ---- (GPG6)  --- K4

    * EINT15  ---- (GPG7)  --- K5

    * EINT19  ---- (GPG11) --- K6 (按下低电平)

    /**********************************************************************************************/

    练习5:按下按K1键时蜂鸣器名叫,松开k1手时蜂鸣器停止名叫

    /*********************************************************************************************/

    /*按下k1键蜂鸣器鸣叫、松开手时,蜂鸣器停止鸣叫*/

    #include<s3c2440.h>

    int main()

    {

    GPBCON=0x00000001;

    GPGCON=0x00000000;

    while(1)

    {

    if((GPGDAT&0x00000001)==0)

    GPBDAT=0x00000001;

    else

    GPBDAT=0x00000000;

    }

    return 0;

    }

    /*********************************************************************************************/

    练习6:k1按下时led全部闪动,松开手时led流动

    /*********************************************************************************************/

    #include<s3c2440.h>

    #define uint unsigned int

    #define uchar unsigned char

    void led_liu();

    void delay(unsigned int aa);

    void led_jump();

    void main()

    {

    GPBCON=0x00015400;//01 0101 0100 0000 00005678设置为输出模式

    GPGCON=0x00000000;//GPG全部设置为输入

    while(1)

    {

    if((GPGDAT&0x00000001)==0)

    led_jump();

    else

    led_liu();

    }

    }

    void led_liu()

    {

    uchar i,aa=10;

    for(i=5;i<=8;i++)

    {

    GPBDAT=~(1<<i);

    delay(100);

      }

    }

    void led_jump()

    {

    uchar aa=10;

    GPBDAT=0x00000000;//00000

    delay(300);

    GPBDAT=0x000001e0;//0001 1110 0000

    delay(300);

    }

    void delay(unsigned int aa)

    {

    uint i,j;

    for(i=50000;i>0;i--)

    for(j=aa;j>0;j--)

    {}

    }

    【总结】GPGDAT&0x00000001这句很重要,分析为什么这样写??                                                             

    /*********************************************************************************************/

    练习7:按下k1~k4时对应点亮led1~led4*/

    /*********************************************************************************************/

    #include<s3c2440.h>

    void main()

    {

    char aa=5;

    GPBCON=0x00015400;//01 0101 0100 0000 0000

    GPGCON=0x00000000;

    while(1)

    {

    if((GPGDAT&0x00000001)==0)

    aa=5;

    if((GPGDAT&0x00000008)==0)

    aa=6;

    if((GPGDAT&0x00000020)==0)

    aa=7;

    if((GPGDAT&0x00000040)==0)

    aa=8;

    GPBDAT=~(1<<aa);

    }

    /********************************************************************************************

    按键k1按下去之后、蜂鸣器名叫、松开手时、蜂鸣器停止名叫。(主要是位操作的正确方法)

    *********************************************************************************************/

    #include<s3c2440.h>

    int main()

    {

    GPBCON=GPBCON&0xfffffffc|0x00000001;//*1100 仅仅将GPB0设置为输出模式、而不改变其他位

    GPGCON=GPGCON&0xffffff3c;//111 0011 1100 仅仅将GPG0和GPG3设置为输入模式、而不改变其他位

    while(1)

    {

    if((GPGDAT&0x00000001)==0)

    GPBDAT=GPBDAT&0xfffffffe|0x00000001;//仅仅将GPB0设置为1、其他位的电平不要发生变化

    else

    GPBDAT=GPBDAT&0xfffffffe;//仅仅将GPB0设置为0、而不影响其他位

    }

    return 0;

    }

  • 相关阅读:
    this指向详解
    领域驱动设计-1-概述
    算法 表达式求值
    进制转换
    IDEA Junit FileNotFoundException: class path resource [spring/spring.xml] cannot be opened because it does not exist
    aes加密示例
    create an oauth app
    搭建docusaurus博客
    Vue项目整体架构记要
    vue+element 获取验证码
  • 原文地址:https://www.cnblogs.com/summer-xwq/p/4147883.html
Copyright © 2011-2022 走看看