C基础与SDK调试方法

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.rhkb.cn/news/342015.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用双升压转换器扩展高转换比设计的功率范围

任何升压转换器设计都会对从输入到输出的电压升高程度存在实际限制。脉宽调制 (PWM) 控制器具有时序限制&#xff0c;限制了场效应晶体管 (FET) 的允许接通和断开时间。时序限制将有效地限制可实现的升压比&#xff0c;尽管这个缺点在使用电感器而不是变压器或耦合电感器作为其…

【Uniapp】uniapp微信小程序定义图片地址全局变量

错误写法&#xff1a; main.js Vue.prototype.$imgUrl 图片地址这么写之后 就发现压根不起作用&#xff1b;获取到的是undefined 正确写法&#xff1a; 返回函数&#xff0c;后面可以拼上OSS图片完整路径 Vue.prototype.$imgUrl (url) > {return ("https://地址…

SparkSql近期使用经验分享

背景 近期在公司使用了SparkSql重构一个由Java开发的ETL程序&#xff0c;因为Java模块不易于修改和部署&#xff0c;而由于SparkSql脚本是由Python开发&#xff0c;便于根据业务需求来开发维护&#xff0c;特别是不需要编译、打包部署。 技术理念 SparkSql是以Sql的形式去开…

植物大战僵尸杂交版2.0.88最新版安装包

游戏简介 游戏中独特的杂交植物更是为游戏增添了不少亮点。这些杂交植物不仅外观独特&#xff0c;而且拥有更强大的能力&#xff0c;能够帮助玩家更好地应对游戏中的挑战。玩家可以通过一定的条件和方式&#xff0c;解锁并培养这些杂交植物&#xff0c;从而不断提升自己的战斗…

【Python】推荐比print更好用的调试方法

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

算法学习笔记(7.6)-贪心算法(霍夫曼编码)

目录 1.什么是霍夫曼树 2.霍夫曼树的构造过程 3.霍夫曼编码 3.1具体的作用-频率统计 ##实战题目 1.什么是霍夫曼树 给定N个权值作为N个叶子结点&#xff0c;构造一棵二叉树&#xff0c;若该树的带权路径长度达到最小&#xff0c;称这样的二叉树为最优二叉树&#xff0c;也…

