【嵌入式】非操作系统下GPIO口控制器及LED灯编程

GPIO控制器

概述

S3C6410 共有 187 根 IO 口,分成 17 个 PORT,每根 IO 口可以被用在输入引脚线、输出引脚线和其它功能引脚线使用,可以通过每个端口自带的控制寄存器进行功能配置。在这里插入图片描述
在这里插入图片描述

内部架构

  • GPIO控制器挂在APB总线,属于低速设备。
  • 控制器包括寄存器文件相应的功能电路组成,通过寄存器可以控制功能电路按照用户的方式进行工作。
  • 整个控制器包括 alive-part , off-part 两个部分, 区别在于sleep mode 时是否有电源供应,在 alive-part 时有电源供给,所以其端口可用作 wake –up 唤醒信号
    在这里插入图片描述

端口寄存器

GPIO控制寄存器

  • 功能 – 配置相应端口的功能

在这里插入图片描述

GPIO数据寄存器

  • 数据寄存器每个bit位对应相应端口的IO线
  • 如果该IO线被用做输入口引脚,该bit位随着引脚线电平的变化而变化(其对应值为0或者1);
  • 如果该IO线被用作输出口引脚,则该bit位值为1时,外面对应引脚线为高电平(一般为3.3v左右),则该bit位值为0时,外面对应引脚线为低电平(一般为略大于0V)

在这里插入图片描述

GPIO上拉寄存器

  • 该寄存器可以对 arm 一些特殊io做上拉或下拉处理,这在一些场合是非常有用的,避免了在pcb上加上拉或下拉电阻,能够简化外部电路设计

在这里插入图片描述

非操作系统LED灯闪烁

开发步骤

  1. 看懂硬件图
  2. 编写驱动
  3. 编写应用程序
  4. 使用工具
  5. 系统调试
    在这里插入图片描述

开发板上二极管

在这里插入图片描述

读电路图

S3C6410芯片手册

在这里插入图片描述

程序框架

  • 汇编
;asses.s内容
	AREA Init, CODE READONLY
	ENTRY
_start
        B Main
	END
  • 编写应用程序
// ledapp.c
void main()
{
	ledconfig();
	for()
	{
		ledon();delay();
	  	ledoff();delay();
	}
}
  • 编写驱动
// leddrv.c
void ledconfig()
{
	……
}
void ledon()
{
	……
}
void ledoff()
{
	……
}

驱动编写示例 leddrv.c

  • 配置M口M1引脚为输出口
#define rGPMCON  *((volatile int *) 0x7f008820 )
void ledconfig()
	tmp= rGPMCON;		//读出端口寄存器值
	tmp &=! (0xF<<4);	//把bit4~7清0
	tmp |= (1<<4);		//把bit4~7写入0x1值
	rGPMCON = tmp;		//写回到端口寄存器
}
  • 点亮
    配置M口M1输出低电平
#define rGPMDAT  *((volatile int *) 0x7f008824 )
void ledon()
{
	tmp= rGPMDAT;		//读出端口寄存器值
	tmp &=! (0x1<<1);	//把bit1清0
	tmp |= (0<<1);		//把bit1写入0x0值
	rGPMDAT = tmp;		//写回到端口寄存器
}
  • 熄灭
    配置M口M1输出高电平
void ledoff()
{
	tmp= rGPMDAT;		//读出端口寄存器值
	tmp &=	! (0x1<<1);	//把bit1清0
	tmp |= (1<<1);		//把bit1写入0x1值
	rGPMDAT = tmp;		//写回到端口寄存器
}

课后作业

编写一个在非操作系统LED灯闪烁的程序,要求
1)控制GPM2和GPM4端口;
2)写出驱动程序和应用程序。

刚开始嵌入式,对于硬件方面有很多不理解,不过这不影响我编程。
在这里插入图片描述

答案如下:

  • 驱动程序 leddrv.c
//  leddrv.c
#define rGPMCON  *((volatile int *) 0x7f008820 )
// 控制GPM2和GPM4端口
void ledconfig(){
	tmp= rGPMCON;		//读出端口寄存器值
	tmp &= !(0xF<<8);	//把bit8~11清0
	tmp |= (1<<8);		//把bit8~11写入0x1值
	tmp &= !(0xF<<16);	//把bit16~19清0	
	tmp |= (1<<16);		//把bit16~19写入0x1值
	// 这里再提供一种简便写法,完全等价上面四行
	// tmp &= !(0xF<<8 | 0xF<<16);
	// tmp |= (1<<8 | 1 <<16);
	// 这里再再提供一种写法
	// tmp &= !(0xF0F << 8);
	// tmp |= (0x101 << 8);
	rGPMCON = tmp;		//写回到端口寄存器
}
#define rGPMDAT  *((volatile int *) 0x7f008824 )
void ledon()
{
	tmp= rGPMDAT;		//读出端口寄存器值
	tmp &= !(0x1<<2);	//把bit2清0
	tmp |= (0<<2);		//把bit2写入0x0值
	tmp &= !(0x1<<4);	//把bit4清0
	tmp |= (0<<4);		//把bit4写入0x0值
	// 这里再提供一种简便写法,完全等价上面四行
	// tmp &= !(0x1<<2 | 0x1<<4);
	// tmp |= (0<<2 | 0<<4)
	rGPMDAT = tmp;		//写回到端口寄存器
}
void ledoff()
{
	tmp= rGPMDAT;		//读出端口寄存器值
	tmp &= !(0x1<<2);	//把bit2清0
	tmp |= (1<<2);		//把bit2写入0x1值
	tmp &= !(0x1<<4);	//把bit4清0
	tmp |= (1<<4);		//把bit4写入0x1值
	// 这里再提供一种简便写法,完全等价上面四行
	// tmp &= !(0x1<<2 | 0x1<<4);
	// tmp |= (1<<2 | 1<<4)
	// 还可以这么写
	// tmp &= !(0x5 << 2);
	// tmp |= (0x5 << 2);// bit2,bit4写入1,相当于101左移2位
	rGPMDAT = tmp;		//写回到端口寄存器
}
  • 应用程序 ledapp.c
// leadapp.c
void delay(){ // 停止一段时间
	for( i=0;i<1000;i++)
		for( j=0;j<1000;j++);
}
void main()
{
	ledconfig(); // 配置驱动
	while(1)
	{
		ledon();delay();
		ledoff();delay();
	}
}

配套作业

(1) S3C6410 处理器其内部知识产权核使用(ARM11),该处理器内置(看门狗控制器、GPIO口控制器)等多接口控制器。

(2) 接口编程核心是要掌握端口寄存器,一般情况下程序员通过(芯片手册)来了解端口寄存器定义和使用方法。假设某端口寄存器地址为0xC2000004,32比特大小,需要将其第8-9位写入二进制值(10)2,而其它位保持不变,请写出关键代码(采用内存指针法)

tmp = *((volatile int*)0xC2000004);
tmp &= !( 0x3 << 8);
tmp |= (0x3 << 8);
*((volatile int*)0xC2000004) = tmp;

(3) 看门狗部件属于(硬件模块),其核心功能为(侦测软件代码跑飞,当系统“跑飞”而进入死循环时,恢复系统的运行)。

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌宅鹿同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值