《智能家居系统》4

一、如何控制LED灯的状态

在嵌入式linux系统中,控制硬件需要硬件的驱动。液晶屏和触摸屏的驱动已经安装到linux内核中。我们可以直接访问。
液晶屏:/dev/fb0
触摸屏:/dev/input/event0
访问液晶屏和触摸屏的方法:open()、read()、write()、close()

1、LED灯的驱动程序

led_drv.c----LED驱动程序的源文件
Makefile ----- 编译驱动程序使用的Makefile文件
led_drv.ko ---->已经编译好的驱动程序
test.c ---->访问驱动程序的应用程序

2、驱动程序的安装

[root@GEC6818 /test]#insmod led_drv.ko
[  110.830000] gec6818_led_init

3、查看驱动的设备文件

[root@GEC6818 /test]#ls /dev/led_drv -l
crw-rw----    1 root     root      100,   0 Jan  1 00:01 /dev/led_drv

4、通过设备文件来控制LED


int main(void)
{
	int fd;
	int ret;
	char buf[2]; //buf[1]---LED灯的灯号:8、9、10、11
                     //buf[0]---LED灯的状态:1--on, 0--off

	fd = open("/dev/led_drv", O_WRONLY); //打开LED驱动
	if(fd < 0)
	{
		perror("open led driver");
		return -1;		
	}
	while(1)
	{
		buf[1]=8; buf[0]=1;//LED8 on
		ret = write(fd,buf,sizeof(buf));
		if(ret != 2)
			perror("write led driver ");
		usleep(300*1000);//300ms
		
		buf[1]=8; buf[0]=0;//LED8 off
		ret = write(fd,buf,sizeof(buf));
		if(ret != 2)
			perror("write led driver ");
		usleep(300*1000);//300ms
	}
	
	close(fd);
	
	return 0;
}


二、控制LED灯

//GPIOC17 引脚控制D8
//这个是一个裸机程序,直接在ARM硬件上运行的程序,而不是在linux运行的程序。


void delay(int data);
//裸机程序通常不能直接使用C库,裸机程序的入口是_start()
int _start(void) //注意:_start()函数要放在源文件的最开始
{
	//1.将GPIOC17设置成一个IO功能。GPIOCALTFN1[3:2] = 01; 0xC001C024
	*(unsigned int *)0xC001C024 &= ~(3<<2); 
	*(unsigned int *)0xC001C024 |= (1<<2);
	
	//2.将GPIOC17设置成输出引脚.GPIOCOUTENB[17]=1; 0xC001C004
	*(unsigned int *)0xC001C004 |= (1<<17);
	while(1)
	{
		//3.GPIOC17输出低电平,D8 on。GPIOCOUT[17]=0;0xC001C000
		*(unsigned int *)0xC001C000 &= ~(1<<17);
		delay(0x3000000);
		
		//4.GPIOC17输出高电平,D8 off。GPIOCOUT[17]=1;0xC001C000
		*(unsigned int *)0xC001C000 |= (1<<17);	
		delay(0x3000000);
	}
	return 0;
}

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

一、分析LED电路的原理图

gec6818_base_V1.1-底板.pdf ----> LED
gec6818cv1_20170407-核心板 ---->S5P6818

思考:
找到LED灯的处理器控制引脚,分析控制原理。D7、D8、D9、D10

1、5个GPIO引脚控制5个LED
D7 ----- GPIOE13
D8 ----- GPIOC17
D9 ----- GPIOC8
D10 ----- GPIOC7
D11 ----- GPIOC12
2、LED的控制原理

在ARM处理器中,一般GPIO的引脚电平是3.3v。
高—“1”----3.3V
低—“0”----0V

灯的状态控制:
GPIO输出高电平,即GPIO输出3.3V,LED off
GPIO输出低电平,即GPIO输出0V,LED on
思考:
LED亮的时候,流过LED的电流是多少呢?

所以,控制LED灯状态就是控制GPIO的电平(高/低)

3、LED的控制过程—控制寄存器

寄存器的访问流程

1)将GPIOC17设置成IO功能

2)将GPIOC17设置成输出引脚

3)设置输出的电平(高/低)