【JavaEE进阶】——MyBatis操作数据库 (#{}与${} 以及 动态SQL)

目录 &#x1f6a9;#{}和${} &#x1f388;#{} 和 ${}区别 &#x1f388;${}使用场景 &#x1f4dd;排序功能 &#x1f4dd;like 查询 &#x1f6a9;数据库连接池 &#x1f388;数据库连接池使⽤ &#x1f6a9;MySQL开发企业规范 &#x1f6a9;动态sql &#x1f388…

能动嘴就别再手动操作了!国产AI大模型让你轻松搞定一切

国产AI大模型使用入门指南 #大模型# ▶▶▶ 引言 简单来说&#xff0c;大模型拥有超级无敌强大的大脑&#xff0c;无所不知&#xff08;不断吸收互联网上海量信息、文献、图书等等它可以找到的数据进行训练&#xff09;。因此&#xff0c;懂得利用AI生成内容&#xff0c;就如同…

DockerCompose中部署Jenkins(Docker Desktop在windows上数据卷映射)

场景 DockerJenkinsGiteeMaven项目配置jdk、maven、gitee等拉取代码并自动构建以及遇到的那些坑&#xff1a; DockerJenkinsGiteeMaven项目配置jdk、maven、gitee等拉取代码并自动构建以及遇到的那些坑_jenkins的安装以及集成jdkgitmaven 提示警告-CSDN博客 Windows10(家庭版…

MySQL的联合索引及案例分析

1. 联合索引 关于联合索引的详解参考博客【Mysql-----联合索引和最左匹配】&#xff0c;包含讲解 最左匹配 联合索引失效的情况 不遵循最左匹配原则范围查询右边失效原理like索引失效原理 比较关注的点在于&#xff1a; 对A、B、C三个字段创建一个联合索引&#xff08;A, …

数据结构之归并排序算法【图文详解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

FY-SA-20237·8-ZombieFires

Translated from the Scientific American, July/August 2023 issue. Zombie Fires &#xff08;僵尸火灾&#xff09; “Zombie Fires”&#xff08;僵尸火灾&#xff09;是指在地下或地表深处燃烧的火灾&#xff0c;通常在冬季或早春的时候被扑灭&#xff0c;然后在夏季再次…

idea实用快捷键(持续更新...)

文章目录 1、快速输入try/catch/finally2、选中多个光标3、实现接口4、方法参数提示5、查看某个类的子类6、弹出显示查找内容的搜索框 1、快速输入try/catch/finally CtrlAltT 2、选中多个光标 ShiftAlt单机多选 End可以全部到行尾&#xff0c;Home则可以全部回到行首 3、实现接…

Hadoop3:MapReduce源码解读之Mapper阶段的FileInputFormat的切片原理(2)

Job那块的断点代码截图省略&#xff0c;直接进入切片逻辑 参考&#xff1a;Hadoop3&#xff1a;MapReduce源码解读之Mapper阶段的Job任务提交流程&#xff08;1&#xff09; 4、FileInputFormat切片源码解析 切片入口 获取切片 获取切片最大的Size和切片最小的Size 判断文…

可燃气体报警器效检:预防事故,守护家园

在现代化工业生产、居民生活中&#xff0c;可燃气体报警器作为安全预防的重要工具&#xff0c;其准确性和可靠性直接关系到人们的生命财产安全。 因此&#xff0c;对可燃气体报警器进行定期效检&#xff0c;确保其处于最佳工作状态&#xff0c;是保障安全生产的必要措施。 接…

打开C# 大门:Hallo, World!

C# 介绍 C#&#xff08;C Sharp&#xff09;是一种面向对象的编程语言&#xff0c;由微软公司开发。它是 .NET Framework 的一部分&#xff0c;用于构建 Windows 应用程序、Web 应用程序、移动应用程序等。C# 语言的设计目标是简单、现代化、易于学习和使用。在本文中&#xf…

GLM-4已经“低调”开源了

GLM-4-9B 是智谱 AI 推出的最新一代预训练模型 GLM-4 系列中的开源版本。 在语义、数学、推理、代码和知识等多方面的数据集测评中&#xff0c;GLM-4-9B 及其人类偏好对齐的版本 GLM-4-9B-Chat 均表现出较高的性能。 除了能进行多轮对话&#xff0c;GLM-4-9B-Chat 还具备网页浏…

stm32 Systick定时器的配置

从原理上来说&#xff0c;Systick定时器和开发板上的通用定时器没有区别。从功能上来说&#xff0c;Systick定时器主要是用来用来进行延时的&#xff0c;而通用或者高级定时器往往用来进行PWM输出、输入捕获等功能。至于为什么不用通用定时器或者高级定时器来完成延时功能&…

Nginx02-Nginx虚拟主机介绍、日志介绍、Location规则介绍

目录 写在前面NginxNginx处理用户请求流程虚拟主机虚拟主机的分类基于域名的虚拟主机基于端口的虚拟主机基于IP的虚拟主机 Nginx日志错误日志案例 访问日志访问格式变量案例 Location规则案例1案例2Location规则小结 写在前面 这是Nginx第二篇&#xff0c;内容为Nginx处理用户请…

电阻、电容和电感测试仪设计

在现代化生产、学习、实验当中,往往需要对某个元器件的具体参数进行测量,在这之中万用表以其简单易用,功耗低等优点被大多数人所选择使用。然而万用表有一定的局限性,比如:不能够测量电感,而且容量稍大的电容也显得无能为力。所以制作一个简单易用的电抗元器件测量仪是很…