全志V3s之应用层点灯

1、全志V3s的管脚控制简介:

全志V3s一共有5个端口可以作为输入输出,其数量如图所示:
在这里插入图片描述
端口的基地址为:PIO : 0x01c20800。其中,每个端口都有自己的偏移地址,其偏移计算公式如表所示:
在这里插入图片描述
PB端口为例,其偏移地址为0x24,默认值为0x77777777,共32位,0~2、4~6、8~10、12~14、16~18、20~22、24~26、28~30分别对应0、1、2、3、4、5、6、78个管脚。配置方式如图所示:
在这里插入图片描述
PB的数据寄存器的偏移地址为0x34,默认数值为0x00000000,配置如图所示:
在这里插入图片描述

2、点灯程序编写:

根据上述的寄存器,可以在应用层直接控制寄存器进行点灯操作。其程序如下:

#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 rPB_CFG0 0X24  //PB_CFG0寄存器地址偏移
#define rPB_DAT 0X34    //PB_DAT寄存器地址偏移
/***************************************************/
int led_on(unsigned char *MAP_BASE);
int led_off(unsigned char *MAP_BASE);
int main(int argc, char **argv)
{
    static int dev_fd;
    unsigned char *map_base;
    printf("led OK\r\n");

    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;
    }
    printf("Modified GPIO_PAGE_OFFSET: 0x%08X\n", GPIO_PAGE_OFFSET);
    map_base = (unsigned char *)mmap(NULL, 0x400,PROT_READ | PROT_WRITE, MAP_SHARED,dev_fd, GPIO_PAGE_OFFSET); //把物理地址映射到虚拟地址
    printf("Modified GPIO_PAGE_OFFSET: 0x%08X\n", GPIO_PAGE_OFFSET);
    printf("Modified map_base: 0x%08X\n", map_base);
    if(!strcmp(argv[1],"on")) led_on(map_base); //点亮LED
    if(!strcmp(argv[1],"off")) led_off(map_base);//关闭LED
    if(dev_fd) close(dev_fd);
    munmap(map_base,MAP_SIZE);//解除映射关系
    return 0;
}


//led_on
int  led_on(unsigned char *MAP_BASE)
{
    unsigned int PB_CFG0,PB_DAT;
    printf("Modified MAP_BASE: 0x%08X\n", MAP_BASE);
    PB_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_CFG0);
    printf("Modified PB_CFG0: 0x%08X\n", PB_CFG0);
    PB_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_DAT);
    printf("Modified PB_DAT: 0x%08X\n", PB_DAT);
    *(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_CFG0)=((PB_CFG0 & 0XFFFFFF0F)|0X00000010);//PB1 第2个引脚
    *(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_DAT)=((PB_DAT & 0XFFFFFFDF)|0X0000002);
}
//led_off
int  led_off(unsigned char *MAP_BASE)
{
    unsigned int PB_CFG0,PB_DAT;
    PB_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_CFG0);
    PB_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_DAT);
    *(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_CFG0)=((PB_CFG0 & 0XFFFFFF0F)|0X00000010);//PB1 第2个引脚
    *(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_DAT)=((PB_DAT & 0XFFFFFFFD));
}

3、编译执行:

a、编译生成可执行文件:

arm-linux-gnueabihf-gcc gpio_app.c -o gpio_app

通过交叉编译生成可执行文件
在这里插入图片描述

b、执行gpio_app可执行文件:

开灯:
在这里插入图片描述
在这里插入图片描述
关灯:
在这里插入图片描述
在这里插入图片描述

4、部分函数解释:

a、程序一:

map_base = (unsigned char *)mmap(NULL, 0x400,PROT_READ | PROT_WRITE, MAP_SHARED,dev_fd, GPIO_PAGE_OFFSET);

