2 szu zengp szu_zengp 于 2014.12.03 16:48 提问

mini2440 led驱动 gpio接口连线

mini2440开发板linux系统下的控制led实验,控制用户led,分别对应的是gpb5、gpb6、gpb7、gpb8,成功了。
随后我修改驱动程序代码,改为控制gpb1、gpb6、gpb7、gpb8,用杜邦线连接gpb1,连接一个led,在终端输入控制命令
“开led”和“关led”,结果不能控制连接着gpb1的led,其余三个用户led正常,测量了gpb1和gnd的电压,在“开led”和“关led”两种命令下,
其电压均为3v左右。随后我又修改驱动程序代码,改为控制gpb0和gpb6、gpb7、gpb8,gpb0是连接着内部蜂鸣器的,在终端输入控制命令“开led”和“关led”,
可以控制蜂鸣器的开和关。在“开led”和“关led”的两种命令下。其对应的电压分别为1.6v和0v。为啥我只是修改了引脚代码,就不能控制其他端口呢?实物连线图

2个回答

szu_zengp
szu_zengp   2014.12.03 16:50
已采纳

具体连线

devmiao
devmiao   Ds   Rxr 2014.12.03 19:18

mini2440的led接了4个GPIO,分别是GPB5-8

关于这几个GPIO的寄存器描述可以看三星的文档,主要是GPBCON,GPBDAT和GPBUP,GPBCON寄存器可以表示某引脚是输入功能还是输出功能,因为这些引脚是复用的。GPBDAT用来给某引脚读写数据的。GPBUP表示是否使用内部上拉电阻,这里没有用上,貌似,不懂。

linux对ARM支持很好,有关gpio的操作都有函数写好了,直接用就可以。

以前真是傻呀,自己写,呵呵。

linux/arch/arm/plat-s3c24xx/gpio.c描述了对gpio的操作,这里用到两个函数:

s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

s3c2410_gpio_setpin(led_table[i], 0);

第一个函数是设置led_table[i]表示的引脚为输入或者输出(led_cfg_table[i]定义的),其实就是设置GPBCON寄存器;

第二个函数是设置引脚读写数据为0或者其他值,比如1.

led_table[i], led_cfg_table[i]在这个文件里都有定义,定义中涉及的宏S3C2410_GPB6 和S3C2410_GPB6_OUTP 之类都在arch/arm/mach-s3c2410/include/mach/regs-gpio.h中定义好了。

下面的就是LED的驱动程序:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define DEVICE_NAME "leds" 设备名

static unsigned long led_table [] = { 4个对应的引脚

S3C2410_GPB5,

S3C2410_GPB6,

S3C2410_GPB7,

S3C2410_GPB8,

};

static unsigned int led_cfg_table [] = { 引脚功能都是输出

S3C2410_GPB5_OUTP,

S3C2410_GPB6_OUTP,

S3C2410_GPB7_OUTP,

S3C2410_GPB8_OUTP,

};

static int sbc2440_leds_ioctl( ioctl具体实现,对应应用程序中的ioctl

struct inode *inode, 

struct file *file,   这个参数对应应用程序中的第一个参数,文件

unsigned int cmd, 两个值,0或1,led灭或者亮

unsigned long arg)  参数个数,不能超过4,表示只有4个led

{

switch(cmd) {

case 0:

case 1:

    if (arg > 4) {

        return -EINVAL;

    }

    s3c2410_gpio_setpin(led_table[arg], !cmd); 设置某个led数据0或1

    return 0;

default:

    return -EINVAL;

}

}

file_operations 数据结构填充

static struct file_operations dev_fops = {

.owner    =    THIS_MODULE,

.ioctl    =    sbc2440_leds_ioctl,对应的ioctl函数实现

};

misc设备,也就是非字符,非块,非网络,其他设备。这种设备统一采用一个主设备号

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR, 次设备号

.name = DEVICE_NAME,

.fops = &dev_fops,

};

static int __init dev_init(void) 初始化设备

{

int ret;

int i;



for (i = 0; i < 4; i++) {

   设置引脚为输出功能


    s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

   各引脚写入0,即都是不亮的 


   s3c2410_gpio_setpin(led_table[i], 0);

}

ret = misc_register(&misc); 注册misc设备

printk (DEVICE_NAME"\tinitialized\n");

return ret;

}

static void __exit dev_exit(void)

{

misc_deregister(&misc);  注销misc设备

}

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("FriendlyARM Inc.");

led的应用程序如下:
#include

#include

#include

#include

int main(int argc, char **argv) 带参数,一共是三个

{

int on;

int led_no;

int fd;


//if条件表示,有三个参数,on的值只能是0或者1,led_no的值只能是0-3


//sscanf的返回值为0,出错,否则返回正确格式化数据的个数,这样就确保main参数每个都读的争取

if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 ||

 on < 0 || on > 1 || led_no < 0 || led_no > 3) {

    fprintf(stderr, "Usage: leds led_no 0|1\n");

    exit(1);

}

fd = open("/dev/leds0", 0);  不知道什么意思?

if (fd < 0) {

    fd = open("/dev/leds", 0); 读取设备

}

if (fd < 0) {

    perror("open device leds");

    exit(1);

}

ioctl(fd, on, led_no);  调用ioctl,和驱动里的对应。不过那个ioctl函数貌似四个参数,第一个参数是inode节点,后面三个和这里是对应的,有点茫然。

close(fd);

return 0;

}

交叉编译后,执行:

#./led 2 1

第三个led亮

szu_zengp
szu_zengp 驱动程序我都有,问题是我把驱动程序中的一个引脚改为GPB1,然后用线外接一个led,就无法控制led了
大约 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!