ARM架构(寄存器点灯)

举报
yd_274589494 发表于 2023/07/29 12:21:40 2023/07/29
【摘要】 @TOC 前言本篇文章我们来讲解一下如何使用寄存器点亮一个LED灯,一般对于新人来说都是使用HAL库或者标准库来操作的,但是学习寄存器有助于我们了解更加深入的知识,这加会提高我们对ARM架构的理解。 一、LED原理图首先第一步我们需要先找到LED的原理图,确定对应的引脚,然后知道是高电平点亮还是低电平点亮。这里我们用到了三个LED,分别是PB0,PB1,PB5。 二、使用寄存器点灯的步骤1....

@TOC


前言

本篇文章我们来讲解一下如何使用寄存器点亮一个LED灯,一般对于新人来说都是使用HAL库或者标准库来操作的,但是学习寄存器有助于我们了解更加深入的知识,这加会提高我们对ARM架构的理解。

一、LED原理图

在这里插入图片描述
首先第一步我们需要先找到LED的原理图,确定对应的引脚,然后知道是高电平点亮还是低电平点亮。

这里我们用到了三个LED,分别是PB0,PB1,PB5。

二、使用寄存器点灯的步骤

1.使能对应的GPIO

2.引脚模式设置

3.引脚方向设置

4.输出电平设置

这个步骤其实和使用那些库的步骤是一样的,只不过在库中我们总是使用一些结构体来完成这些GPIO的初始化。

三、如何操作寄存器

操作寄存器这里我们使用指针来得到对应寄存器的地址,并对他进行操作。

在ARM中,使用指针操作寄存器时,需要进行读取、改写和写入这三个步骤,以确保正确更新寄存器的特定位,同时不影响其他位。

1.读取寄存器:首先,需要读取寄存器中的当前值。

2.改写寄存器:根据需要改写寄存器的对应位。

3.写入寄存器:修改完成后,将修改好的值再次写入对应的寄存器中。

四、实际操作

这里我们来进行实际的操作,首先我们需要找到STM32的数据手册,在数据手册中我们可以查看到对应寄存器的地址,并且知道如何配置对应的寄存器。

1.使能GPIO端口

在数据手册中的第8章找到时钟使能对应的寄存器:

并且可以从其中得到偏移地址为0x18。
在这里插入图片描述
在第三章中找到对应寄存器的基地址:
在这里插入图片描述
这样我们就可以得到这个寄存器的完整地址了:0x40021000 + 0x18

在这里插入图片描述
在这里可以看到将bit3设置为1可以使能GPIOB端口。

	/* 使能GPIOB */
	pReg = (unsigned int *)(0x40021000 + 0x18);
	*pReg |= (1<<3);

2.将引脚设置为输出模式

在这里插入图片描述
在数据手册中找到第九章,GPIO的寄存器,设置MODE可以将GPIO设置为输入或者输出模式。

找到基地址:0x40010C00
在这里插入图片描述
偏移地址:
在这里插入图片描述
最后得到的地址:0x40010C00 + 0x00

	/* 设置GPIOB0为输出引脚 */
	pReg = (unsigned int *)(0x40010C00 + 0x00);
	*pReg |= (1<<1);
	
	/* 设置GPIOB1为输出引脚 */
	pReg1 = (unsigned int *)(0x40010C00 + 0x00);
	*pReg1 |= (1<<4);
	
	/* 设置GPIOB5为输出引脚 */
	pReg2 = (unsigned int *)(0x40010C00 + 0x00);
	*pReg2 |= (1<<20);	

3.设置输出状态

偏移地址:0x0C
最终地址:0x40010C00 + 0x0C
在这里插入图片描述
这里将需要设置为高电平的引脚,设置寄存器对应的位为1即可。

五、全部代码

main.c


void delay(int d)
{
	while(d--);
}

int main()
{
	unsigned int *pReg;
	
	unsigned int *pReg1;
	
	unsigned int *pReg2;
	
	/* 使能GPIOB */
	pReg = (unsigned int *)(0x40021000 + 0x18);
	*pReg |= (1<<3);
	
	/* 设置GPIOB0为输出引脚 */
	pReg = (unsigned int *)(0x40010C00 + 0x00);
	*pReg |= (1<<1);
	
	/* 设置GPIOB1为输出引脚 */
	pReg1 = (unsigned int *)(0x40010C00 + 0x00);
	*pReg1 |= (1<<4);
	
	/* 设置GPIOB5为输出引脚 */
	pReg2 = (unsigned int *)(0x40010C00 + 0x00);
	*pReg2 |= (1<<20);	

	pReg = (unsigned int *)(0x40010C00 + 0x0C);
	
	pReg1 = (unsigned int *)(0x40010C00 + 0x0C);
	
	pReg2 = (unsigned int *)(0x40010C00 + 0x0C);
	
	while (1)
	{
		/* 设置GPIOB0输出1 */
		*pReg |= (1<<0);
		
		delay(500000);

		/* 设置GPIOB0输出0 */
		*pReg &= ~(1<<0);
		
		delay(500000);		

		/* 设置GPIOB1输出1 */
		*pReg1 |= (1<<1);
		
		delay(500000);

		/* 设置GPIOB1输出0 */
		*pReg1 &= ~(1<<1);
		
		delay(500000);	

		/* 设置GPIOB5输出1 */
		*pReg2 |= (1<<5);
		
		delay(500000);

		/* 设置GPIOB5输出0 */
		*pReg2 &= ~(1<<5);
		
		delay(500000);			
	}
	
	return 0;
}

start.s启动文件:


                PRESERVE8
                THUMB


; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
				EXPORT  __Vectors
					
__Vectors       DCD     0                  
                DCD     Reset_Handler              ; Reset Handler

				AREA    |.text|, CODE, READONLY

; Reset handler
Reset_Handler   PROC
				EXPORT  Reset_Handler             [WEAK]
                IMPORT  main

				LDR SP, =(0x20000000+0x10000)
				BL main

                ENDP 
                
                 END


这个启动文件的内容我们后续再来讲解。

总结

本篇文章就讲解到这里,希望大家能够多加练习,学习寄存器的编程对深入了解ARM架构是有好处的。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。