这段时间在学习ARM9嵌入式系统——Mini2451开发板,首先是硬件的学习,然后学习linux系统的移植,最后是linux驱动的学习。前段时间学了STM32F1,对ARM芯片有了一定的了解,感觉对S3C2451芯片的学习有很大的帮助,很多名词都是一样的,功能也是大同小异。
学习S3C2451和学习单片机、STM32是一样的方法,第一步先尝试点亮LED吧。点亮LED用了三种方法,
①汇编语言点亮LED
②C语言操作寄存器点亮LED
③C语言自己写库函数,操作库函数点亮LED(类似于STM32的库函数)
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。
#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);
}
}
原理还是和汇编语言一样的,只是换了一种语言和写法。
/************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);
}
}