[ARM+Linux] 基于全志h616外设开发笔记

news2024/11/13 20:31:29

修改用户密码

配置网络

nmcli dev wifi 命令扫描周围WIFI热点

 

nmcli dev wifi connect  xxx password xxx 命令连接WiFi

查看ip地址的指令:

ifconfig

ip addr show wlan0

SSH登录

        这是企业开发调试必用方式,比串口来说不用接线,前提是接入网络并获得板子IP 地址,且系统做了SSH的服务器,本镜像自带 SSH 服务器,所以通过 mobaXterm 登陆就行

基于官方外设开发

1.wiringPi库SDK安装

git clone https : //github.com/orangepi-xunlong/wiringOP // 下载源码
cd wiringOP // 进入文件夹
sudo . / build clean // 清除编译信息
sudo . / build // 编译
通过 windows 浏览器打开 https : //github.com/orangepi-xunlong/wiringOP
下载压缩包
把压缩包通过 xterm 传到开发板
解压 unzip xxx . zip
cd xxx
sudo . / build
gpio readall
通过指令:gpio readall验证

设置tab缩进

⑥、设置tab缩进

sudo vim /etc/vim/vimrc

set tabstop=4 设置tab键缩进4个空格

set shiftwidth=4 设置批量对齐时候的tab键空格数为4

 

通过配置GPIO口,让蜂鸣器响 

#include<wiringPi.h>
#include <stdio.h>
#include <sys/time.h>

#define BEEP 0

int main()
{
    wiringPiSetup();//wiringPi库初始化
    pinMode(BEEP,OUTPUT);//配置GPIO口为输出端口
    while(1)
    {
        digitalWrite(BEEP,LOW);//蜂鸣器输出低电平响
        sleep(1);
        digitalWrite(BEEP,HIGH);//蜂鸣器输出高电平不响
        sleep(1);
    }
    return 0;
}

 因为编译关于配置gpio口的程序需要连接很多,比如:

-lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
所以我们可以编写一个简易的shell脚本
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt 
$1是待编译的文件名

超声波测距

超声波测距的原理就是当Trig发出波后开始计时,Echo会从低电平变为高电平,当接收到返回的波时,Echo会从高电平重新变回低电平,这时停止计时,计算发送和接收到波的时间,用速度x时间=距离来计算,速度= 340m/s(最后的距离单位是cm/s注意换算单位!!!)

(86条消息) [STM32F103C8T6] 超声波测距_TX564的博客-CSDN博客

 在全志h616中怎么获取时间呢?

我们会用到时间函数

#include<sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz )
gettimeofday() 会把目前的时间用 tv 结构体返回,当地时区的信息则放到 tz 所指的结构中
struct timeval
{
long tv_sec ; /* */
long tv_usec ; /* 微妙 */
};
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>

#define Trig 0
#define Echo 1

double getdistance()
{
   double dis;
   struct timeval start;
   struct timeval stop;
   pinMode(Trig,OUTPUT);
   pinMode(Echo,INPUT);

   digitalWrite(Trig,LOW);
   usleep(5);
   digitalWrite(Trig,HIGH);
   usleep(20);
   digitalWrite(Trig,LOW);
   while(!digitalRead(Echo));
   gettimeofday(&start,NULL);
   while(digitalRead(Echo));
   gettimeofday(&stop,NULL);
   long difftime = 1000000*(stop.tv_sec - start.tv_sec)+(stop.tv_usec - start.tv_usec);//乘以1000000是为了将s换算成us便于与后面相加
   dis = (double)difftime/1000000 * 34000/2;dis的单位是cm/us
   return dis;
}

int main()
{
    if(wiringPiSetup() == -1)
    {
        perror("error\n");
    } 
   while(1)
    {
        dis = getdistance();
        printf("dis = %ld\n",dis);
        sleep(1);
    }
}

全志h616在linux下的定时器

#include <sys/time.h>

