用LED实现流水灯和用按键控制LED的亮灭

2023-05-16

【前言】
  恒子之后的系列文章都是为了记录自己在跟着韦东山老师学习嵌入式Linux开发过程中自己所学知识的梳理与总结。
  若恒子的学习记录对您有帮助,那么将是我莫大的荣幸;如果文章当中有写得不当的地方,还望您指出,我将感谢至极!
  恒子所用的开发板是韦老师的JZ2440,故之后的代码都是在JZ2440上运行成功的代码(都是裸板程序)。如果您是用其他开发板,也只需对代码进行简单修改。

文章目录

    • 一、用LED灯实现流水灯
    • 二、用按键控制LED灯的亮灭

一、用LED灯实现流水灯

在解决这个问题之前我们需要先查看JZ2440的原理图来了解如下两点:

  1. 我们需要用哪几个LED灯,以及对应的LED是连接在哪几个引脚的和对应引脚是通过输出高电平(1)还是低电平(0)来点亮LED;
  2. 查看S3C2440芯片手册,了解GPIO管脚的配置方法。

首先明确我们要使用LED的为D10、D11和D12来实现跑马灯效果,通过查看原理图我们知道D10–>GPF4、D11–>GPF5、D12–>GPF6(–>表示引脚连接),当对应引脚输出低电平(0)时对应的LED灯点亮,输出高电平(1)时熄灭。在这里插入图片描述
在这里插入图片描述
然后通过查看芯片手册我们知道需要配置的GPIO管脚寄存器有GPFCON和GPFDAT,对应的寄存器地址和相应位的配置信息如下图。
在这里插入图片描述
C代码文件 led.c 如下:


#define pGPFCON (*(unsigned int *)0x56000050)
#define pGPFDAT (*(unsigned int *)0x56000054)

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

int main(void)
{
	int statu = 7;	/* 初始三盏灯全熄灭,0b111 */

	/*  配置GPF4\5\6为输出引脚 */
	pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));
	pGPFCON |=  ((1<<8) | (1<<10) | (1<<12));
	
	/* 循环点亮LED0\1\2,对应GPF4\5\6 */
	while (1)
	{
		pGPFDAT &= ~(7<<4);
		pGPFDAT |= (statu<<4);
		delay(100000);	/* 延时一会儿 */
		switch (statu)	/* 状态切换 */
		{
			case 7: statu = 6; break;	/* 状态1: 6 = 0b110, 点亮D10 */
			case 6: statu = 5; break;	/* 状态2: 5 = 0b101, 点亮D11 */
			case 5: statu = 3; break;	/* 状态3: 3 = 0b011, 点亮D12 */
			case 3: statu = 6; break;	/* 返回状态 1 以达到循环的目的 */
			default: statu = 7;			/* 如果都不是则熄灭D10\D11\D12 */
		}
	}
	return 0;
}

这里的C文件并不是在我们常用的MDK中编译的,那么这个C文件中的main函数由谁调用呢?这是我们在MDK中编写代码所不需要考虑问题,因为MDK是一个高度集成的软件,它早已将这一切帮我们做好了,而我们需要做的仅仅只是点几个按钮就可以了。MDK中也是需要汇编启动代码去调用main函数的,只不过它帮我们设置好而已。既然是在裸机上开发程序那么我们就得自己实现一个汇编启动代码去调用main函数。
知道了是谁调用main后我们又该怎样才能让这个C代码在我们的裸机开发板上运行呢?因为我们知道局部变量是保存在栈中的,那既然是栈我们就得设置内存了(SRAM),而NOR启动和NAND启动的片内4K SRAM是不一样的,它们的具体地址看下图。因为我们是使用满减的栈,所以我们得让sp指向栈最高的地址处。
在这里插入图片描述
在这里插入图片描述
汇编启动文件 start.S 如下:


.text
.global _start

_start:
	/* 关闭看门狗 */
	ldr r0 , =0x53000000
	ldr r1, =0
	str r1, [r0]

	/* 设置内存,SP栈 
 	 * 先判断是nor启动还是nand启动
 	 * 可以nand flash进行写,它相当于ram,但不能对nor flash进行写
 	 * 往nand flash的0地址写0,随后读取0地址的值,判断是否为0
	 * 若为0,则为nand启动
	 * 否则则为nor启动
	 */
	mov r1, #0
	ldr r0, [r1]	/* 读原来的值 */
	str r1, [r1]	/* 往0地址写0 */
	ldr r2, [r1]	/* 读写后的值 */
	cmp r1, r2;
	ldr sp, = 0x40000000 + 4096		/* 先假设为nor启动 */
	ldreq sp, = 4096		/*如果相等则为nand启动 */
	streq r0, [r1]

	bl main		/* 跳转到c中的main函数并将返回地址保存在lr中 */

