如果是自己開發的板子,需要用GPIO引腳控制3G模塊開機/關機時,下面的文章會對你有所幫助,是以處理器IMX6和中興MG3732模塊爲例介紹。
一、引腳連接
處理器的gpio3_GPIO[9]連接3G模塊的ON/OFF(29)引腳來控制3G的開機/關機。
二、開關機條件
給ON/OFF引腳連續2500~3500毫秒低電平則開機,給再ON/OFF引腳連續2500~3500毫秒低電平則關機。
三、gpio驅動程序
gpio_3g.c
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/device.h>
#include<asm/io.h>
#include<linux/mm.h>
#include<asm/uaccess.h>
#include<linux/gpio.h>
#define GPIO_IOF_MAGIC 0xd0
#define 3G_INPUT _IO(GPIO_IOF_MAGIC,8)
#define 3G_OUTPUT _IO(GPIO_IOF_MAGIC,9)
#define 3G_ON_OFF IMX_GPIO_NR(3,9) //控制引腳爲:gpio3[9]
MODULE_LICENSE ("GPL");
int gpio_major=2555;
int gpio_minor=0;
int number_devices=1;
struct cdev gpiocdev;
struct class *my_class;
static int gpio_open(struct inode *inode,struct file *file)
{
printk (KERN_INFO "GPIO device opened\n");
if(gpio_direction_output(3G_ON_OFF,0x00)<0){
printk("3G_ON_OFF set direction failed\n");
}
return 0;
}
static long gpio_ioctl(struct file *file,unsigned int cmd,unsigned long arg)
{
int val;
printk("GPIO:ioctl running....\n");
switch(cmd){
case 3G_INPUT:
if(gpio_direction_input(3G_ON_OFF)<0){
printk("3G_ON_OFF set input failed\n");
}
if(arg>0){
gpio_set_value(3G_ON_OFF,0x01);
}else{
gpio_set_value(3G_ON_OFF,0x00);
}
val=gpio_get_value(3G_ON_OFF);
printk("3G_ON_OFF ioctl val=%d\n",val);
break;
case 3G_OUTPUT:
if(gpio_direction_output(3G_ON_OFF,0x00)<0){
printk("3G_ON_OFF set direction failed\n");
}
if(arg>0){
gpio_set_value(3G_ON_OFF,0x01);
}else{
gpio_set_value(3G_ON_OFF,0x00);
}
val=gpio_get_value(3G_ON_OFF);
printk("3G_ON_OFF ioctl val=%d\n",val);
break;
default:
printk("cmd is not exist\n");
return -1;
}
return val;
}
static int gpio_release (struct inode *inode, struct file *file)
{
printk (KERN_INFO "GPIO device closed\n");
return 0;
}
struct file_operations gpio_fops = {
.owner=THIS_MODULE,
.open=gpio_open,
.release=gpio_release,
.unlocked_ioctl=gpio_ioctl,
};
static void char_reg_setup_cdev (void)
{
int error;
dev_t devno;
devno=MKDEV(gpio_major,gpio_minor);
cdev_init(&gpiocdev,&gpio_fops);
gpiocdev.owner=THIS_MODULE;
error=cdev_add(&gpiocdev,devno,1);
if (error)
printk(KERN_NOTICE "Error %d adding char device GPIO",error);
}
static int __init gpio_init (void)
{
int result;
dev_t devno;
devno=MKDEV(gpio_major,gpio_minor);
if(gpio_major){
result=register_chrdev_region(devno,number_devices,"gpio_3g");
}else{
result=alloc_chrdev_region(&devno,0,number_devices,"gpio_3g");
gpio_major=MAJOR(devno);
}
if (result<0){
printk(KERN_WARNING "GPIO:can't get major number %d\n", gpio_major);
return result;
}
char_reg_setup_cdev ();
my_class=class_create(THIS_MODULE,"GPIOCLASS");
device_create(my_class,NULL,MKDEV(gpio_major,gpio_minor),NULL,"gpio_3g");
if(gpio_request(3G_ON_OFF,"UnKnow")<0){
printk("3G_ON_OFF request failed\n");
}
printk (KERN_INFO "char device GPIO registered\n");
return 0;
}
static void __exit gpio_exit(void)
{
dev_t devno=MKDEV(gpio_major,gpio_minor);
gpio_free(3G_ON_OFF);
cdev_del(&gpiocdev);
unregister_chrdev_region(devno,number_devices);
device_destroy(my_class,devno);
class_destroy(my_class);
printk(KERN_INFO"char device GPIO unregister\n");
}
module_init (gpio_init);
module_exit (gpio_exit);
四、內核添加gpio驅動步驟(android4.3源碼)
1、把gpio_3g.c放到~/myandroid/kernel_imx/drivers/char目錄下(假設源碼在~/myandroid下)。
2、~/myandroid/kernel_imx/drivers/char/Konfig中最後添加紅色框部分語句。
3、在~/myandroid/kernel_imx/drivers/char/Makefile中添加紅色框部分語句。
4、在~/myandroid/kernel_imx下 make menuconfig 來配置內核,配置完成後退出並保存。如下圖:
5、在進入~/myandroid/kernel_imx目錄執行:
cp .config arch/arm/configs/imx6_android_defconfig
到此後,行以下命令編譯:
source build/enevsetup.sh
lunch sabresb_6dq-user
make
五、編譯3G模塊開關機程序
1、程序代碼
3g_on_off.c
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#define 3G_INPUT _IO(GPIO_IOF_MAGIC,8)
#define 3G_OUTPUT _IO(GPIO_IOF_MAGIC,9)
#define SET_ON 0x01
#define SET_OFF 0x00
int main(int argc, char *argv[])
{
int fd;
fd=open("/dev/gpio_3g",O_RDWR); //打開gpio_3g設備文件
if(fd<0){
perror("open:");
}
if(ioctl(fd,3G_OUTPUT,SET_ON)<0){ //設置該引腳爲輸出高
perror("3G_OUTPUT ioctl:");
}
sleep(3);
if(ioctl(fd,3G_OUTPUT,SET_OFF)<0){ //設置該引腳爲輸出低
perror("3G_OUTPUT ioctl:");
}
if(ioctl(fd,3G_INPUT,SET_OFF)<0){ //設置該引腳爲輸入,防止被意外篡改
perror("3G_INPUT ioctl:");
}
close(fd);
return 0;
}
Android.mk
LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGES :=optional
LOCAL_MODULE :=3g_on_off
LOCAL_SRC_FILES :=3g_on_off.c
include $(BUILD_EXECUTABLE)
2、在~/myandroid/external下創建 3g_on_off文件夾
3、把 3g_on_off.c 和 Android.mk 文件放到新建文件夾下。
4、執行以下命令編譯:
source build/enevsetup.sh
lunch sabresb_6dq-user
mmm external/3g_on_off
5、把生成的可執行程序:
~/myandroid/out/target/product/sabresd_6dq/obj/EXECUTABLES/3g_on_off_intermediates/3g_on_off放到
~/myandroid/out/target/product/sabresd_6dq/system裏面
執行:make snod 打包
六、燒寫鏡像到開發板,執行3g_on_off程序對3G模塊進行開關機操作。
3G上電後,連接板子的調試串口終端會輸出以下紅色框的信息,此時表明已識別USB串口設備