嵌入式系统学习——S3C2451点亮LED

  这段时间在学习ARM9嵌入式系统——Mini2451开发板,首先是硬件的学习,然后学习linux系统的移植,最后是linux驱动的学习。前段时间学了STM32F1,对ARM芯片有了一定的了解,感觉对S3C2451芯片的学习有很大的帮助,很多名词都是一样的,功能也是大同小异。

  学习S3C2451和学习单片机、STM32是一样的方法,第一步先尝试点亮LED吧。点亮LED用了三种方法,

①汇编语言点亮LED

②C语言操作寄存器点亮LED

③C语言自己写库函数,操作库函数点亮LED(类似于STM32的库函数)


一、汇编语言点亮LED

    AREA Init, CODE ,READONLY
	ENTRY
	
start
    ;关闭看门口
    ldr r0,=0x53000000
	ldr r1,=0
	str r1,[r0]
	
	ldr r0, = 0x56000000
	ldr r1, = 0
	str r1, [r0];设置GPA为输出
	
	ldr r0, = 0x56000010
	ldr r1, = 0x5 << 10
	str r1, [r0];设置GPB为输出
	
	ldr r0, = 0x5600001c
	ldr r1, = 0x0
	str r1, [r0];GPB复用了特殊功能引脚,设置为输出模式
	
	
	
	
led_blink
    ;led on
	ldr r0, = 0x56000004
	ldr r1, = 0					
	str r1, [r0]				;GPA所有引脚输出0
	
	ldr r0, = 0x56000014
	ldr r1, = 0					
	str r1, [r0];				;GPB所有引脚输出0
	
	bl delay
	;led off
	ldr r0, = 0x56000004
	ldr r1, = (0x3 << 25)
	str r1, [r0];				;GPA25和26输出高点平
	
	ldr r0, = 0x56000014
	ldr r1, = (0x3 << 5)
	str r1, [r0];				;GPB5和6输出高点平
	
	bl delay
	
	bl led_blink
	

	
delay
    ldr r0, = 0x100000
delay_loop
    cmp r0,#0
    sub r0,r0,#1
	bne delay_loop
	mov pc ,lr
	
    END
  这里主要需要操作两个寄存器,GPACON和GPADAT来操作GPA25和26口输出低电平点亮LED,GPBCON和GPBDAT来操作GPB5和6口输出低电平点亮LED。S3C2451中GPACON地址为0x56000000,GPADAT地址为0x56000004,GPBCON地址为0x56000010,GPBDAT地址为0x56000014。


二、C语言直接操作寄存器

#ifndef _S3C2451_LED_H
#define _S3C2451_LED_H

#define GPACON 		(*(volatile unsigned long*)0x56000000)		//GPA的控制脚
#define GPADAT		(*(volatile unsigned long*)0x56000004)		//GPA的数据位
	
#define GPBCON		(*(volatile unsigned long*)0x56000010)		//GPB的控制脚
#define GPBDAT		(*(volatile unsigned long*)0x56000014)		//GPB的数据位
#define GPBUDP		(*(volatile unsigned long*)0x56000018)		//GPB的上拉下拉控制位
#define GPBSEL		(*(volatile unsigned long*)0x5600001c)		//GPB的功能选择位

#define LEDA_ON(i)		(GPADAT &= ~(0x1 << i))
#define LEDA_OFF(i)		(GPADAT |=  (0x1 << i))

#define LEDB_ON(i)		(GPBDAT &= ~(0x1 << i))
#define LEDB_OFF(i)		(GPBDAT |=  (0x1 << i))

extern void LED_INIT(void);

#endif

/**直接操作寄存器
  *
  **/
void LED_INIT(void)
{
	
	GPACON &= ~(0x3 << 25); 			//GPACON25和26赋0,点亮LED
	GPBCON &= ~(0xF << 10);				//GPBCON先清零
	GPBCON |=  (0x5 << 10);				//GPACON设置输出
	
	/*
	 *GPACON     1111 1001 1111 1111 1111 1111 1111 1111
	 *GPACON = 0xF9FFFFFF
	 *GPBCON     1111 1111 1111 0000 0001 0111 1111 1111
	 *GPBCON = 0xFFF017FF
	 */	
}