这行代码使用mmap函数将物理地址映射到虚拟地址。

  • NULL: 映射的开始地址。由于通常将其设置为NULL,操作系统会自动选择合适的地址。
  • 0x400: 这是映射的长度,也就是要映射的字节数。0x400,即1024字节
  • PROT_READ | PROT_WRITE: 这是保护位,指定对映射区域的访问权限。PROT_READ 表示可读,PROT_WRITE 表示可写。所以这个映射区域是可读可写的。
  • MAP_SHARED: 这表示映射区域对所有映射到这个对象的进程可见,对映射到同一个对象的其他进程也可见。通常用于共享内存。
  • dev_fd: 这是打开的设备文件描述符,指定了映射的对象。
  • GPIO_PAGE_OFFSET: 映射的偏移量,通常是物理地址的页面大小的倍数。在这里,是 GPIO_REG_BASE 的页面偏移。

这行代码的作用是创建一个大小为 0x400 字节的映射区域,使得你可以通过 map_base 指针访问这段内存。在这个例子中,它用于将物理地址映射到虚拟地址,以便后续的操作可以通过虚拟地址来访问 GPIO 寄存器。

b、程序二:

munmap(map_base,MAP_SIZE);

munmap 是一个系统调用,用于解除内存映射,即取消之前使用 mmap 函数创建的映射关系。

  • map_base: 是通过 mmap 映射得到的指向映射内存起始位置的指针。
  • MAP_SIZE: 是通过 mmap 映射的内存区域的大小。

这行代码的作用是取消 map_base 所指向的内存区域的映射,并释放相关资源。

c、程序三:

PB_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_CFG0);

这行代码用于从内存映射的地址中读取 PB_CFG0 寄存器的值。

  • MAP_BASE:这是通过 mmap 函数映射得到的内存的起始地址,它是一个指向映射内存区域的指针。
  • GPIO_BASE_OFFSET:这是 GPIO 基地址的偏移计算,它通常是为了从 GPIO_REG_BASE 中提取低12位的偏移。在这个上下文中,它可能是为了获取到 GPIO 寄存器的正确位置。
  • rPB_CFG0:这是 PB_CFG0 寄存器的地址偏移。
  • *(volatile unsigned int *) 就是告诉编译器将一个特定地址的内存解释为一个 volatile unsigned int 类型的值。这个表达式通常在底层系统编程中用于直接访问硬件寄存器或者内存地址。

整体来说,这行代码的作用是从内存映射区域中读取 PB_CFG0 寄存器的值,并将其赋给 PB_CFG0 变量。

d、程序四:

*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_CFG0)=((PB_CFG0 & 0XFFFFFF0F)|0X00000010);

这行代码的作用是配置 PB1 引脚的控制寄存器(PB_CFG0)

  • PB_CFG0 寄存器的原始值与 0XFFFFFF0F 进行按位与操作,目的是清除该寄存器中与 PB1 引脚相关的配置信息。其原始值为0x777777770XFFFFFF0F 按位与可得0x77777707
  • 通过按位或操作|,将 PB1 引脚的新配置信息 0X00000010 加入到寄存器中。0x777777070X00000010 按位或,则可得到0x77777717。其意思为:将PB0、PB2~PB7设置为IO Disable,将PB1设置为Output

e、程序五:

*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPB_DAT)=((PB_DAT & 0XFFFFFFDF)|0X0000002);

这行代码的作用是设置 PB1 引脚的数据输出寄存器(PB_DAT),即控制 PB1 引脚的高低电平。

  • PB_DAT 寄存器的原始值与 0XFFFFFFDF 进行按位与操作,目的是清除该寄存器中与 PB1 引脚相关的数据信息。其原始值为0x0,与 0XFFFFFFDF 进行按位与操作,可得0x0
  • 通过按位或操作 |,将 PB1 引脚的新数据信息 0X0000002 加入到寄存器中。将0x00X0000002 按位或可得0X0000002 ,其二进制表示为:0010

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/242349.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

业务代码-整合框架-存储-缓存常见错误详解一

