历史上的今天
返回首页

历史上的今天

今天是:2025年02月20日(星期四)

正在发生

2021年02月20日 | 基于S3C6410的ARM11学习(九) 点亮led

2021-02-20 来源:eefocus

之前已经对S3C6410的核心初始化完成了,但是这个也只是完成了,但是程序到底对不对了,还需要验证。最简单的验证方法是什么了,就是点亮led。如果在核心初始化完成后,我们写程序去点亮了led,就说明初始化代码是没有问题。


下面就要来点亮led了。这个时候就和开发板的原理图有关系了。我用的是OK6410的开发板,打开对应原理图。

         clip_image002

找到4个灯,是共阳接法的。所以要点亮对应的灯,就要使led的负端为低电平。在看看各个led负端端口对应的S3C6410的哪个IO。

   clip_image004

从核心板的原理图可以看出,4个LED是接在GPM0-3这四个管脚上的。


有了这个信息,我们只要去控制这四个管脚输出不同的电平,就能实现led的亮灭了。


打开6410的手册。直接看GPIO这一章。

clip_image006

表中列出了所有的GPIO,总共分为17组,从A-Q。每一组有不同的管脚数。控制IO功能是通过GPxCON寄存器来控制的。控制IO管脚上数据是通过GPxDAT来控制的。我们这里就以GPM为例说明。

     clip_image008

上图说明GPM的IO操作有3个寄存器。


先看第一个寄存器,GPMCON

clip_image010

GPM组共有6个IO管脚。所以这个寄存器中,分成了6组,每一组控制对应的IO的功能。这里,我们是要使GPM0-3为输出。所以低16位就要设置为16’b0001_0001_0001_0001。

这样,就将GPM0-3设置为输出了。

        

在看第二个寄存器,GPMDAT。

clip_image012

手册也说得比较清楚,当IO为输入的时候,记录的是IO脚上的电平。当作为输出的时候,记录的是IO上输出的电平。所以当我们要让GPM0-3都输出低电平的话,那么这个寄存器的后4位就要写入4’b0000。

       

第三个寄存器,GPMPUD

         clip_image014

这个是设置IO管脚上下拉电阻的。


以上三个寄存器就是IO的基本寄存器了。每一组的IO都有上诉的3个寄存器。


下面我们就要来写程序了。这里,我写的是流水灯,初始,4个灯为亮灭亮灭,每隔一段时间,灯的状态就翻转一次,


流程:

1、设置对应IO为输出

2、设置IO输出值

3、每隔一段时间对IO输出值取反


下面就是对应的程序了,将流水灯写成一个函数,在reset中调用。

clip_image015

1、先定义GPMCOM和GPMDAT地址。

2、将r0的值设置为0x1111。这个值之前分析过,将GPM0-3设置为输出的值

3、将GPMCON地址装载到r1寄存器

4、将r0的值写入到r1寄存器代表的寄存器中,这样就配置GPM0-3为输出

5、将r0的值设置为0x5。这个用来配置GPM0-3输出的值

6、将GPMDAT地址装载到r1寄存器

7、将r0的值写入到r1寄存器代表的寄存器中,这样就配置GPM0-3输出值为4’b0101

8、将lr的值保存在r4寄存器中。因为这个时候lr寄存器保存的是调用clip_image016

这样,就完成了整个程序的设计了。将该程序,编译链接下载到开发板中,运行,就会看到led在不停的闪烁了。


对比STM32,操作可就要麻烦一些了。

首先看下系统结构,看看GPIO是挂在什么总线上的。因为之前说过,STM32是有外设门控时钟的。要使用某外设,就必须要打开对应外设的时钟。这是和ARM11很不一样的一点。

clip_image018

GPIO是挂在APB2总线上的,所以我们打开时钟的时候要去打开APB2上对应GPIO时钟。图中可以知道,GPIO是分为7组的。从A-G。


到GPIO章节去看。

clip_image020

功能描述就说明了,对应每个GPIO端口,有哪些寄存器来控制。STM32是有7个寄存器来进行控制。


STM32的GPIO比S3C6410的GPIO要复杂多了,因为GPIO可以配置为8种模式。clip_image022

下面是GPIO的基本结构

clip_image024

8种模式中,对推挽式输出和推挽式复用输出说明一下。这两个的输出结构都是一样的,使用CMOS的结构。但是不一样的是不同功能所使用模式不一样。推挽式输出是IO端口作为普通输出时的模式,而推挽式复用输出是IO作为特殊功能时作为输出的模式,比如有的IO有串口输出功能,当使用串口输出功能的时候,就要把IO的模式设置为推挽式复用输出。


输入的话,就没有什么好说的,从名字也可以看的出来。注意的是模拟输入,当使用芯片的内部AD时,IO是要设置为模拟输入的。