void delay_ms(unsigned int xms)
{
	unsigned int j;
	for(; xms > 0; xms--)
	{
		for(j = 500; j > 0; j --);
	}
}

void Main(void)
{
/*****寄存器点亮LED************/
	LED_INIT();
	BEEP_INIT();
	while(1)
	{		
		BEEP_ON();
		
		LEDB_OFF(6);
		LEDA_ON(25);
		delay_ms(2000);
		
		BEEP_OFF();
		
		LEDA_OFF(25);
		LEDA_ON(26);
		delay_ms(2000);	
		
		LEDA_OFF(26);
		LEDB_ON(5);
		delay_ms(2000);	
		
		LEDB_OFF(5);
		LEDB_ON(6);			
		delay_ms(2000);	
	}
}
  原理还是和汇编语言一样的,只是换了一种语言和写法。


三、C语言编写库函数,利用库函数操作GPIO

/************S3C2451_GPIO.h*******************/
#ifndef _S3C2451_GPIO_H
#define _S3C2451_GPIO_H

#include "typedef.h"

typedef struct {
	U32 GPCON;
	U32 GPDAT;
	U32 GPUDP;
	U32 GPSEL;
}volatile* GPIOMEMabptr;

#define GPIOA_BASE_PTR			((GPIOMEMabptr)0x56000000)
#define GPIOB_BASE_PTR			((GPIOMEMabptr)0x56000010)
#define GPIOC_BASE_PTR			((GPIOMEMabptr)0X56000020)
#define GPIOD_BASE_PTR			((GPIOMEMabptr)0x56000030)
#define GPIOE_BASE_PTR			((GPIOMEMabptr)0x56000040)
#define GPIOF_BASE_PTR			((GPIOMEMabptr)0x56000050)
#define GPIOG_BASE_PTR  		((GPIOMEMabptr)0X56000060)

#define GPIO_Pin_0				(1<<0)
#define GPIO_Pin_1				(1<<1)
#define GPIO_Pin_2				(1<<2)
#define GPIO_Pin_3				(1<<3)
#define GPIO_Pin_4				(1<<4)
#define GPIO_Pin_5				(1<<5)
#define GPIO_Pin_6				(1<<6)
#define GPIO_Pin_7				(1<<7)
#define GPIO_Pin_8				(1<<8)
#define GPIO_Pin_9				(1<<9)
#define GPIO_Pin_10				(1<<10)
#define GPIO_Pin_11 			(1<<11)
#define GPIO_Pin_12				(1<<12)
#define GPIO_Pin_13				(1<<13)
#define GPIO_Pin_14				(1<<14)
#define GPIO_Pin_15				(1<<15)
#define GPIO_Pin_16				(1<<16)
#define GPIO_Pin_17 			(1<<17)
#define GPIO_Pin_18				(1<<18)
#define GPIO_Pin_19				(1<<19)
#define GPIO_Pin_20				(1<<20)
#define GPIO_Pin_21				(1<<21)
#define GPIO_Pin_22				(1<<22)
#define GPIO_Pin_23				(1<<23)
#define GPIO_Pin_24				(1<<24)
#define GPIO_Pin_25				(1<<25)
#define GPIO_Pin_26				(1<<26)

typedef enum{
	BIT_RESET = 0,
	BIT_SET
}BIT_Typedef;

typedef enum{
	GPIOA = 0,
	GPIOB,
	GPIOC,
	GPIOD,
	GPIOE,
	GPIOF,
	GPIOG
}GPIO_Typedef;

typedef enum{
	GPIO_MODE_IN = 0,
	GPIO_MODE_OUT,
	GPIO_MODE_ALT1,
	GPIO_MODE_ALT2
}GPIO_MODE_Typedef;

typedef enum{
	GPIO_UDP_DISABLE = 0,
	GPIO_UDP_DOWN,
	GPIO_UDP_UP,
	GPIO_UDP_UNAVAILABLE
}GPIO_UDP_Typedef;

typedef struct {
	U32  				pinx;
	GPIO_MODE_Typedef 	mode;
	GPIO_UDP_Typedef 	udp;
}GPIO_InitType;


extern void GPIO_Init(GPIO_Typedef port, GPIO_InitType gpio_init_typedef);
extern void GPIO_WriteBit(GPIO_Typedef port, U32 pinx, BIT_Typedef bit);
extern BIT_Typedef GPIO_ReadBit(GPIO_Typedef port, U32 pinx);

