C基础与SDK调试方法

news2024/11/27 16:32:30

REVIEW

上次学习了一下软件使用流程zynq PS点灯-CSDN博客

本次学习一下C编程基础与调试方法

 1.  硬件编程原理

小梅哥视频链接:

07_Xilinx嵌入式裸机硬件编程原理_哔哩哔哩_bilibili

对应的课程笔记:【zynq课程笔记】【裸机】【第7课 】【硬件编程原理】 - ACZ702开发板 - 芯路恒电子技术论坛 - Powered by Discuz! (corecourse.cn)

①典型GPIO结构

R1:方向/输出使能控制寄存器
R2:输出状态/数据寄存器
R3:输入状态/数据寄存器

②Zynq7000 GPIO结构

zynq PS端 GPIO-CSDN博客

GPIO控制的编程思路

初始化
根据GPIO对应位的工作场景,设置其方向、中断屏蔽位、中断检测类型。
工作
输入:若开启了中断,则编写中断处理函数;

           若不开启中断,则在需要的时候直接读取输入寄存器的值。
输出:则通过写数据寄存器或输出置位/清零寄存器来修改该位的输出值。

2.  寄存器操作

小梅哥视频:06_Zynq SoC嵌入式逻辑C编程基础_哔哩哔哩_bilibili

课程笔记:【zynq课程笔记】【裸机】【第6课 】【C编程基础】 - ACZ702开发板 - 芯路恒电子技术论坛 - Powered by Discuz! (corecourse.cn)

cpu编程,本质上就是对指定地址进行读写操作

视频课程用到的代码:实现让开发板上的PS_LED0亮灭

        端口为MIO7

场景分析:该场景下只需要简单的控制GPIO的对应位输出高低电平即可,用不到中断功能。
初始化
关闭中断
INT_DIS/ INT_EN:
这是一组作用于同一个功能的2个独立的寄存器,一个负责使能GPIO的每一位的中断,另一个负责禁止GPIO的每一位的中断。
本应用中,对应GPIO无需开启中断,所以设计时针对INT_DIS/ INT_EN寄存器,需要明确:
关闭某位中断该操作哪个寄存器,往该寄存器写0关闭中断,还是写1关闭中断。
根据UG585中的描述,对INT_DIS寄存器的对应位写1就可以禁止该位对应的IO产生中断。所以本例中初始化时,理论上需要对INT_DIS寄存器进行操作。设置MIO7对应的中断控制位不打开。
Data = (1<<7);
Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_INTDIS_OFFSET, Data);

#include "stdio.h"
#include "xparameters.h"
#include "xil_io.h"
#include "xgpiops.h"
#include "sleep.h"

int main(void)
{

        u32 reg_val = 0;
        u32 Data = 0;

                //设置方向和输出使能
                //OUTEN、DIRM寄存器

        //设置IO方向,bit7的方向为输出
        reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DIRM_OFFSET);
        Data = reg_val | (1<<7);
        Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DIRM_OFFSET ,  Data);

        //设置输出使能,bit7输出使能
        reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_OUTEN_OFFSET);
        Data = reg_val | (1<<7);
        Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_OUTEN_OFFSET, Data);

                 //设置方向和输出使能
                //OUTEN、DIRM寄存器

        由于是点亮LED,属于输出型GPIO,因此,根据GPIO的结构图知道,需要使output enable信号为高电平,以使能IO Pin上的三态缓冲器输出。

        而output enable为1的条件则是OUTENDIRM两个寄存器对应的位都为1
        由于这两个寄存器均是32位同时写入型,所以为了不干扰寄存器中其他位的值,

需要采用read-modify-write的操作顺序,也就是先读出,再修改,最后再写回。

        while(1)
        {

                //MASK_DATA寄存器
            //设置bit7输出1
            Data = ((~(1<<7)) << 16) | (1<<7);
            Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DATA_LSW_OFFSET,  Data);
            usleep(1000000);//延时1000000us

            //设置bit7输出0
            Data = ((~(1<<7)) << 16) & (~(1<<7));
            Xil_Out32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DATA_LSW_OFFSET,  Data);
            sleep(1);//延时1000000us
        }
        
        
        return 0;
}

                  //MASK_DATA寄存器

        写MASK_DATA寄存器时需要注意,对于每一个GPIO Bank,由MASK_DATA_LSWMASK_DATA_MSW两个寄存器组成,其中MASK_DATA_LSW控制该组GPIO中低16位的状态,MASK_DATA_MSW控制该组GPIO中高16位的状态。
        MASK_DATA的高16位中,哪些位为0,这些位对应的数据寄存器的值才允许被更新,更新的值由MASK_DATA寄存器的低16位来指定。

