最近正在学习arm裸机,所用的开发板是友善之臂的arm9-s3c2451开发板,发现没有向stm32开发板那样可以用库函数开发,只能使用寄存器来开发,非常痛苦,在参考了stm32的封装以及前辈的指导下,我对s3c2451的GPIO口进行了初步封装,大大提高的开发效率,适合二次开发。
s3c2451.h
#ifndef _S3C2451_GPIO_H_ #define _S3C2451_GPIO_H_ #include "typedef.h" typedef struct{ U32 GPCON; //配置端口引脚 输入/输出 U32 GPDAT; //配置高低电平 U32 GPUDP; //上拉 下拉设置 U32 GPSEL; //模式设置 }volatile *GPIO_MenMapPtr;//结构体存储,顺序对其即会补齐的,还有顺序很重要要对应地址,相差4 #define GPIOA_BASE_PTR ((GPIO_MenMapPtr)0x56000000) //每个i/o口的起始地址 #define GPIOB_BASE_PTR ((GPIO_MenMapPtr)0x56000010) #define GPIOC_BASE_PTR ((GPIO_MenMapPtr)0x56000020) #define GPIOD_BASE_PTR ((GPIO_MenMapPtr)0x56000030) #define GPIOE_BASE_PTR ((GPIO_MenMapPtr)0x56000040) #define GPIOF_BASE_PTR ((GPIO_MenMapPtr)0x56000050) #define GPIOG_BASE_PTR ((GPIO_MenMapPtr)0x56000060) #define GPIO_PIN0 (1<<0) //各个i/o口的第几个端口 #define GPIO_PIN1 (1<<1) #define GPIO_PIN2 (1<<2) #define GPIO_PIN3 (1<<3) #define GPIO_PIN4 (1<<4) #define GPIO_PIN5 (1<<5) #define GPIO_PIN6 (1<<6) #define GPIO_PIN7 (1<<7) #define GPIO_PIN8 (1<<8) #define GPIO_PIN9 (1<<9) #define GPIO_PIN25 (1<<25) #define GPIO_PIN26 (1<<26) typedef enum { GPIOA=0, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG }GPIO_typedef; //枚举的使用方法,默认第一位为零当然自己也可以自己设变量的值 typedef enum { BIT_RESET=0, //低电平 BIT_SET //低电平 }BIT_typedef; //高低电平的设置 typedef enum { GPIO_MODE_IN=0, //输入模式 GPIO_MODE_OUT, //输出模式 GPIO_MODE_ALT1, //模式1 GPIO_MODE_ALT2 //模式2 }GPIO_MODE_typedef; //模式的选择 typedef enum { GPIO_UDP_DISABLE=0, //不使能设置 GPIO_UDP_DOWN, //下拉设置 GPIO_UDP_UP, //上拉设置 GPIO_UDP_NOAVAILABLE }GPIO_UDP_typedef; typedef struct { U32 pinx; GPIO_MODE_typedef mode; GPIO_UDP_typedef udp; }GPIO_Init_typedef; //定义i/o口初始化结构体 extern void GPIO_INIT(GPIO_typedef portx,GPIO_Init_typedef gpio_init_typedef); //初始化函数 extern void GPIO_write(GPIO_typedef portx,U32 pinx,BIT_typedef bit); //写函数 extern BIT_typedef GPIO_read(GPIO_typedef portx,U32 pinx); //读函数 #endif 各个函数的实现 #include "s3c2451_gpio.h" GPIO_MenMapPtr 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 }; void GPIO_INIT(GPIO_typedef portx,GPIO_Init_typedef gpio_init_typedef) { int i; for(i=0;i<32;i++) { if((gpio_init_typedef.pinx && (1<<i))==(1<<i)) //判断是否有针脚号存在,如果有再判断是哪一个PORT口 { if(portx==GPIOA) //A口的工作模式设置 { if(gpio_init_typedef.mode==GPIO_MODE_OUT) //判断A口是否为输出模式 { PORT_BASE_PTR[portx]->GPCON &= ~(1<<i); //如果为输出模式则将相应的位清零 } else if(gpio_init_typedef.mode==GPIO_MODE_ALT1) //如果为其它工作模式 { PORT_BASE_PTR[portx]->GPCON |=(1<<i); //其他工作模式置一 } } else //除A口之外的工作模式设置 { PORT_BASE_PTR[portx]->GPCON &=~(0x3<<(2*i)); //先进行清零操作 PORT_BASE_PTR[portx]->GPCON |=(gpio_init_typedef.mode<<(2*i)); //对A口之外的端口进行模式设置 PORT_BASE_PTR[portx]->GPUDP &=~(0x3<<(2*i)); //进行清零操作 PORT_BASE_PTR[portx]->GPUDP |=(gpio_init_typedef.udp<<(2*i)); //进行UDP的功能模式设置 } } } } void GPIO_write(GPIO_typedef portx,U32 pinx,BIT_typedef bit) { if(bit==BIT_SET) //判断某个PORT口的某个位是否置高 { PORT_BASE_PTR[portx]->GPDAT |=pinx; //如果是则将该位置为高电平 } else if(bit == BIT_RESET) //反之则将该位置为低电平 { PORT_BASE_PTR[portx]->GPDAT &=~pinx; } } BIT_typedef GPIO_read(GPIO_typedef portx,U32 pinx) { if((PORT_BASE_PTR[portx]->GPDAT & pinx)==pinx ) //判断针脚是否为置高 { return BIT_SET; //如果是则返回BIT_SET即1 } else { return BIT_RESET; //如果是则返回BIT_RESET即0 } }