=============================================================

二、访问S5P6818的寄存器

SEC_S5P6818X_Users_Manual_preliminary_Ver_0.00.pdf

注意:
在ARM处理器中,访问寄存器的过程就是通过访问寄存器的地址来实现的。每个寄存器都有一个唯一的地址。

1、配置GPIO引脚功能的寄存器

GPIOxALTFN0
GPIOxALTFN1
是32bits的寄存器,寄存器的每两个位分成了一个组。每个组控制一个引脚。
GPIOxALTFN0 ----- GPIO0~GPIO15 16个引脚
GPIOxALTFN1 ----- GPIO16~GPIO31 16个引脚

以GPIOC17为例:
GPIOCALTFN1的第3、2引脚控制GPIOC17的功能。该寄存器的地址是0xC001C024

GPIOCALTFN1[3:2]=01b //将GPIOC17设置为IO功能

2、配置IO是输出还是输入的寄存器

GPIOXOUTENB — 每个位对应一个引脚,通过这个位来配置引脚的输出还是输入。

以GPIOC17为例:
GPIOCOUTENB[17]=1b //GPIOC17设置为输出引脚

3、设置引脚输出的电平

GPIOXOUT — 每个位对应一个引脚,通过这个引脚来配置IO输出的电平。

=============================================================

三、C语言程序设计

通过寄存器的分析,得到几个问题:

1、访问寄存器都是通过地址来访问的,所以在C语言中,如何根据地址访问地址下的内容???
2、在ARM中,一般一个寄存器有32个位,每个位代表不同的意义,通常我们只需要改变寄存器的某个位,而其他位保持不变?

思考:
C的位操作运算符: &、 |、 ~、 ^、<<、>>
问题:

1 & 2 = 0  ; 1 && 2 = 1; 
1 | 2 = 3  ; 1 || 2 = 1;
~1 = 0xFFFFFFFE;  !1= 0;
1^2 = 3;  7 ^ 2 = 5;
1<<3 = 8 = 2**3;

int a=10;
int *p;
p = &a; //p是指向a的指针,p的值是a的地址,*p的值是a的值
*p ---> 10

总结:
一个位和1按位或操作,将这个位置1;一个位和0按位或操作,这个位保持不变
一个位和0按位与操作,将这个位清0;一个位和1按位与操作,这个位报错不变

1、有一个地址0x40000000,如何将unsigned int a写入该地址。
写法1:

unsigned int *p;
p=(unsigned int *)0x40000000;
*p = a;

写法2:

unsigned int *p = (unsigned int *)0x40000000;
*p = a;

写法3:

(*(unsigned int *)0x40000000) = a;

2、读取地址0x40000000地址下的数据,给

unsigned int a。
a = (*(unsigned int *)0x40000000);

3、unsigned int a,将a的第17位置1,其他位保持不变

	a = a | (1<<17);
        a |= (1<<17);

1<<17  ----> 10 0000 0000 0000 0000b 
1<<0   ----0001
1<<1   ----0010

4、unsigned int a,将a的第17位清0,其他位保持不变

	a = a & 0xFFFFDFFFF;
	a = a & (~(1<<17));
	a &= ~(1<<17);

0xFFFFDFFF ---- > ~(1<<17)

5、unsigned int a,将a的第17位取反,其他位保持不变

   a = a ^ (1<<17);
   a ^= (1<<17);
xxxxb
0100b ^
---------
x反xx

=============================================================

四、编写裸机程序

//GPIOC17 引脚控制D8
//这个是一个裸机程序,直接在ARM硬件上运行的程序,而不是在linux运行的程序。


void delay(int data);
//裸机程序通常不能直接使用C库,裸机程序的入口是_start()
_start(void) //注意:_start()函数要放在源文件的最开始
{
	//1.将GPIOC17设置成一个IO功能。GPIOCALTFN1[3:2] = 01; 0xC001C024
	*(unsigned int *)0xC001C024 &= ~(3<<2); 
	*(unsigned int *)0xC001C024 |= (1<<2);
	
	//2.将GPIOC17设置成输出引脚.GPIOCOUTENB[17]=1; 0xC001C004
	*(unsigned int *)0xC001C004 |= (1<<17);
	while(1)
	{
		//3.GPIOC17输出低电平,D8 on。GPIOCOUT[17]=0;0xC001C000
		*(unsigned int *)0xC001C000 &= ~(1<<17);
		delay(0x3000000);
		
		//4.GPIOC17输出高电平,D8 off。GPIOCOUT[17]=1;0xC001C000
		*(unsigned int *)0xC001C000 |= (1<<17);	
		delay(0x3000000);
	}
}

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