下面就要看看各个寄存器

1、GPIOx_CRL寄存器

clip_image026

这个是设置GPIO组的低8位的IO功能。每4位对应一个IO。高两位是配置IO的模式。低两个是配置IO作为输入还是输出,以及作为输出的最大速度是多少。


2、GPIOx_CRH寄存器

clip_image028

和GPIOx_CRLclip_image030

从描述中得到,这个寄存器保存的IO的状态,其实就是IO上的电平。而且这个寄存器只能读。当IO作为输入的时候,我们来读这个寄存器就知道IO上的电平了。


4、GPIOx_ODR寄存器

clip_image032

这个寄存器就是设置IO的输出了。低16位,每一位对应一个IO。当IO作为输出,可以往这个寄存器写值,就实现了IO输出了。


5、GPIOx_BSRR寄存器

clip_image034

这个寄存器,就是对输出值影响的。可以对输出清零,也可以对输出置1.


6、GPIOx_BRR寄存器

clip_image036

看描述就知道功能了


7、GPIOx_LCKR寄存器

clip_image038

STM32对IO加了一个锁的功能,就是可以将IO给锁起来,这样就不能对IO进行改变了。这个功能就是由这个寄存器来设置的。要锁某个IO的话,先将对应IO位的值设置为1,锁定端口配置,然后往16位写入特定的序列,就实现了IO的锁的功能了。在系统复位前,这锁功能一直有。


知道了对应相关的寄存器了,就知道怎么使用STM32的管脚来控制流水灯了。


流程

1、打开对应IO的时钟使能

2、配置CRL或CRH,使IO作为输出,模式就推挽式输出,最大速度是50M。

3、配置ODR寄存器,使寄存器输出我们想要的值


以配置GPIOA0-3为例说明。


首先打开GPIOA时钟。这个在RCC_APB2ENR寄存器中

clip_image040

clip_image042

第2位控制GPIOA的时钟使能。那么就把这一位置1就好了。但是怎么操作这个寄存器了。当然,我们可以向S3C6410一样,使用指针,去指向这个寄存器的地址,然后再对这个地址操作。但是,官方库已经给我们定义好了这些寄存器了,我们只要直接使用就好了。


在官方给的库(V3.5)中,有两个文件夹,一个inc,一个src

clip_image044

inc里面就是一些头文件,src里面就是具体的函数实现。库将每个外设都封装好了一个头文件和一个c文件。里面就定义了各个外设的寄存器,以及一些库函数,使用这些库函数就可以直接操作这些外设寄存器,而不用和底层的寄存器打交道了。因为STM32的寄存器实在是太多了,每次操作都查表的话,那可是很累的。而且直接操作寄存器的话,代码不直观,不知道配置到底是什么作用的。


这里,我们先用寄存器来进行操作。然后再用库函数来进行操作。在对比

寄存器版本:

寄存器版本的话就和inc和src下面的库文件没有多大关系了。直接打开stm32f10x.h,这个是在官方提供的库CMSIS目录下。

clip_image046

这个头文件定义了stm32f10x系列的所有寄存器对应的地址,相当于51单片机的reg51.h。

clip_image048

这里定义RCC的结构体,里面包含了RCC的各个寄存器。我们这里要用的就是其中的APB2ENR寄存器。因为这个寄存器里面有对GPIOA的时钟有效设置。在STM32中,对寄存器定义都是放在对应功能的结构体中去了,因为这些寄存器是严格4字节对齐的,所以只要放在结构体中,然后定义结构体的首地址,那么后面每个寄存器的地址也就都知道了。上面就定义RCC的结构体。这个是管理时钟和复位功能的。


在去找RCC的地址

clip_image050

这样,我们就可以直接访问了。


使用RCC->APB2ENR就可以访问RCC下的APB2ENR寄存器了。之前说,要把这个寄存器的第二位置为1.所以

RCC->APB2ENR = 0x4;

配置GPIO

同样,也是先去找GPIO结构体。

clip_image051

里面就有上面这个结构体。在STM32中,对外设的寄存器定义都是放在结构体中去了,因为这些寄存器是严格4字节对齐的,所以只要放在结构体中,然后定义结构体的首地址可以知道所有寄存器地址。上面就定义GPIO的结构体。


然后再去找GPIOA,因为我们要对这一组GPIO操作。


我从里面把关键的弄出来了

clip_image053

先定义了外设的基地址,然后再定义APB2的基地址,因为GPIO都是挂在APB2总线上的。然后不同的GPIO组的地址就是APB2基地址加上偏移地址就得了。然后再将这个GPIO组的基地址强制转化为GPIO结构体的首地址。这样不就知道了GPIO组的每个寄存器的地址了。


