S5PV210 | 裸机LED灯呼吸实验
S5PV210 | 裸机LED灯呼吸实验
目录
- S5PV210 | 裸机LED灯呼吸实验
- 电路原理
- DATASHEET(相关寄存器设置详解)
- 2.2.7 GPD0控制寄存器组
- 2.2.7.1 Port Group GPD0 Control Register (GPD0CON, R/W, Address = 0xE020_00A0)
- 2.2.7.2 Port Group GPD0 Control Register (GPD0DAT, R/W, Address = 0xE020_00A4)
- 2.2.7.3 Port Group GPD0 Control Register (GPD0PUD, R/W, Address = 0xE020_00A8)
- 2.2.7.4 Port Group GPD0 Control Register (GPD0DRV, R/W, Address = 0xE020_00AC)
- 2.2.7.5 Port Group GPD0 Control Register (GPD0CONPDN, R/W, Address = 0xE020_00B0)
- 2.2.7.6 Port Group GPD0 Control Register (GPD0PUDPDN, R/W, Address = 0xE020_00B4)
- 2.2.7 GPD0控制寄存器组
- 代码编写
-
电路原理
本实验中,我们通过控制D25(LED4)来实现一个呼吸灯。GPD0_1输出高电平,熄灭LED;反之,输出低电平,点亮LED。
这里通过延时函数,来控制LED灯亮灭的时间长短。
渐亮过程:在调光级数递增过程中,LED灯亮起来的时间越来越长;
渐灭过程:在调光级数递增过程中,LED灯熄灭起来的时间越来越长。
两个过程即为一个呼吸周期,一个过程控制在一秒左右,即可实现灯的呼吸效果。
-
DATASHEET(相关寄存器设置详解)
2.2.7 GPD0控制寄存器组
GPD0
控制寄存器组包含六组控制寄存器,分别叫做:GPD0CON
,GPD0DAT
,GPD0PUD
,GPD0DRV
,GPD0CONPDN
和
GPD0PUDPDN
。
2.2.7.1 Port Group GPD0 Control Register (GPD0CON, R/W, Address = 0xE020_00A0)
2.2.7.2 Port Group GPD0 Control Register (GPD0DAT, R/W, Address = 0xE020_00A4)
2.2.7.3 Port Group GPD0 Control Register (GPD0PUD, R/W, Address = 0xE020_00A8)
2.2.7.4 Port Group GPD0 Control Register (GPD0DRV, R/W, Address = 0xE020_00AC)
2.2.7.5 Port Group GPD0 Control Register (GPD0CONPDN, R/W, Address = 0xE020_00B0)
2.2.7.6 Port Group GPD0 Control Register (GPD0PUDPDN, R/W, Address = 0xE020_00B4)
-
代码编写
-
启动代码
/**********************************************************
* > File Name: start.S
* > Author: fly
* > Create Time: 2020年07月17日 星期五 07时56分19秒
*********************************************************/
#define PS_HOLD_CONTORL 0xE010E81C
#define WTCON 0xE2700000
#define SVC_STACK 0xD0037D80
//#define CONFIG_SYS_ICACHE_OFF 1
.global _start
_start:
// 给5v电源置锁
// LDR指令:从内存中将1个32位的字读取到目标寄存器中
// STR指令:将1个32位的字数据写入到指令中指定的内存单元中
// ORR指令:逻辑或
// BIC指令:位清零
ldr r0,=PS_HOLD_CONTORL // r0 = 0xE010E81C
ldr r1,[r0] // 将r0地址处的数据读出,保存到r1中(零偏移)
orr r1,r1,#0x300 // 设置r1的第8、9位,其他位保持不变
orr r1,r1,#0x1 // 设置r1的第1位,其他位保持不变
str r1,[r0] // 将r1中的内容传输到r0中数指定的地址内存中去
//关看门狗
ldr r0, =WTCON // r0 = 0xE2700000
mov r1, #0 // r1 = 0
str r1, [r0] // 将r1中的内容传输到r0中数指定的地址内存中去
// 开/关iCache
// MRC指令:从协处理器寄存器传数据到ARM寄存器
// MCR指令:从ARM寄存器传数据到协处理器寄存器
mrc p15, 0, r0, c1, c0, 0
#ifdef CONFIG_SYS_ICACHE_OFF
bic r0, r0, #0x00001000 @ clear bit 12 (I) I-Cache
#else
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
#endif
mcr p15, 0, r0, c1, c0, 0
// 设置栈,以便调用c函数
ldr sp, =SVC_STACK
bl main /* 跳转到main函数 */
b . /* 死循环 */
-
LED灯控制代码
/*********************************************************
* > File Name: led.c
* > Author: fly
* > Create Time: 2021-06-26 6/25 21:46:02 +0800
*======================================================*/
typedef struct{
unsigned int GPD0CON;
unsigned int GPD0DAT;
unsigned int GPD0PUD;
unsigned int GPD0DRV;
unsigned int GPD0CONPDN;
unsigned int GPD0PUDPDN;
}gpd0;
#define GPD0 (*(volatile gpd0*)0xE02000A0)
typedef struct{
unsigned int GPJ0CON;
unsigned int GPJ0DAT;
unsigned int GPJ0PUD;
unsigned int GPJ0DRV;
unsigned int GPJ0CONPDN;
unsigned int GPJ0PUDPDN;
}gpj0;
#define GPJ0 (*(volatile gpj0*)0xE0200240)
void delay(volatile unsigned int i)
{
while(i--);
}
unsigned int readl(unsigned int addr)
{
return ( *((volatile unsigned int *)addr) );
}
void writel(unsigned int addr, unsigned int value)
{
*((volatile unsigned int *)addr) = value;
}
void led_init(void)
{
/* LED1 */
GPJ0.GPJ0CON = (GPJ0.GPJ0CON & ~(0xf<<12)) | (0x1<<12);
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<3)) | (0x1<<3);
/* LED2 */
GPJ0.GPJ0CON = (GPJ0.GPJ0CON & ~(0xf<<16)) | (0x1<<16);
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<4)) | (0x1<<4);
/* LED3 */
GPJ0.GPJ0CON = (GPJ0.GPJ0CON & ~(0xf<<20)) | (0x1<<20);
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<5)) | (0x1<<5);
/* LED4 */
GPD0.GPD0CON = (GPD0.GPD0CON & ~(0xf<<4)) | (0x1<<4);
GPD0.GPD0DAT = (GPD0.GPD0DAT & ~(0x1<<1)) | (0x1<<1);
}
void led_set_led1(unsigned int value)
{
if (value){
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<3)) | (0x0<<3);//ON
}else{
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<3)) | (0x1<<3);//OFF
}
}
void led_set_led2(unsigned int value)
{
if (value){
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<4)) | (0x0<<4);//ON
}else{
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<4)) | (0x1<<4);//OFF
}
}
void led_set_led3(unsigned int value)
{
if (value){
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<5)) | (0x0<<5);//ON
}else{
GPJ0.GPJ0DAT = (GPJ0.GPJ0DAT & ~(0x1<<5)) | (0x1<<5);//OFF
}
}
void led_set_led4(unsigned int value)
{
if (value){
GPD0.GPD0DAT = (GPD0.GPD0DAT & ~(0x1<<1)) | (0x0<<1);//ON
}else{
GPD0.GPD0DAT = (GPD0.GPD0DAT & ~(0x1<<1)) | (0x1<<1);//OFF
}
}
void led_set_all_led(unsigned int value)
{
if(value){
led_set_led1(1);
led_set_led2(1);
led_set_led3(1);
led_set_led4(1);
}else{
led_set_led1(0);
led_set_led2(0);
led_set_led3(0);
led_set_led4(0);
}
}
void tester_led(void)
{
led_init();
/* 流水灯 */
while(1){
led_set_led1(1);
delay(900000);
led_set_led1(0);
led_set_led2(1);
delay(900000);
led_set_led2(0);
led_set_led3(1);
delay(900000);
led_set_led3(0);
led_set_led4(1);
delay(900000);
led_set_all_led(1);
delay(900000);
led_set_all_led(0);
delay(900000);
}
}
void tester_breath_led(void)
{
#define CYCLE (3500)
unsigned int pwm;
led_init();
/* 呼吸灯 */
while(1){
/* LED灯渐渐变亮 */
for(pwm = 1; pwm < CYCLE; pwm++)
{
led_set_led4(0), delay(CYCLE - pwm);
led_set_led4(1), delay(pwm);
}
led_set_led4(1), delay(pwm/5);
/* LED灯渐渐熄灭 */
for(pwm = 1; pwm < CYCLE; pwm++)
{
led_set_led4(1), delay(CYCLE - pwm);
led_set_led4(0), delay(pwm);
}
led_set_led4(0), delay(pwm);
}
}
int main(int argc, char* argv[])
{
tester_breath_led();
return 0;
}
-
Makefile文件
# 将所有的.o文件链接成.elf文件,“-Ttext 0x0”
# 表示程序的运行地址是0x0,由于目前编写的是位置
# 无关码,可以在任一地址运行
# 将elf文件抽取为可在开发板上运行的bin文件
# 将elf文件反汇编保存在dis文件中,调试程序会用
# 添加文件头
.PHONY: all clean tools
CROSS ?= arm-linux-
NAME := LED
LD := $(CROSS)ld
OC := $(CROSS)objcopy
OD := $(CROSS)objdump
CC := $(CROSS)gcc
MK := ../../tools/mk_image/mkv210_image
CFLAGS := -nostdlib
all:$(NAME).bin
$(NAME).bin : start.o led.o
$(LD) -Ttext 0x0 -o $(NAME).elf $^
$(OC) -O binary $(NAME).elf $(NAME).bin
$(OD) -D $(NAME).elf > $(NAME)_elf.dis
$(MK) $(NAME).bin
# 将当前目录下存在的汇编文件及C文件编译成.o文件
%.o : %.S
$(CC) -o $@ $< -c $(CFLAGS)
%.o : %.c
$(CC) -o $@ $< -c $(CFLAGS)
clean:
$(RM) *.o *.elf *.bin *.dis *.sd
tools:
make -C ../../tools/mk_image/