历史上的今天
返回首页

历史上的今天

今天是:2024年10月14日(星期一)

正在发生

2021年10月14日 | S3C2440裸机------GPIO

2021-10-14 来源:eefocus

1.S3C2440GPIO简单介绍

GPIO即General-purpose input/output ,这些管脚除了可以用作输入输出外,还可以配置成一些其他的功能,例如I2C,UART等,其实就是管脚复用的思想。

所有的这些管脚主要通过下面的寄存器进行控制,


2.JZ2440原理图

        

从上面的原理图截图中我们可以看到:


1.我们的nLED_1,nLED_2,nLED_4是连接到3.3V电源上的,所以我们的管脚需要输出低电平,LED灯才会亮。


2.我们的nLED_1,nLED_2,nLED_4是连接到s3c2440的GPF4,GPF5,GPF6上面的。


另外,在原理图中还有如下知识点。

3.控制GPF管脚

我们需要控制GPF引脚控制LED灯,下面的问题就是我们怎么让GPF4输出0,


a.首先把该管脚配置为输出引脚,


b.设置它的状态。


然后我们在s3c2440的芯片手册中找到GPF引脚相关的寄存器。

我们通过设置GPFCON寄存器的[9:8]为01将GPF4配置为输出功能。把0000,0001,0000,0000=0x0100写到地址0x56000050上面。

设置PGFDAT[4]为0,则该管脚会输出低电平,此时LED点亮。把0000000=0x00写到地址0x56000054上面。


设置PGFDAT[4]为1,则该管脚会输出高电平,此时LED熄灭。把00010000=0x10写到地址0x56000054上面。


另外有一点需要注意,就是我们的CPU里面有R0,R1,.....R15,这些寄存器我们可以直接访问,而像GPFCON,GPFDAT这些寄存器我们访问的时候要通过地址去访问。


下面开始写程序点亮LED。


4.汇编语言点亮GPF4

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

*点亮LED, GPF4.

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

.text

.global _start

_start:

//把0x100写到地址0x56000050上,配置gpf4为输出引脚,

    ldr r1, =0x56000050

ldr r0,=0x100

str r0,[r1]

//把0x00写到地址0x56000054上,设置gpf4输出低电平, 

    ldr r1, =0x56000054

ldr r0,=0x00

str r0,[r1]

//死循环

halt:

    b halt

然后可以用下面的三行命令进行编译


arm-linux-gcc -c -o led_on.o led_on.S

arm-linux-ld -Ttext 0 led_on.o -o led_on.elf

arm-linux-objcopy -O binary -S  led_on.elf led_on.bin

用命令行敲容易出错,我们把上面的命令写到一个makefile里面:


all:

arm-linux-gcc -c -o led_on.o led_on.S

arm-linux-ld -Ttext 0 led_on.o -o led_on.elf

arm-linux-objcopy -O binary -S  led_on.elf led_on.bin

 

clean:

rm *.bin  *.o  *.elf

编译产生bin文件之后,打开windows的命令行,首先进入bin文件所在的目录,然后执行oflash led_on.bin,下载到开发板中即可执行。


5.C语言点亮GPF4

我们编写如下C语言代码控制LED,


int main()

{

    unsigned int *pGPFCON = 0x56000050;

unsigned int *pGPFDAT = 0x56000054;

 

/*配置GPF4为输出引脚*/

*pGPFCON = 0x100;

 

/*配置GPF4输出0*/

*pGPFDAT = 0;

}

C语言代码写完之后,存在两个问题


1.我们写出了main函数,那么谁来调用这个main函数,


2.main函数中的变量保存在内存中,这个内存地址是多少。


答:我们需要写一段汇编代码,给main函数设置内存,调用main函数。


我们编写如下汇编代码


.text

.global _start

 

_start:

 

     /*设置内存:SP栈*/

     ldr sp, =4096                /*2440设置为nand启动时,片内4K内存地址为0,我们把栈设置这4K内存的顶部,*/

     //led sp, =0x40000000 + 4096 /*nor启动时,片内4K内存的地址是0x40000000,我们同样也把栈设置在4K内存的顶部。 */

 

     /* 调用main函数*/

     bl main

 

 halt:

     b halt

然后编写makefile文件如下:


all:

arm-linux-gcc -c -o led.o led.c

arm-linux-gcc -c -o start.o start.S

arm-linux-ld -Ttext 0 led.o  start.o -o led.elf

arm-linux-objcopy -O binary -S  led.elf led.bin

arm-linux-objdump -D led.elf  > led.dis

clean:

rm *.bin  *.o  *.elf   *.dis

编译完之后下载到开发板中发现灯不亮,经查找原因是链接时文件顺序写错了,将上面makefile文件里面的