halt:	/* 死循环 */
	bl halt

其中的r0、r1、sp为ARM中的寄存器,ARM状态下共有14个通用寄存器r0~r14,另外还有r15、CPSR(当前程序状态寄存器)和SPSR(程序保护状态寄存器),其中 r13 为 lr (连接寄存器)、r14 为 sp (堆栈指针)、r15 为pc (程序计数器)。
在这里插入图片描述

二、用按键控制LED灯的亮灭

这里我们要做的事情如下:

  1. 确定用哪个按键控制哪个LED灯 ;
  2. 明白按键按下时与按键相连的引脚是高电平(1)还是低电平(0)。

通过查看原理图我们选取按键S2–>D10,S3–>D11,S4–>D12,当按键按下时让对应的LED灯点亮,松开时熄灭。
在原理图中我们还发现当按键下时对应引脚为低电平(0)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
C代码文件 key_led.c 如下:


#include "s3c2440_soc.h"	/* 包含寄存器地址的头文件,读者可根据前一个led.c 中对寄存器宏定义的方法自行定义 */

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

int main(void)
{
	int val1, val2;

	/* 用按键s2\s3\s4分别控制led0\led1\led2 
	 * s2->GPF0, s3->GPF2, s4->GPG3
	 * 配置GPF0、GPF2、GPG3为输入引脚
	 */
	GPFCON &= ~((3<<0) | (3<<4));
	GPGCON &= ~(3<<6);
	 
	/*  配置GPF4\5\6为输出引脚 */
	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));

	/* 用按键控制LED */
	while (1)
	{
		val1 = GPFDAT;
		val2 = GPGDAT;

		if ((val1 & (1<<0)) == 0 )	/* s2->GPF4 */
		{
			/* s2 按下 */
			GPFDAT &= ~(1<<4);
		}
		else
		{
			/* s2 松开 */
			GPFDAT |= (1<<4);
		}
		if ((val1 & (1<<2)) == 0 )	/* s3->GPF5 */
		{
			/* s3 按下 */
			GPFDAT &= ~(1<<5);
		}
		else
		{
			/* s3 松开 */
			GPFDAT |= (1<<5);
		}
		if ((val2 & (1<<3)) == 0 )	/* s4->GPF6 */
		{
			/* s4 按下 */
			GPFDAT &= ~(1<<6);
		}
		else
		{
			/* s4 松开 */
			GPFDAT |= (1<<6);
		}
	}
	return 0;
}

汇编启动文件 start.S 如下:


.text
.global _start

_start:
	/* 关闭看门口 */
	ldr r0 , =0x53000000
	ldr r1, =0
	str r1, [r0]

	/* 设置内存,SP栈 
 	 * 先判断是nor启动还是nand启动
 	 * 可以nand flash进行写,它相当于ram,但不能对nor flash进行写
 	 * 往nand flash的0地址写0,随后判断0地址是否为0
	 * 若为0,则为nand启动
	 * 否则则为nor启动
	 */
	mov r1, #0
	ldr r0, [r1]	/* 读原来的值 */
	str r1, [r1]	/* 往0地址写0 */
	ldr r2, [r1]	/* 读写后的值 */
	cmp r1, r2;
	ldr sp, = 0x40000000 + 4096		/* nor启动 */
	ldreq sp, = 4096		/*如果相等则为 nand启动 */
	streq r0, [r1]

	bl main			/* 跳转到c中的main函数并将返回地址保存在lr中 */

halt:	/* 死循环 */
	bl halt
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用LED实现流水灯和用按键控制LED的亮灭 的相关文章