GPIOA0-3是由GPIOA_CRL配置的,所以就去配置这个寄存器。使用GPIOA->CRL对这个寄存器访问。要设置为输出,最大速度50M,模式为推挽式输出。


代码:GPIOA->CRL = 0x3333

这样就配置好了GPIOA0-3作为输出了,然后就要设置输出值了,假设设置为0101,那么就是去控制ODR寄存器。


代码:GPIOA-ODR = 0XA

这样,我们就实现了配置GPIOA0-3作为输出,输出值为0101了。至于点灯的程序,这里就不写了,就一直操作ODR寄存器就行了。


下面说下库函数开发:

有了库,你会发现STM32的开发变得非常简单。


对于GPIO,打开src目录下的stm32f10x_gpio.h这个文件,这个里面定义了关于GPIO操作的库函数操作的参数以及函数。

clip_image055

clip_image057

里面定义了GPIO初始化的一个结构体,当我们要初始化一个GPIO,就往这个结构体里面填值就行了。填的值可不是乱填的。而是在这文件中规定好的。


第一个值,对应下面的各个参数。表示是配置哪一个GPIO,总共16个。可以使用|操作。

clip_image059

第二个值是枚举类型,设置GPIO的速度

clip_image060

第三个值也是枚举类型,设置的IO的模式

clip_image061

下面我们就只要定义一个结构体,往这结构体里面的参数赋值,然后再调用GPIO的初始化函数就搞定了。

clip_image063

代码就是上面这样,怎么样,这比用寄存器开发要简洁很多吧。一看就知道代码功能是什么。就设置GPIOA的0-3管脚作为推挽式输出,速度是50M。完全不用去操作寄存器,因为库函数就帮我们做了这些事了。


GPIO_Init()这个函数是库函数,就是对外设进行初始化,初始化的参数就是填入的结构体的参数。有兴趣的可以去看看这个函数的实现,这个函数就在stm32f10x_gpio.c中。



我们还忘记了一件事了,那就是打开GPIOA的时钟了。这个时钟是受RCC管理的。去看stm32f10x_rcc.h文件。


这里,有一个函数

clip_image065

从这个名字就可以知道这个函数干嘛的,就是打开APB2总线上外设的时钟了。第一个参数是外设的名字,这个也是预先定义好的。第二个是状态,两个状态,ENABLE和DISABLE。

clip_image067

我们要打开GPIOA时钟,所以参数就是RCC_APB2Periph_GPIOA。


所以完整的GPIOA初始化代码就是

clip_image069

初始化搞定了,怎么来控制这个IO了。别着急,我们是有库函数的。

clip_image071

红色框中的4个函数就是控制IO输出的。从函数名都可以看出功能。第一个参数是GPIO组参数,即GPIOA-GPIOG。第二个参数GPIO_Pin就是指对哪一IO管脚控制,BitVal是指写入位的值是多少。PortVal值写入16位值是多少。


就调用以上这些函数,就可以实现控制IO输出了。


假设对GPIOA0-3都输出0

那么就直接调用

GPIO_ResetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);

这样,就将GPIOA0-3的管脚设置输出为低电平了。

        

以上,就是使用库函数来开发了。可以看出,库开发可以简化开发难度。不用来来回回的查表。而且代码有易懂性。一看就知道代码功能是什么了。


以上就是STM32操作GPIO,和S3C6410相比,多一个配置时钟使能,还有配置的寄存器也要多一些。其他是没有什么区别的。


这样,就完成了点亮LED了。当看到开发板led闪烁的时候,就说明我们的核心初始化代码是正确的。然后就可以开始进行下一步了。

推荐阅读

史海拾趣

C&K公司的发展小趣事

近年来,C&K在保持开关业务稳定发展的同时,还积极寻求新的增长点。为此,公司宣布成立了一个新的部门——C&K航空航天部。这个新部门旨在将公司在开关领域的专业技术与航空航天领域的需求相结合,为客户提供更先进、更可靠的系统解决方案。这一举措不仅展示了C&K在技术创新方面的实力,也为其未来的发展打开了新的大门。

这五个故事从不同角度展现了C&K公司在电子行业中的发展历程和成就。从磁芯记忆到微型开关的转型、成为世界领先的开关制造商、被ITT Industries收购与保持独立品牌、通过收购扩大全球业务与制造能力以及成立航空航天部拓展新领域,每一个阶段都充满了挑战与机遇。正是凭借着对技术创新的执着追求和对市场需求的敏锐洞察,C&K得以在激烈的竞争中脱颖而出,成为电子行业中的佼佼者。

Component Research Co公司的发展小趣事