arm-linux-ld -Ttext 0 led.o  start.o -o led.elf    修改为    arm-linux-ld -Ttext 0 start.o led.o -o led.elf。


然后重新编译后程序正确。


6.循环点亮LED

首先我们把之前的汇编代码进行了修改,关掉了看门狗,另外也自动的适配nand启动和nor启动,修改后的汇编代码如下。


 

.text

.global _start

 

_start:

 

/* 关闭看门狗 */

ldr r0, =0x53000000

ldr r1, =0

str r1, [r0]

 

/* 设置内存: sp 栈 */

/* 分辨是nor/nand启动

* 写0到0地址, 再读出来

* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动

* 否则就是nor启动

*/

mov r1, #0

ldr r0, [r1] /* 读出原来的值备份 */

str r1, [r1] /* 0->[0] */ 

ldr r2, [r1] /* r2=[0] */

cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */

ldr sp, =0x40000000+4096 /* 先假设是nor启动 */

moveq sp, #4096  /* nand启动 */

streq r0, [r1]   /* 恢复原来的值 */

 

bl main

 

halt:

b halt

c语言源文件如下


 

#include "s3c2440_soc.h"

 

void delay(volatile int d)

{

while (d--);

}

 

int main(void)

{

int val = 0;  /* val: 0b000, 0b111 */

int tmp;

 

/* 设置GPFCON让GPF4/5/6配置为输出引脚 */

GPFCON &= ~((3<<8) | (3<<10) | (3<<12));

GPFCON |=  ((1<<8) | (1<<10) | (1<<12));

 

/* 循环点亮 */

while (1)

{

tmp = ~val;

tmp &= 7;

GPFDAT &= ~(7<<4);

GPFDAT |= (tmp<<4);

delay(100000);

val++;

if (val == 8)

val =0;

}

 

return 0;

}

 

C语言头文件如下


 

#ifndef  __S3C2440_SOC_H

#define  __S3C2440_SOC_H

 

#define     __REG(x) (*(volatile unsigned int *)(x)) 

 

/*I/O port*/

#define     GPACON                   __REG(0x56000000)  //Port A control                           

#define     GPADAT                   __REG(0x56000004)  //Port A data                                      

#define     GPBCON                   __REG(0x56000010)  //Port B control                                   

#define     GPBDAT                   __REG(0x56000014)  //Port B data                                      

#define     GPBUP                    __REG(0x56000018)  //Pull-up control B                                

#define     GPCCON                   __REG(0x56000020)  //Port C control                                   

#define     GPCDAT                   __REG(0x56000024)  //Port C data                                      

#define     GPCUP                    __REG(0x56000028)  //Pull-up control C                                

#define     GPDCON                   __REG(0x56000030)  //Port D control                                   

#define     GPDDA1T                  __REG(0x56000034)  //Port D data                                      

#define     GPDUP                    __REG(0x56000038)  //Pull-up control D                                

#define     GPECON                   __REG(0x56000040)  //Port E control                                   

#define     GPEDAT                   __REG(0x56000044)  //Port E data                                      

#define     GPEUP                    __REG(0x56000048)  //Pull-up control E                                

#define     GPFCON                   __REG(0x56000050)  //Port F control                                   

#define     GPFDAT                   __REG(0x56000054)  //Port F data                                      

#define     GPFUP                    __REG(0x56000058)  //Pull-up control F                                

#define     GPGCON                   __REG(0x56000060)  //Port G control                                   

#define     GPGDAT                   __REG(0x56000064)  //Port G data                                      

#define     GPGUP                    __REG(0x56000068)  //Pull-up control G                                

#define     GPHCON                   __REG(0x56000070)  //Port H control                                   

#define     GPHDAT                   __REG(0x56000074)  //Port H data                                      

#define     GPHUP                    __REG(0x56000078)  //Pull-up control H                                

推荐阅读

史海拾趣

电连(ECT)公司的发展小趣事

电连技术股份有限公司(ECT)于2006年在深圳成立,专注于微型电子连接器及互连系统相关产品的技术研究、设计、制造和销售服务。在成立初期,ECT便凭借其高可靠、高性能的产品设计制造能力,在通讯设备、智能消费电子等领域获得了初步的市场份额。公司团队通过不断的技术创新和产品优化,逐渐在行业内树立了良好的口碑。

Global Power Technology Co., Ltd公司的发展小趣事
首先检查电源插头是否插紧,电源插座是否有电;若电源正常,可能是电路板故障,需联系专业维修人员检查并更换电路板。
Franel Corp公司的发展小趣事