一. java空指针和异常&#xff1a; 1.什么是空指针异常&#xff08;java.lang.NullPointException)&#xff1a; 1.1常见的空指针异常案例&#xff1a; public class WhatIsNpe {public static class User {private String name;private String[] address;public void print…

有监督学习、无监督学习、半监督学习和强化学习

有监督学习 训练数据有标签 无监督学习 数据是没有标签的 聚类的思想&#xff1a;通过计算空间中的距离来判断是否属于同一类 强化学习 和环境交互&#xff0c;从环境中学习 三者对比 半监督学习 少量有标注&#xff0c;大量无标注 三个假设 1.连续性/平滑性假设:相…

关于对RF射频方面性能要求各有不同

1.1 射频天线性能 对于一个射频设备每个公司对其合格指标要求都不一&#xff0c;有些公司注重于阻抗及电压驻波&#xff0c;有些公司注重与回波损耗及阻抗、有些只关注电压驻波。 1.2 射频的目的 其实射频天线的目的就是在不把无用的杂散放大超标准的前提下&#xff0c;把有用…

Nature 确认:大语言模型只是没有感情的「学人精」

DeepMind、EleutherAI 科学家提出&#xff0c;大模型只是在角色扮演。 ChatGPT 爆火后&#xff0c;大语言模型一跃而至&#xff0c;成为了行业与资本的宠儿。而在人们或是猎奇、或是探究地一次次对话中&#xff0c;大语言模型所表现出的过度拟人化也引起了越来越多的关注。 其实…

使用FluentAvalonia组件库快速完成Avalonia前端开发

前言 工欲善其事必先利其器,前面我们花了几篇文章介绍了Avalonia框架以及如何在Avalonia框架下面使用PrismAvalonia完成MVV模式的开发。今天我们将介绍一款重磅级的Avalonia前端组件库,里面封装了我们开发中常用的组件,这样就不用我们自己再写组件了。专注业务功能开发,提…

SpringBoot类文件具有错误的版本 61.0, 应为 55.0

4.SpringBoot入门案例 每一个从你生命中路过的人&#xff0c;都在教你成长&#xff0c;感恩的心&#xff0c;感谢一程陪伴&#xff0c;感谢曾经有你spring learn https://spring.io/projects/spring-boot#learn Getting Started Developing Your First Spring Boot Applicati…

Tcon基础知识

1、TCON&#xff0c;就是 Timing Controller 的缩写。从主芯片输出的要在 TFT 显示屏上显示的数据&#xff0c;在经过 TCON 模块后可以变换生成 Panel 可以直接利用的 DATA 信号和驱动器&#xff08;包括 source driver 和 gate driver&#xff09;的控制信号。 TV 市场上 TCO…

超声波测距HC-SR04模块的简单应用

文章目录 一、HC-SR04HC-SR04是什么&#xff1f;HC-SR04测距的原理 二、使用步骤1.硬件最远探测距离调节硬件连接 2.软件1.初始化配置代码如下&#xff08;示例&#xff09;&#xff1a;引脚初始化定时器初始化 2.引脚输入输出配置代码如下&#xff08;示例&#xff09;&#x…

OfficeWeb365 SaveDraw 文件上传漏洞复现

0x01 产品简介 OfficeWeb365 是专注于 Office 文档在线预览及PDF文档在线预览云服务,包括 Microsoft Word 文档在线预览、Excel 表格在线预览、Powerpoint 演示文档在线预览,WPS 文字处理、WPS 表格、WPS 演示及 Adobe PDF 文档在线预览。 0x02 漏洞概述 OfficeWeb365 Sav…

基于Leaflet的Webgis经纬网格生成实践

目录 前言 一、Leaflet.Graticule 1、参数说明 二、集成使用 1、新建网页模板 2、初始化地图对象 3、运行效果 三、源码调用分析 1、参数注入 2、经纬网构建 总结 前言 众所周知&#xff0c;在地球仪上或地图上&#xff0c;经线和纬线相互交织&#xff0c;就构成经纬…

