一、如何控制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的流水等程序。