① bsp(board  support package)板级支持包

        用户编程时,可以使用该支持包中提供的驱动和函数,来避免自己编写应用函数和基于寄存器读写的驱动。

        由于这些驱动程序中加了很多安全判断和兼容操作,所以,在对程序尺寸和运行效率要求不高的场合,推荐使用BSP提供的驱动和函数,而在对性能和程序尺寸有要求的场合,推荐自己编写基于寄存器读写的驱动。

        //对与本摸鱼怪来说,这一点后面需要的话,再肥来恶补知识叭~

② 如何实现对指定地址的读写操作

使用指针

例如对地址为0x00000020的寄存器进行读写,就可以使用下面的形式:

        读寄存器:return (volatile u8 ) 0x00000020;

        写寄存器:(volatile u8 ) 0x00000020 = 0x12;

使用IO读写函数   xil_io.h

Xil_In8(addr);

Xil_In16(addr);

Xil_In32(addr);

Xil_In64(addr);

Xil_Out8 (addr, data);

Xil_Out16(addr, data);

Xil_Out32(addr, data);

Xil_Out64(addr, data);

这些函数就是对指针操作的封装

③ 如何知道各个外设的硬件信息(寄存器地址,位功能)

查看datasheet

在UG585的附录B中,有所有外设的每个寄存器的地址和功能描述。

reg_val = Xil_In32(XPAR_PS7_GPIO_0_BASEADDR + XGPIOPS_DIRM_OFFSET);

XPAR_PS7_GPIO_0_BASEADDR 为基地址

XGPIOPS_DIRM_OFFSET  为偏移地址

使用BSP提供的驱动和硬件信息文件

在bsp工程中,Xilinx为每一个硬件功能都提供了描述其寄存器地址和位功能的.h文件:

这类文件字母x开头,然后紧跟外设功能名,最后以_hw结尾。

例如,对于GPIO,提供的该文件名为xgpiops_hw.h,

          对于串口(uart),提供的该文件名为xuartps_hw.h,

          对于SD/MMC外设控制器,提供的该文件名为xsdps_hw.h。

需要注意的是,SDK在生成BSP时,会仅针对系统中配置使能了的硬件生成硬件信息文件,对于没有配置使能的硬件,则可能不会生成硬件信息文件,例如我们开发流程课程中,因为没有使能SD/MMC外设和UART外设,所以在SDK中生成的LED_bsp下就找不到刚刚说的xsdps_hw.h和xuartps_hw.h。

④如何实现程序中的延时

对精度要求较高的延时,可以使用BSP中提供的基于CPU心跳定时器的定时/延时函数,例如

微秒单位延迟usleep(unsigned long useconds)

秒单位延迟sleep(unsigned int seconds)

⑤使用跨平台可移植的数据类型

include “stdint.h”

uint8_t us8_type;

uint16_t us16_type;

uint32_t us32_type;

uint64_t us64_type;

int8_t s8_type;

int16_t s16_type;

int32_t s32_type;

int64_t s64_type;

3.  使用硬件库进行编程

小梅哥视频链接:

08_基于SDK硬件驱动库的编程方法_哔哩哔哩_bilibili

对应的课程笔记:【zynq课程笔记】【裸机】【第8课 】【使用SDK硬件驱动库】 - ACZ702开发板 - 芯路恒电子技术论坛 - Powered by Discuz! (corecourse.cn)

#include "xgpiops.h"

#include "unistd.h"


XGpioPs Gpio;

XGpioPs_Config *ConfigPtr;


int main(void)