揭示 ETL 系统架构中的 OLAP、OLTP 和 HTAP

探索 ETL 系统设计需要了解 OLAP、OLTP 和不断发展的 HTAP。让我们试图剖析这些范式的复杂性。 1. OLAP&#xff08;联机分析处理&#xff09;&#xff1a; OLAP 是商业智能的中流砥柱&#xff0c;通过 OLAP 立方体进行多维数据分析。这些立方体封装了预先聚合、预先计算的数据…

31、应急响应——Windows

文章目录 一、账户排查1.1 登录服务器的途径1.2 弱口令1.3 可疑账号 二、网络排查三、进程排查四、注册表排查五、内存分析 一、账户排查 1.1 登录服务器的途径 3389smb 445httpftp数据库中间件 1.2 弱口令 弱口令途径&#xff1a;3389、smb 445、http、ftp、数据库、中间件…

双指针的运用——双数之和II和三数之和

两数之和 https://leetcode.cn/problems/two-sum-ii-input-array-is-sorted/description/ 我们考虑这个排序过的数组&#xff0c;首先一个指针在最左&#xff0c;一个在最右。如果这两个数字比目标数字来的要小&#xff0c;那么如果我们左边指针移动了&#xff0c;移动后一定变…

【LeetCode刷题】-- 163.缺失的区间

163.缺失的区间 class Solution {public List<List<Integer>> findMissingRanges(int[] nums, int lower, int upper) {List<List<Integer>> res new ArrayList<>();for(int num : nums){if(lower < num){res.add(Arrays.asList(lower,num -…

计算机网络:数据链路层(介质访问控制)

欢迎关注大家关注我的公众号&#xff1a;浩泽学编程&#xff1b;联系我&#xff0c;一起交流学习&#xff0c;也可以解答你的迷茫。 目录 前言 一、静态划分信道&#xff08;信道划分介质访问控制&#xff09; 1、频分多路复用FDM 2、时分多路复用TDM 3、波分多路复用WDM …

基于单片机智能自动浇花系统设计

**单片机设计介绍&#xff0c;基于单片机智能自动浇花系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的智能自动浇花系统是一种可以自动感知周围环境&#xff0c;并执行相应动作的系统。通过使用传感器检测土…

微服务--07--Sentienl中使用的限流算法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Sentienl中使用的限流算法1、计数器固定窗口算法2、计数器滑动窗口算法----&#xff08;默认&#xff09;3、漏桶算法----&#xff08;排队等待&#xff09;4、令牌…

如何想成为嵌入式工程师?(这些东西您必须知道)

嵌入式的发展怎么样&#xff1f; 嵌入式系统领域一直在迅速发展&#xff0c;伴随着物联网、智能设备、汽车电子、医疗设备等应用的不断增加&#xff0c;对嵌入式技术的需求也在不断扩大。因此&#xff0c;嵌入式领域仍然是一个充满机会的领域&#xff0c;为专业人士提供…

AGI 营销价值持续释放,Whale 帷幄近期荣誉时刻有哪些?

临近年底&#xff0c;各类奖项、活动、盘点层出不穷&#xff0c;是营销界最活跃也是最丰收的时刻。近期&#xff0c;「Whale 帷幄」凭借着对数字化营销销售场景的独到洞察和扎实的落地应用能力&#xff0c;不仅为客户带来了业绩提升&#xff0c;也斩获了多项权威奖项&#xff0…

AI全栈大模型工程师(二十六)如何选择 GPU 和云服务厂商

&#x1f4a1; 这节课会带给你 如何选择 GPU 和云服务厂商&#xff0c;追求最高性价比 如何部署自己 fine-tune 的模型&#xff0c;向业务提供高可用推理服务 如何控制内容安全&#xff0c;做好算法备案&#xff0c;确保合规 开始上课&#xff01; 硬件选型 当我们为模型训练及…