=============================================================

五、裸机程序编译

麻烦的方法:
arm-linux-gcc -o test test.c
方便的方法:
使用Makefile文件----里面定义了交叉编译工具的使用方法和使用顺序。

gec@ubuntu:/mnt/hgfs/东莞理工实训/笔记/day6/led8$ ls
led8.c  Makefile
gec@ubuntu:/mnt/hgfs/东莞理工实训/笔记/day6/led8$ make
arm-none-linux-gnueabi-gcc -o led8.o led8.c -c -nostdlib
arm-none-linux-gnueabi-ld -Ttext 0x40000000 -o led.elf led8.o
arm-none-linux-gnueabi-objcopy -O binary led.elf led.bin
arm-none-linux-gnueabi-objdump -D led.elf > led.dis
gec@ubuntu:/mnt/hgfs/东莞理工实训/笔记/day6/led8$ ls
led8.c  led8.o  led.bin  led.dis  led.elf  Makefile

编译后,生成二进制可执行文件—>led.bin

=============================================================

六、裸机程序的调试

注意:
直接在ARM硬件上运行的程序,而不是在linux运行的程序。

需要使用网络下载裸机程序(led.bin)到嵌入式平台。

1、使用网线连接开发板和PC

注意:
PC机需要使用静态IP地址,例如:162.168.3.200
PC机的防火墙需要关闭

2、在PC机上搭建tftp服务器

tftpd32
1)设置tftp当前下载/上传的路径
2)设置服务器的IP—192.168.3.200

3、进入开发板的uboot命令行

注意:不是linux命令行
DSIM_STATUS : 0x10010f
## Skip BAT Animation. 
## IRQ(0x48)   : 0x00 0x00 0x00 0x00 0x00 
## chg_type    : ADP 
## battery_vol : 0mV 
## battery_cap : 100%
## Booting 
Card did not respond to voltage select!
Net:   GEC6818 mac init...
dwmac.c0060000
Hit any key to stop autoboot:  0 
GEC6818#    --------->uboot的命令行提示符

4、设置服务器和开发板的IP地址

1)查看IP

GEC6818# printenv

gatewayip=192.168.1.1  ----网关
ipaddr=192.168.1.165  ---开发板
netmask=255.255.255.0 ---- 子网掩码
serverip=192.168.1.164 ----服务器

Environment size: 843/32764 bytes

2)设置IP

GEC6818# setenv serverip 192.168.3.200
GEC6818# setenv gatewayip 192.168.3.1
GEC6818# setenv ipaddr 192.168.3.117

3)保存设置

GEC6818# saveenv
Saving Environment to MMC...
Writing to MMC(2)... done

4)查看
ok

5)使用开发板ping windows

GEC6818# ping 192.168.3.200
Speed: 100, full duplex
Using dwmac.c0060000 device
host 192.168.3.200 is alive

5、使用tftp下载裸机程序

GEC6818# tftp 0x40000000 led.bin
Speed: 100, full duplex
Using dwmac.c0060000 device
TFTP from server 192.168.3.200; our IP address is 192.168.3.117
Filename 'led.bin'.
Load address: 0x40000000
Loading: #
         6.8 KiB/s
done
Bytes transferred = 228 (e4 hex)

注意:
需要先保证网络是通的,然后在下载。第一次下载不成功,可以再下载一次
led.bin程序是下载开发板的DDR3内存中的,0x40000000是DDR3内存的地址。

6、执行led.bin

GEC6818# go 0x40000000
## Starting application at 0x40000000 ...

作业:
使用C语言实现裸机编程,控制4盏LED的流水等程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WeSiGJ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值