setitimer() value 指向的结构体设为计时器的当前值,如果 ovalue 不是 NULL ,将返回计时器原有值。
int setitimer (__itimer_which_t __which,
const struct itimerval  *__restrict __new,
struct itimerval  *__restrict __old)
一般第三个参数设为NULL
which: 三种类型
ITIMER_REAL // 数值为0(底层吧ITIMER_REAL 宏定义为0),计时器的值实时递减,发送的信号是 SIGALRM 。---->用的最多
ITIMER_VIRTUAL // 数值为 1 ,进程执行时递减计时器的值,发送的信号是 SIGVTALRM
ITIMER_PROF // 数值为 2 ,进程和系统执行时都递减计时器的值,发送的信号是 SIGPROF

struct itimerval {
struct timeval it_interval;
struct timeval it_value;
};

it_interval:定时器初始值
it_value:当定时器被设置OK,延时多久时间去执行定时器计时 //这个值不能设置为0!!

struct timeval {
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};

__restrict __old:
可以不设置,用NULL

返回值: 成功执行时,返回0。失败返回-1

很明显,这边需要捕获对应的信号进行逻辑相关处理 signal(SIGALRM,signal_handler);

一个进程只能创建一个定时器!!!

每隔1s打印一次gogogo 

#include <stdio.h>
#include <sys/time.h>

/*
struct itimerval {
struct timeval it_interval;//初值
struct timeval it_value;//启动定时器时间
};*/

static i = 0;
void signal_handler()
{
    i++;
    if(i == 2000)
    {
        printf("gogoog\n");//每一秒打印一次
    }

}


int main()
{
    struct itimerval ivt;
    //设定初值
    ivt.it_interval.sec = 0;
    ivt.it_interval.usec = 500;//初值为500us
    //设定什么时候开启定时器
    ivt.it_value.sec = 1;//1s后开始启动定时器
    ivt.it_value.usec = 0;
    //设定定时方式
    setitimer(ITIMER_REAL,&ivt,NULL);
    //信号处理
    signal(SIGALRM,signal_handler);
    while(1);
}

 sg90舵机操作

sg90舵机的角度控制主要是pwm控制,pwm说白了就是占空比(高电平所占周期与总周期的比例)

#include <stdio.h>
#include <sys/time.h>

#define sg90 5
int jd;
static int i;

void signal_handler()
{
    if(i<=jd)
    {
        digitalWrite(sg90,HIGH);
    }else
    {
        digitalWrite(sg90,LOW);
    }
    if(i == 40)//总周期为20ms分成若干份作为pwm波
    {
        i = 0;
    }
    i++;
}


int main()
{
   struct itimerval ivt;
   //初始化
   wiringPiSetup();
   pinMode(sg90,OUTPUT);
   //设置定时器初值   
   ivt.it_interval.tv_sec = 0;
   ivt.it_interval.tv_usec = 500;      
   //设置几秒后启动定时器
   ivt.it_value.tv_sec = 1;
   ivt.it_value.tv_usec = 0; 
   //设置定时器模式
   if(setitimer(ITIMER_REAL,&ivt,NULL) == -1)
    {
        perror("error");
    }
   //信号处理
   signal(SIGALRM,signal_handler);
   while(1)
    {
        printf("choose jd:1-0,2-45,3-90,4-135,5-180");
        scanf("%d",&jd);
    }
}

基于iic的oled显示

 

开始测试 i2c , 首先安装 i2c-tools
使用命令:
sudo apt-get install i2c-tools

根据官方给的oled_demo来编写 

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
 
#include "oled.h"
#include "font.h"
 
int oled_show(struct display_info *disp) {
    int i;
    char buf[100];
 
    disp->font = font1;//选择字体
    oled_putstrto(disp, 0, 10, "Welcome to my home");
    disp->font = font1;//选择字体
    oled_putstrto(disp, 0, 20, "handsome");
    oled_send_buffer(disp);
 
    return 0;
}
 
 
void show_usage(char *progname) {
    printf("\nUsage:\n%s <I2C bus device node >\n", progname);
}
 