{

    ConfigPtr =  XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);

    XGpioPs_CfgInitialize(&Gpio,  ConfigPtr, ConfigPtr->BaseAddr);


    XGpioPs_SetDirectionPin(&Gpio,  7, 1);

    XGpioPs_SetOutputEnablePin(&Gpio,  7, 1);


    while(1)

    {

       //设置bit7输出1

       XGpioPs_WritePin(&Gpio,  7, 0x1);

       usleep(500000);


       //设置bit7输出0

       XGpioPs_WritePin(&Gpio,  7, 0x0);

       usleep(500000);

    }

    return 0;

}

XGpioPs_LookupConfig

  

寻找指定GPIO设备的配置信息

XGpioPs_CfgInitialize

对GPIO的驱动程序进行初始化

XGpioPs_SetDirectionPin

设置指定Pin的方向

XGpioPs_SetOutputEnablePin

设置指定Pin的输出使能

XGpioPs_WritePin

写/更新指定管脚的值/状态

4.调试

小梅哥视频:

09_Zynq SoC ARM裸机程序调试方法_哔哩哔哩_bilibili

对应课程笔记:【zynq课程笔记】【裸机】【第9课 】【裸机程序调试方法】 - ACZ702开发板 - 芯路恒电子技术论坛 - Powered by Discuz! (corecourse.cn)

5.  小作业

①GPIO_MIO  PS按键控制PS_LED闪烁

#include "COMMON.h"
#include "sleep.h"

int main(void)
{
    u8 State_PS_KEY; //存放按键(MIO7)的电平状态,0 为低电平,1 为高电平
    PS_GPIO_Init(); //初始化 PS 端 MIO 和 EMIO

    //设置 PS_LED(MIO7)为输出并且初始为低电平
    PS_GPIO_SetMode(PS_LED, OUTPUT, 0);
    PS_GPIO_SetMode(PS_KEY, INPUT, 0); //设置 PS_KEY(MIO47)方向为输入

    while(1)
    {

        //读取 PS_KEY 的电平值并存储到 State_PS_KEY 变量里
      //  State_PS_KEY = PS_GPIO_GetPort(PS_KEY);

        while(!PS_GPIO_GetPort(PS_KEY))
        {

        //将 State 变量的值取非赋予 PS_LED 来输出
        PS_GPIO_SetPort(PS_LED,1);
        usleep(500000);
        PS_GPIO_SetPort(PS_LED,0);
        usleep(500000);
        }
        PS_GPIO_SetPort(PS_LED,0);
    }
    return 0;
}

 while(!PS_GPIO_GetPort(PS_KEY))

嘎嘎~这个是调试出来的小问题:

    while(State_PS_KEY )
        {

        //将 State 变量的值取非赋予 PS_LED 来输出
        PS_GPIO_SetPort(PS_LED,1);
        usleep(500000);
        PS_GPIO_SetPort(PS_LED,0);
        usleep(500000);

          State_PS_KEY = PS_GPIO_GetPort(PS_KEY);
        }

这个小问题,自己调试一下就可以发现啦~

好久没写C,还是要好好熟练一下~

或者是:

#include "xgpiops.h"
#include "unistd.h"

XGpioPs Gpio;
XGpioPs_Config *ConfigPtr;

int main(void)
{
    ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
    XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);

    //设置MIO7为输出
    XGpioPs_SetDirectionPin(&Gpio, 7, 1);
    XGpioPs_SetOutputEnablePin(&Gpio, 7, 1);

    //设置MIO47为输入
    XGpioPs_SetDirectionPin(&Gpio, 47, 0);
    XGpioPs_SetOutputEnablePin(&Gpio, 47, 0);

    while(1)
    {
        while(!XGpioPs_ReadPin(&Gpio, 47))
        {
            //设置bit7输出1
            XGpioPs_WritePin(&Gpio, 7, 0x1);
            usleep(500000);

            //设置bit7输出0
            XGpioPs_WritePin(&Gpio, 7, 0x0);
            usleep(500000);
        }

        //设置bit7输出0
        XGpioPs_WritePin(&Gpio, 7, 0x0);
    }

    return 0;
}
 

②GPIO_EMIO  PL按键控制PS_LED、PL_LED交替闪烁

#include "xgpiops.h"
#include "unistd.h"