随机推荐

  • 重装@angular/cli reason: write EPROTO 139955972261696:error:1408F10B:SSL routines:ssl3_get_record:wron...

    前几天不小心卸载了 angular 64 cli 然后重装的时候发现 xff0c 一直报错 如下 xff1a 64 ln622653 npm install g 64 angular cli npm ERR code EPROTO npm
  • Outlook2016删不掉主账户的解决方法

    控制面板 gt 账户 gt 邮件把配置文件删了 前两项和Outlook内部打开账户选项一样没用 进第三个 重启Oulook的时候会提示重新建一个配置 就OK了 转载于 https www cnblogs com haimingpro p 6
  • 新版新概念英语1-4册(英音+美音)MP3打包下载

    新版新概念英语第一册MP3 美音 新版新概念英语第一册MP3 英音 新版新概念英语第一册PDF 课文 新版新概念英语第二册MP3 美音 新版新概念英语第二册MP3 英音 新版新概念英语第二册PDF 课文 新版新概念英语第三册MP3 美音 新
  • linux远程windows无法输入,XRDP在Windows下用远程桌面连接,键盘失效有关问题

    XRDP在Windows下用远程桌面连接 xff0c 键盘失效问题 很久没上这个博客了 xff0c 最近在做虚拟化方面的东西 xff0c 有个需求是通过windows远程连接Linux桌面 xff0c 采用的是xrdp 安装和使用xrdp都
  • 3367 【模板】并查集

    题目描述 如题 xff0c 现在有一个并查集 xff0c 你需要完成合并和查询操作 输入输出格式 输入格式 xff1a 第一行包含两个整数N M xff0c 表示共有N个元素和M个操作 接下来M行 xff0c 每行包含三个整数Zi Xi Y
  • MySQL优化之my.conf配置详解

    最近项目不太忙 xff0c 所以有时间静心来研究下mysql的优化 xff0c 对于MySQL的设置是否合理优化 xff0c 直接影响到网站的速度和承载量 xff01 同时 xff0c MySQL也是优化难度最大的一个部分 xff0c 不但
  • NPM全局安装软件包时解决EACCES权限错误

    NPM全局安装软件包时解决EACCES权限错误 Resolving EACCES permissions errors when installing packages globally npm WARN checkPermissions
  • 阿里云学生服务器认证条件详解与选择教程

    简介 xff1a 本文汇总学生购买阿里云服务器以及其它云产品优惠 xff0c 阿里云的云翼计划 xff0c 是阿里云针对在校学生扶持的一项优惠活动 xff0c 只需9元即可购买阿里云服务器 xff0c 而且云服务器配置不低 xff0c 足够
  • deepin系统

    https www uc23 net xinwen 76259 html 据介绍 xff0c 深度操作系统 xff08 deepin xff09 自 2015 年开始 xff0c 就放弃基于 Ubuntu 作为上游 xff0c 选择 Ubu
  • Linux 大文件日志快速定位错误或者异常的位置

    1 得到错误日志或者异常日志的行号 cat n test log grep 34 error 34 cat n test log grep 34 exception 34 2 通过位置往前往后查看日志详细 339563 can not cl
  • 《oracle正则表达式》摘抄+自理

    select from t test regexp A B 1 AAA 2 bbb 3 4 xff01 xff01 xff01 5 吴雁渡 6 12345 7 123AAbb存储 64 xff01 64 445BBC 1 REGEXP LI
  • ASP.NET Core 3.0 : 二十四. 配置的Options模式

    上一章讲到了配置的用法及内部处理机制 xff0c 对于配置 xff0c ASP NET Core还提供了一种Options模式 ASP NET Core 系列目录 一 Options的使用 上一章有个配置的绑定的例子 xff0c 可以将配置
  • 区分柱状图(条形图)和直方图

    柱状图 61 条形图 柱状图一般用于描述离散型分类数据的对比每根柱子宽度固定 xff0c 柱子之间会有间距横轴变量可以任意排序 直方图 直方图一般用于描述连续型数据的分布关系每根柱子宽度可以不一样 xff0c 且一般没有间距横轴变量有一定顺
  • Latex公式字母加粗

    在Latex 中 xff0c 公式字母加粗用语法 xff1a boldsymbol 待添加的字母 xff0c 如 xff1a boldsymbol bold 61 frac 1 boldsymbol w s t boldsymbol x 4
  • [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web app...

    问题 启动tomcat 就一直卡在了这里 继续往上查看日志 解决方法 xff1a 转载于 https www cnblogs com chenyanlong p 10699434 html
  • ccf 画图

    问题描述 试题编号 xff1a 201409 2试题名称 xff1a 画图时间限制 xff1a 1 0s内存限制 xff1a 256 0MB问题描述 xff1a 问题描述 在一个定义了直角坐标系的纸上 xff0c 画一个 x1 y1 到 x
  • Pigx官方文档地址

    https www kancloud cn lengleng pig guide 949171 转载于 https www cnblogs com mengjianzhou p 11229623 html
  • Linux IPC实践(11) --System V信号量(1)

    信号量API include lt sys types h gt include lt sys ipc h gt include lt sys sem h gt int semget key t key int nsems int semf
  • linux ubuntu 分区,查看Ubuntu分区列表方法

    今天在Ubuntu修复Grub正好碰到了要展示分区列表看看 不然都不清楚哪个是哪个了 sudo fdisk l 就是这个命令 ubuntu 64 ubuntu sudo fdisk l Disk dev sda 250 0 GB 25005
  • 用LED实现流水灯和用按键控制LED的亮灭

    前言 恒子之后的系列文章都是为了记录自己在跟着韦东山老师学习嵌入式Linux开发过程中自己所学知识的梳理与总结 若恒子的学习记录对您有帮助 xff0c 那么将是我莫大的荣幸 xff1b 如果文章当中有写得不当的地方 xff0c 还望您指出