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

非操作系统下GPIO口控制器及LED灯编程

  • GPIO控制器
    • 概述
    • 内部架构
    • 端口寄存器
      • GPIO控制寄存器
      • GPIO数据寄存器
      • GPIO上拉寄存器
  • 非操作系统LED灯闪烁
    • 开发步骤
    • 开发板上二极管
    • 读电路图
    • S3C6410芯片手册
    • 程序框架
      • 驱动编写示例 leddrv.c
  • 课后作业
  • 配套作业

GPIO控制器

概述

S3C6410 共有 187 根 IO 口,分成 17 个 PORT,每根 IO 口可以被用在输入引脚线、输出引脚线和其它功能引脚线使用,可以通过每个端口自带的控制寄存器进行功能配置。【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第1张图片
【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第2张图片

内部架构

  • GPIO控制器挂在APB总线,属于低速设备。
  • 控制器包括寄存器文件相应的功能电路组成,通过寄存器可以控制功能电路按照用户的方式进行工作。
  • 整个控制器包括 alive-part , off-part 两个部分, 区别在于sleep mode 时是否有电源供应,在 alive-part 时有电源供给,所以其端口可用作 wake –up 唤醒信号
    【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第3张图片

端口寄存器

GPIO控制寄存器

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

【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第4张图片

GPIO数据寄存器

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

在这里插入图片描述

GPIO上拉寄存器

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

【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第5张图片

非操作系统LED灯闪烁

开发步骤

  1. 看懂硬件图
  2. 编写驱动
  3. 编写应用程序
  4. 使用工具
  5. 系统调试
    【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第6张图片

开发板上二极管

【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第7张图片

读电路图

S3C6410芯片手册

【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第8张图片

程序框架

  • 汇编
;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)写出驱动程序和应用程序。

刚开始嵌入式,对于硬件方面有很多不理解,不过这不影响我编程。
【嵌入式】非操作系统下GPIO口控制器及LED灯编程_第9张图片

答案如下:

  • 驱动程序 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) 看门狗部件属于(硬件模块),其核心功能为(侦测软件代码跑飞,当系统“跑飞”而进入死循环时,恢复系统的运行)。

你可能感兴趣的:(#,嵌入式系统与设计,芯片,嵌入式)