int main(int argc, char **argv) {
    int e;
    char filename[32];
    struct display_info disp;
 
    if (argc < 2) {
        show_usage(argv[0]);
 
        return -1;
    }
 
    memset(&disp, 0, sizeof(disp));
    sprintf(filename, "%s", argv[1]);
    disp.address = OLED_I2C_ADDR;
 
    e = oled_open(&disp, filename);
    e = oled_init(&disp);
    oled_show(&disp);
 
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手把手带你了解《线程池》

文章目录 线程池的概念池的目的线程池的优势为什么从池子里拿线程更高效&#xff1f;构造方法参数讲解线程拒绝策略模拟实现线程池一个线程池设置多少线程合适&#xff1f; 线程池的概念 线程池&#xff1a;提前把线程准备好&#xff0c;创建线程不是直接从系统申请&#xff0…

【linux】——日志分析

文章目录 1. 日志文件1.1 日志文件的分类1.2 日志文件保存位置1.2.1 内核及系统日志1.2.2 日志消息的级别1.2.3 日志记录的一般格式1.2.4 用户日志分析 程序日志分析日志管理策略 远程收集日志 1. 日志文件 1.1 日志文件的分类 ● 日志文件是用于记录Linux系统中各种运行消息的…

Flutter PC桌面端 控制应用尺寸是否允许放大缩小

一、需求 桌面端中&#xff0c;登录、注册、找回密码页面不允许用户手动放大缩小&#xff0c;主页面允许 二、插件 window_manager 使用教程请参照这篇博客&#xff1a;Flutter桌面端开发——window_manager插件的使用 题外话&#xff1a; 之前使用的是bitsdojo_window插件…

202303-第四周-山川软件产品资讯

山川软件愿为您提供最优质的服务。 您的每一个疑问都会被认真对待&#xff0c;您的每一个建议都将都会仔细思考。 我们希望人人都能分析大数据&#xff0c;人人都能搭建应用。 因此我们将不断完善DEMO、文档、以及视频&#xff0c;期望能在最大程度上快速帮助用户快速解决问…

3、Typescript中补充的六个类型

1、元组 元组可以看做是数组的拓展&#xff0c;它表示已知元素数量和类型的数组。确切地说&#xff0c;是已知数组中每一个位置上的元素的 类型&#xff0c;来看例子&#xff1a; let tuple: [string, number, boolean]; tuple ["a", 2, false]; tuple [2, "…

FPGA | 延迟模型

实际逻辑元器件和它们之间的传输路径都会存在延迟。因此&#xff0c;必须检查设计中的延迟是否满足实际电路的时序约束要求。可以用时序仿真的方法来检查时序&#xff08;timing&#xff09;&#xff0c;即在仿真时向元件或路径中加入和实际相符的延迟信息&#xff0c;并进行相…

4.34、组播(多播)

4.34、多播 1.组播(多播)的介绍①组播地址②如何设置组播&#xff08;组播的使用&#xff09; 2.代码编写①服务端②客户端 1.组播(多播)的介绍 单播地址标识单个 IP 接口&#xff0c;广播地址标识某个子网的所有 IP 接口&#xff0c;多播地址标识一组 IP 接口。单播和广播是寻…

ThreadPoolExecutor原理剖析

1.前言 1.1 为什么要使用线程池&#xff1f; 线程池主要为了解决两个问题 一是当执行大量异步任务时&#xff0c;线程池能够提供较好的性能&#xff0c;避免了重复创建和销毁线程带来的开销二是线程池提供了一种资源限制和管理的手段&#xff0c;比如限制线程个数&#xff0…

【蓝桥杯】最难算法没有之一· 动态规划真的这么好理解?(引入)

欢迎回到&#xff1a;遇见蓝桥遇见你&#xff0c;不负代码不负卿&#xff01; 目录 一、何为动态规划DP 二、记忆化搜索 典例1.斐波那契数列 方法一&#xff1a;暴力递归 方法二&#xff1a;记忆化搜索 变形题 典例2&#xff1a;爬楼梯&#xff08;青蛙跳台阶&#xf…

海睿思分享 | 低而不LOW的低代码开发

低代码&#xff08;Low-Code&#xff09; 是指输出最少的代码&#xff0c;快速完成软件系统开发&#xff0c;进而实现降低开发成本的成效。 Low-Code 中的“Low”与网络热词“LOW”同音同字&#xff0c;前者通常理解为低成本或少量的代码输出&#xff0c;后者是对低认知已见问…

【数据结构】数据结构小试牛刀之单链表

【数据结构】数据结构小试牛刀之单链表 一、目标二、实现1、初始化工作2、单链表的尾插2.1、图解原理2.2、代码实现解答一个疑问 3、单链表的尾删3.1、图解原理3.2、代码实现 4、打印单链表5、单链表的头插5.1、图解原理5.2、代码实现 6、单链表的头删6.1、图解原理6.2、代码实…

【Linux系统】理解Linux中进程间通信

Linux进程间通信 1 进程间通信的介绍1.1为什么要有进程间通信1.2 为什么能进程间通信 2 进程间通信的框架2.1 进程间通信机制的结构2.2 进程间通信机制的类型2.2.1 共享内存式2.2.2 消息传递式 2.3 进程间通信的接口设计 3 进程间通信机制简介4 详细讲解进程间通信部分机制&…

【OAuth2.0 Client 总结】对接github第三方登录以及其他第三方登录总结

之前搞 oauth 登录一直没有搞好&#xff0c;客户端、授权服务端、资源端一起搞对于我刚接触的小菜鸡来说&#xff0c;难度有点大。 然后就先搞了个 Client 端对接 Github 登录。 网上关于 Github 登录的资料有很多&#xff0c;而且框架对 Github 集成的也很好&#xff0c;配置起…

【深入解析K8S专栏介绍】

序言 时间永远是旁观者&#xff0c;所有的过程和结果&#xff0c;都需要我们自己去承担。 Kubernetes (k8s) 是一个容器编排平台&#xff0c;允许在容器中运行应用程序和服务。 专栏介绍 欢迎订阅&#xff1a;【深入解析k8s】专栏 简单介绍一下这个专栏要做的事&#xff1a; 主…

8年测试老兵竟被面试官10分钟pass,这也太难了吧...

前言 随着软件测试领域对于技术要求越来越清晰&#xff0c;到现在测试人员在市场上的岗位需求也变得越来越复杂。极大部分的企业都开始对自动化测试岗位有了更多的需要。自然而然&#xff0c;面试就相对于非常重要了。 笔试部分 1.阐述软件生命周期都有哪些阶段&#xff1f;…

stm32cubemx IAP升级(二)

stm32cubemx IAP升级- App的制作 板卡&#xff1a;Nucleo-L412 平台&#xff1a;macbook pro 工具&#xff1a;vscode stm32cubemx stm32cubeProgramer cmake toolchain 整体思路 将App设置为从0x08007000地址启动&#xff0c;然后初始化一路串口用作接收上位机的升级数据&a…

docker容器:docker镜像的三种创建方法及dockerfile案例

目录 一、基于现有镜像创建 1、创建启动镜像 2、生成新镜像 二、基于本地模板创建 1、OPENVZ 下载模板 2、导入容器生成镜像 三、基于dockerfile创建 1、dockerfile结构及分层 2、联合文件系统 3、docker镜像加载原理 4、dockerfile操作常用的指令 (1)FROM指令 (…

kotlin协程flow retry retryWhen(2)

kotlin协程flow retry retryWhen&#xff08;2&#xff09; 一、retry import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlockingfun main(args: Array<String>) {runBlocking {(1..5).asFlow().onEach {if (it 3) {println("-")throw Runti…

入行IC选择国企、私企还是外企?(内附各IC大厂薪资福利情况)

不少人想要转行IC&#xff0c;但不知道该如何选择公司&#xff1f;下面就来为大家盘点一下IC大厂的薪资和工作情况&#xff0c;欢迎大家在评论区补充。 一&#xff0e;老 牌 巨 头 在 IC 设计领域深耕许久&#xff0c;流程完善、技术扎实&#xff0c;公司各项制度都很完善、前…

关于改造维护工单BAPI_ALM_ORDER_MAINTAIN用于生产订单组件批量修改

1、研究背景 1.1、业务背景 由于销售、研发、工艺等需要频繁变更&#xff0c;导致工单中组件需要频繁的进行变更&#xff0c;修改组件的物料&#xff0c;数量&#xff0c;库存地点&#xff0c;工序等内容。 1.2、技术痛点 为了满足要求&#xff0c;使用了函数&#xff1a;CO…