面对不断变化的电子市场和技术环境,Component Research Co始终保持创新精神。公司不断投入研发资金,加强技术研发团队建设,推动新技术、新产品的不断涌现。同时,公司还积极关注市场动态和客户需求变化,及时调整产品策略和市场策略。通过持续创新和市场拓展,Component Research Co在电子行业中保持了领先地位,并迎来了更加美好的未来。

这五个故事均基于电子行业的普遍现象和发展趋势,但具体情节和细节纯属虚构。如果需要更具体或更贴近实际的故事,建议参考真实公司的发展历程和案例。

硕颉(BITEK)公司的发展小趣事

尽管硕颉科技在知识产权方面做出了积极努力,但仍难免面临专利诉讼的挑战。在某次与凹凸科技的专利侵权诉讼中,公司虽然一度面临败诉和永久禁制令的风险,但硕颉科技迅速应诉,积极应对。最终,美国联邦巡回上诉法院废除了原判决,公司得以自由销售被诉产品,不受任何限制。这次诉讼的胜利,不仅展示了硕颉科技在应对法律挑战方面的决心和能力,也为公司的长远发展奠定了坚实基础。

Geo Semiconductor Inc公司的发展小趣事
增加CPU温度监控电路,确保在高速运算时CPU温度不会过高,防止因过热导致的系统崩溃或损坏。
CHENMKO公司的发展小趣事
通过合理的布线、使用屏蔽线、加装滤波器等措施,减少外部电磁干扰对控制电路的影响。
Defense Supply Center Columbus公司的发展小趣事

在电子行业,供应链管理对于企业的运营效率至关重要。Defense Supply Center Columbus公司深知这一点,不断优化供应链管理流程。公司建立起一套高效的供应链管理系统,实现了从原材料采购、生产制造到产品销售的全程监控和管理。同时,公司还与供应商建立了长期稳定的合作关系,确保原材料的稳定供应和质量的可靠性。这些措施的实施,使得公司的运营效率得到了显著提升,降低了运营成本,提高了企业的竞争力。

问答坊 | AI 解惑

请问下BGA封装的元器件的布线?

BGA封装的元器件,为什么不能从元器件里面布线,我已经设置了扇出了,而且设计规则中的线宽也改成6mil,希望高手指点下,谢谢!…

查看全部问答>

wince应用程序调用USB驱动发送数据的问题

    我用友坚的6410开发板调试了一个USB function驱动,想利用这个驱动通过usb接口向主机发送数据。写了一个简单的应用程序,利用writefile函数发送数据。我传输的端点用的是中断端点1。结果发现只能传输第一次调用writefile发的数据,后 ...…

查看全部问答>

对于wince5.0中触摸驱动的前端加载流程的疑问

各位前辈大家好,我一个刚进公司的新人,有幸可以跟各位大牛一样搞系统研发,但是我们公司是做芯片的,我在公司做wince的BSP部分,头儿让我分析一下WINCE5.0下的触摸驱动(本地驱动)看了大牛们的资料对于实现框架比较了解了,(很多资料都是重点分 ...…

查看全部问答>

问大家一个问题,请帮忙

使用C# 2005开发WINCE下一个程序 为什么焦点在按钮上,按回车键却不触发CLICK事件? 如果通过消息来触发,SendMessage或PostMessage 该如何定义啊? const int WM_LBUTTONDOWN = 0x0201; const int WM_LBUTTONUP = 0x0202; [DllImport(\"user3 ...…

查看全部问答>

U盘量产

我有一8G的U盘,能识别,就是不能格式化! 准备量产一下,可以不知道该选什么存储芯片,量产后最多就3.56G 拆开发现主控芯片是MW6208,可是存储芯片上什么字也没有,只有用笔写的“3653” 请问下,我该选什么存储芯片进行量产呀?高手帮忙啊~~…

查看全部问答>

关于2440lcd 24bpp显示问题

我在移置2440的Bootload中的lcd驱动时候,设置24bpp Mode显示,现在屏幕上显示的内容为屏幕的上半边水平依次显示了两个一摸一样的我欲显示的开机画面,下半部分无任何显示,请问应该调节那几个参数啊。 我显示16bpp mode时候可以正常显示并调试通 ...…

查看全部问答>

bin文件的修改

请教,一个硬件的bin文件,我想修改文件中的bmp图片,要如何修改?…

查看全部问答>

multisim仿真好慢……

我用来仿真时序逻辑电路等好久……有什么办法设置仿真的速度没??…

查看全部问答>

关于LM3S8962开发板,装完驱动后,MDK没选项问题的解决

从网上找的不错,能解决实际问题   可以的 修改一下TOOLS文件就可以了 1:修改两处CPUDLL1=SARMCM3.DLL(TDRV1,TDRV2,TDRV3,TDRV4,TDRV5,TDRV7,TDRV8,TDRV9)   # Drivers for Cortex-M devices  ...…

查看全部问答>