XGpioPs Gpio;
XGpioPs_Config *ConfigPtr;

int main(void)
{

    ConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
    XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);


    /*设置MIO7为输出*/
    XGpioPs_SetDirectionPin(&Gpio,  7, 1);
    XGpioPs_SetOutputEnablePin(&Gpio,  7, 1);


    /*设置EMIO0为输出,MIO有54个,EMIO0=54+0=54*/
    XGpioPs_SetDirectionPin(&Gpio, 54, 1);
    XGpioPs_SetOutputEnablePin(&Gpio, 54, 1);

    /*设置EMIO1为输入*/
    XGpioPs_SetDirectionPin(&Gpio, 55, 0);
    XGpioPs_SetOutputEnablePin(&Gpio, 55, 0);

    while(1)
    {
        while(!XGpioPs_ReadPin(&Gpio, 55))
        {
            //设置bit54输出1
            XGpioPs_WritePin(&Gpio, 54, 0x1);
            XGpioPs_WritePin(&Gpio, 7, 0x0);
            usleep(500000);

            //设置bit54输出0
            XGpioPs_WritePin(&Gpio, 54, 0x0);
            XGpioPs_WritePin(&Gpio, 7, 0x1);
            usleep(500000);
        }

        //设置bit54输出0
        XGpioPs_WritePin(&Gpio, 54, 0x0);
        XGpioPs_WritePin(&Gpio, 7, 0x0);
    }

    return 0;
}
 

//啦啦啦,摸鱼结束~

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

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

相关文章

高并发ping多台主机IP

简介 社区或者是大型公司往往有成千上万或者几百台设备&#xff0c;保持设备始终在线对网络运维人员来说至关重要&#xff0c;然而一个一个登录检查&#xff0c;或者一个一个ping并不明智&#xff0c;累人且效率极低&#xff0c;并出错率高。花钱买检测服务当我没说。 shell编…

Frida 环境配置

目录 一、配置 JDK 和 android 环境 二、连接设备 三、配置 Frida 1、frida-server下载 2、配置客户端 3、验证 因为要学习手机端的自动化&#xff0c;所以来学习 Frida 一、配置 JDK 和 android 环境 链接&#xff1a;配置 JDK 和 Android SDK-CSDN博客 二、连接设备…

Vue3【十一】08使用toRefs和toRef

08使用toRefs和toRef toRefs()函数将person对象中的name和age属性转换为响应式引用&#xff0c;并返回一个对象&#xff0c;对象中的name和age属性都是响应式引用&#xff0c;具有响应式功能。 toRef()函数将person对象中的name属性转换为响应式引用&#xff0c;并返回一个响应…

【lesson1】第三方库(jsoncpp,bundle, httplib)的介绍和使用

文章目录 jsoncpp库json 认识jsoncpp 认识jsoncpp 实现序列化jsoncpp 实现反序列化 bundle库bundle库实现文件压缩bundle库实现文件解压缩 httplib 库httplib 库搭建简单服务器httplib库搭建简单客户端 jsoncpp库 json 认识 json 是一种数据交换格式&#xff0c;采用完全独立…

西门子step7脉冲方波

西门子300/400PLC程序可以使用系统时钟脉冲来完成一些定时任务&#xff0c;节省自己写Timer定时器。 定时器字节位定义 默认定义的MB1&#xff0c;则M1.5是1秒定时脉冲方波。 案例 快闪&#xff0c;慢闪。 报警器一闪一闪用。 1分钟计时及1分钟一个脉冲 30分钟计时及30分…

OpenHarmony napi 编译 .so 并打包成 .har

一、前言 最近在搞公司标准产品适配OpenHarmony 平台&#xff0c; 按照行业上的常用方法&#xff0c;在Android 是将底层代码用c 封装成 xxx.so &#xff0c;然后将其他一部分打包成 xxx.jar。 因此&#xff0c;在OpenHarmony 平台也是打算按照这个模式。正所谓&#xff0c;好…

10 设备树

