用户态下直接操作GPIO/寄存器(linux应用篇)

本文介绍了一种在F1C100S CPU和Linux 5.2环境下,通过mmap方法直接操作寄存器来控制LED灯的方法。详细展示了如何使用C语言编程点亮和关闭特定的LED灯,并提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CPU:F1C100S
目标系统:linux5.2**

实验目的: 点亮LED灯。

PE4---LED1
PE5---LED2
PE6---LED3

实现方法: 写一个c程序通过mmap方法直接来操作寄存器。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

#define GPIO_REG_BASE   0x01C20800      //GPIO物理基地址 (小页4kb)
#define MAP_SIZE        0x400 //MMU页大小
#define GPIO_BASE_OFFSET (GPIO_REG_BASE & 0X00000FFF) //GPIO基地址偏移计算
#define GPIO_PAGE_OFFSET (GPIO_REG_BASE & 0XFFFFF000) //获得页偏移

#define rPE_CFG0 0X90  //PE_CFG0寄存器地址偏移
#define rPE_DAT 0XA0    //PE_DAT寄存器地址偏移
#define rPE_PULL0 0XAC  //PE_PULL0寄存器地址偏移

int GPIOE_456_ON(unsigned char *MAP_BASE);//点亮PE4,PE5,PE6 这3盏LED
int  GPIOE_456_OFF(unsigned char *MAP_BASE);//关闭PE4,PE5,PE6 这3盏LED

int main(int argc, char **argv)
{
 static int dev_fd;
 unsigned char *map_base;
/*参数验证*/
	if(argc!=2 || (strcmp(argv[1],"on") && strcmp(argv[1],"off"))){
   	 printf("argv_error!please input 'on' or 'off'!\n");
 	   exit (0);
	}

    dev_fd = open("/dev/mem", O_RDWR );
    if (dev_fd < 0){
        printf("open(/dev/mem) failed.\n");
        return 0;
    }

map_base = (unsigned char *)mmap(NULL, 0x400,PROT_READ | PROT_WRITE, MAP_SHARED,dev_fd, GPIO_PAGE_OFFSET); //把物理地址映射到虚拟地址
if(*map_base)  printf("mmap_fail!\n"); //是否映射成功

if(!strcmp(argv[1],"on")) GPIOE_456_ON(map_base); //点亮PE4,PE5,PE6 这3盏LED
if(!strcmp(argv[1],"off")) GPIOE_456_OFF(map_base);//关闭PE4,PE5,PE6 这3盏LED
  //usleep(1000000);
    if(dev_fd) close(dev_fd);
    munmap(map_base,MAP_SIZE);//解除映射关系
    return 0;
}


//GPIOE_456_ON
int  GPIOE_456_ON(unsigned char *MAP_BASE)
{
unsigned int PE_CFG0,PE_DAT;
PE_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0);
PE_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0)=((PE_CFG0 & 0XF000FFFF)|0X01110000);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT)=((PE_DAT & 0XFFFFFF8F)|0X00000070);
}
//GPIOE_456_OFF
int  GPIOE_456_OFF(unsigned char *MAP_BASE)
{
unsigned int PE_CFG0,PE_DAT;
PE_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0);
PE_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0)=((PE_CFG0 & 0XF000FFFF)|0X01110000);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT)=((PE_DAT & 0XFFFFFF8F));
}



编译代码并测试

# ./led2 on			/*点亮所有LED灯*/
# ./led2 off		/*开闭所有LED灯*/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yfw&武

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值