#endif

/*********s3c2451_gpio.c************/
#include "s3c2451_gpio.h"

/**
  *GPIOMEMabptr类型的数组,将GPIOA-G与GPIOA_BASE_PTR-GPIOG_BASE_PTR相连
  **/
GPIOMEMabptr const PORT_BASE_PTR[7] = {
										GPIOA_BASE_PTR,
										GPIOB_BASE_PTR,
										GPIOC_BASE_PTR,
										GPIOD_BASE_PTR,
										GPIOE_BASE_PTR,
										GPIOF_BASE_PTR,
										GPIOG_BASE_PTR
									  };	

/**函数名:GPIO_Init
  *参数:端口gpiox,端口初始化结构体gpio_init_typedef
  *功能:初始化GPIO的各个控制寄存器
  **/
void GPIO_Init(GPIO_Typedef port, GPIO_InitType gpio_init_typedef)
{
	unsigned int i;
	for(i = 0; i < 32; i++)
	{
		if(gpio_init_typedef.pinx && (1<GPCON &= ~(0x1<GPCON |= (0x1<GPCON &= ~(2*i);
				PORT_BASE_PTR[port]->GPCON |= (gpio_init_typedef.mode<<(2*i));
				
				PORT_BASE_PTR[port]->GPUDP &= ~(2*i);
				PORT_BASE_PTR[port]->GPUDP |= (gpio_init_typedef.udp<<(2*i));
			}
		}
	}
}

/**函数名:GPIO_WriteBit
  *参数:端口port,引脚pinx,写入的数据bit
  *功能:向某个引脚写入高电平或低电平
  **/
void GPIO_WriteBit(GPIO_Typedef port, U32 pinx, BIT_Typedef bit)
{
	if(bit == BIT_SET)
	{
		PORT_BASE_PTR[port]->GPDAT |= pinx;
	}
	else if(bit == BIT_RESET)
	{
		PORT_BASE_PTR[port]->GPDAT &= ~pinx;
	}
}

/**函数名:GPIO_ReadBit
  *参数:端口port,引脚pinx
  *返回值:读取的高低电平
  *功能:从某个引脚读取高电平或低电平
  **/
BIT_Typedef GPIO_ReadBit(GPIO_Typedef port, U32 pinx)
{
	if((PORT_BASE_PTR[port] && pinx) == pinx)
	{
		return BIT_SET;
	}
	else
	{
		return BIT_RESET;
	}
}

/**通过函数操作寄存器
  *
  **/
void LED_INIT(void)
{
	GPIO_InitType gpio_init_typedef;
	gpio_init_typedef.pinx = GPIO_Pin_25 | GPIO_Pin_26;
	gpio_init_typedef.mode = GPIO_MODE_OUT;
	gpio_init_typedef.udp = GPIO_UDP_UP;
	GPIO_Init(GPIOA, gpio_init_typedef);
	
	gpio_init_typedef.pinx = GPIO_Pin_5 | GPIO_Pin_6;
	GPIO_Init(GPIOB, gpio_init_typedef);
}

void delay_ms(unsigned int xms)
{
	unsigned int j;
	for(; xms > 0; xms--)
	{
		for(j = 500; j > 0; j --);
	}
}

void Main(void)
{
	LED_INIT();
	while(1)
	{
		GPIO_WriteBit(GPIOA, GPIO_Pin_25 | GPIO_Pin_26, BIT_SET);
		GPIO_WriteBit(GPIOB, GPIO_Pin_5 | GPIO_Pin_6, BIT_SET);
		delay_ms(2000);
		GPIO_WriteBit(GPIOA, GPIO_Pin_25 | GPIO_Pin_26, BIT_RESET);
		GPIO_WriteBit(GPIOB, GPIO_Pin_5 | GPIO_Pin_6, BIT_RESET);
		delay_ms(2000);
	}
}

  至此,GPIO的三种操作方法就讲述完毕,第三种库函数实际上和STM32的库函数异曲同工,只是STM32的库函数正点原子已经提供了,但是s3c2451的库函数没有提供,还得自己编写。编写完这个库函数之后,感觉对C语言有了更加深入的了解,看到了C语言与众不同的用法。

你可能感兴趣的:(嵌入式系统S3C2451)