掌握设备树是 Linux 驱动开发人员必备的技能! 1、什么是设备树 新版本 Linux 中,ARM 相关的驱动全部采用了设备树。Linux-4.1.15 支持设备树。我们了解一下设备树的起源、重点学习一下设备树语法。 设备树:Device Tree,就是“设备”和“树”,描述设备树的文件叫做 DTS(…

[数据集][图像分类]黑色素瘤分类数据集10015张7类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;10015 分类类别数&#xff1a;7 类别名称:[“0”,“1”,“2”,“3”,“4”,…

【LeetCode:312. 戳气球+ 动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【JMeter接口测试工具】第一节.JMeter简介和安装【入门篇】

文章目录 前言一、JMeter简介 1.1 JMeter基本介绍 1.2 JMeter优缺点二、JMeter安装 2.1 JMeter安装步骤 2.2 JMeter环境配置三、项目介绍 3.1 项目简介 3.2 API接口清单总结 前言 一、JMeter简介 1.1 JMeter基本介绍 JMeter 是 Apache 组织使用…

30分钟吃掉 Pytorch 转 onnx

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

论文浅尝 | THINK-ON-GRAPH:基于知识图谱的深层次且可靠的大语言模型推理方法...

笔记整理&#xff1a;刘佳俊&#xff0c;东南大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/pdf/2307.07697.pdf 1. 动机 本文是IDEA研究院的工作&#xff0c;这篇工作将知识图谱的和大语言模型推理进行了结合&#xff0c;在每一步图推理中利用大…

Nvidia/算能 +FPGA+AI大算力边缘计算盒子:电力巡检智能机器人

聚焦数字经济与双碳经济赛道&#xff0c;专注于提供集中式新能源场站与分布式综合能源数智化整体解决方案&#xff0c;坚持以场站数字化、综合能源数字化双轮驱动发展。依靠专业化人才队伍与丰富的实证基地研究经验&#xff0c;打造成熟、先进的数智新能源研发平台。 在集中式新…

【Git】远程操作 -- 详解

一、理解分布式版本控制系统 我们目前所说的所有内容&#xff08;工作区、暂存区、版本库等等&#xff09;都是在本地&#xff0c;也就是在我们的笔记本或者计算机上。而我们的 Git 其实是分布式版本控制系统。 上面这段话是什么意思呢&#xff1f; 可以简单理解为&#xff1…

模型 SCAMPER创新法则

说明&#xff1a;系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。激发创新的七步思维法。 1 SCAMPER创新法则的应用 1.1 SCAMPER应用之改进自行车设计 一家自行车制造商希望改进其自行车设计&#xff0c;以吸引更多的消费者并提高市场份额。他们决…

【小白专用24.6.8】C# 异步任务Task和异步方法async/await详解

一、什么是异步 同步和异步主要用于修饰方法。当一个方法被调用时&#xff0c;调用者需要等待该方法执行完毕并返回才能继续执行&#xff0c;我们称这个方法是同步方法&#xff1b;当一个方法被调用时立即返回&#xff0c;并获取一个线程执行该方法内部的业务&#xff0c;调用…

最值,反转数组——跟之前的差不多

文章目录 数组最值感悟改进 反转数组问题 代码改进 数组最值 package com.zhang; /*求数组最大最小值*/ public class test_arr1 {public static void main(String[] args) {int[] arr {10,66,42,8,999,1};max(arr);min(arr);}public static int max(int[] arr){int max arr…

【云原生_K8S系列】Kubernetes 控制器之 Deployment

在 Kubernetes 中&#xff0c;Deployment 是一种高级控制器&#xff0c;负责管理应用的部署和生命周期。它提供了一种声明性的方式来定义应用的期望状态&#xff0c;并确保实际状态与期望状态保持一致。Deployment 可以自动处理应用的滚动更新、扩展和回滚等任务&#xff0c;是…

GPU风扇不旋转:为什么会发生这种情况以及如何修复

GPU在处理数百万像素时往往会发热,因此冷却风扇静音可能会令人担忧,这是可以理解的!如果你注意到你的GPU风扇没有旋转,下面是如何评估是否存在真正的问题,以及如何解决问题。 风扇停止旋转可能是一个功能,而不是一个Bug 如果GPU没有用于密集任务或没有达到高温,则可以…

Java 环境配置 -- Java 语言的安装、配置、编译与运行

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 002 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…