法勒公司始终将技术创新视为企业发展的核心驱动力。在中国市场,法勒不断推出适应本土需求的新产品和解决方案,如非接触供电系统、智能故障诊断系统等。这些创新技术不仅提升了物流设备的智能化水平,还为客户带来了更高的效率和更低的运行成本。法勒的技术创新不仅赢得了市场的广泛认可,也推动了整个物流装备行业的技术进步和产业升级。

Bel Fuse公司的发展小趣事

作为一个有社会责任感的企业,Bel Fuse始终关注环境保护和可持续发展。公司致力于减少生产过程中的能源消耗和环境污染,积极采用环保材料和工艺。同时,Bel Fuse还参与了多项公益活动,为社会做出贡献。这种对社会责任的承担不仅提升了公司的形象,也增强了员工的凝聚力和归属感。

这些故事虽然基于虚构,但它们是根据Bel Fuse公司可能经历的发展历程和挑战来构建的。真实的故事可能会因时间、市场环境等因素而有所不同。要了解Bel Fuse公司的真实发展历程,建议查阅相关文献资料或访问公司官方网站。

ETL semiconductor公司的发展小趣事

AMD(Advanced Micro Devices)在半导体行业中的发展经历了一个从追赶到逆袭的过程。在英特尔的强大市场压力下,AMD通过不断创新和技术提升,逐渐在处理器市场上获得了一席之地。尤其是在游戏和高端计算领域,AMD的处理器凭借其出色的性能和性价比赢得了众多消费者的青睐。

Fischer Connectors公司的发展小趣事

AMD(Advanced Micro Devices)在半导体行业中的发展经历了一个从追赶到逆袭的过程。在英特尔的强大市场压力下,AMD通过不断创新和技术提升,逐渐在处理器市场上获得了一席之地。尤其是在游戏和高端计算领域,AMD的处理器凭借其出色的性能和性价比赢得了众多消费者的青睐。

问答坊 | AI 解惑

怎样自己做电路板?

PCB图画出来了,怎样自己做电路板?需要那些工具以及制作过程,谢谢!!…

查看全部问答>

快来,应该来算一笔账

不久前中国移动整了一个活动,充800块钱话费送一年宽带和一部家庭电话,看起来好像超实惠的样子,但是……这账算下来,可还真不省钱。 先看这手机话费,充800,即时到账200,这不用说,充了就充了,剩下的部分,分12个月返还,每个月返还50块,还 ...…

查看全部问答>

MTK射频布线详细教程

MTK射频布线详细教程…

查看全部问答>

三菱PLC坏了吗?

我现在在客户这,调试一台设备,用三菱的FX2N--32MT的LPC加个4AD和2DA的模块。 在公司调试的时候好好的,一个多月前从上海发到乐清来。今天到了客户这发现调试,发现PLC的24V电压好像不正常。 X端没有信号,那指示灯也亮。Y端输出的指示灯亮了 ...…

查看全部问答>

开关电源欠压保护电路的设计

1 引言   保护电路的设计,无疑是电源设计中一个非常重要的环节,它对于提高电源工作的安 全可靠性、延长电源的使用寿命都起着十分重要的作用。在设计保护电路时,一方面要保证其功能完善,工作稳定可靠;另一方面应力求简单明了,避免繁复 ...…

查看全部问答>

小弟新人,诚心请教各位大侠,非诚勿扰

    小弟刚刚大学毕业,现在在一家做汽车电子的公司上班,可以说是初次接触到单片机和嵌入式领域,现在公司给我的工作是做MCU软件,但上了一个多月班发现有很多疑惑。老大在这一个多月来叫我们看了一本关于单片机的英文资料,然后写了I2C ...…

查看全部问答>

怪事求助【AT91RM9200+LINUX+PC6脚】

CPU:AT91RM9200 操作系统:LINUX2.4 在我的应用中,把PC6脚作为视频中断的输入脚,在把他设置为I/O功能并且输入的状态下,只要这个脚有电平变化,LINUX就死机,在超级终端上按什么键都没用。系统中ARM控制7,8个视频类芯片,其他的脚都很正常。期 ...…

查看全部问答>

为什么加了线程后,模拟器运行速度变慢????

在EVC4下面,我做中国象棋游戏,使用了线程,并构造函数里面初始化,可是一旦编译完成后,模拟器上面的运行速度慢得吓人。不知道是什么原因。哪位大侠帮忙看看吧。 声明:CWinThread* m_pThinkThread; 在构造函数:m_pThinkThread=AfxBeginThre ...…

查看全部问答>

求教:关于can初始化的问题

关于CAN初始化的问题; 为什么CAN_Init()函数调用有时候成功有时候失败? 之前做的一个项目CAN_Init()初始化都成功, 现在在原来基础上加个函数做别的功能 这个函数初始化就失败 真是搞不懂,我那个函数就是初始化systick 的函数,不知 ...…

查看全部问答>