S02_CH09_UART串口中断实验
S02_CH09_UART串口中断实验
本章的UART中断将在之前PL_PS中断和定时器中断上推导出来,因此本章有点难度,如果前两章还不是很熟悉的话,需要返回到前面两章把这两章的内容再次消化一下,再来学习本章的内容。本章的硬件工程可以直接使用定时器中断的硬件工程,因此此次试验就直接到SDK软件部分。
9.1 加载到SDK
Step1:打开定时器中断的工程。
Step2:导出硬件。
Step3:新建一个空SDK工程,并添加一个main.c的文件。
Step4:在main.c文件中添加以下程序,按Ctrl+S保存后自动开始编译。
/* * main.c * * Created on: 2016年6月26日 * Author: Administrator */ #include <stdio.h> #include "xadcps.h" #include "xil_types.h" #include "Xscugic.h" #include "Xil_exception.h" #include "xuartps.h" //timer info #define UART_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #define UART_IRPT_INTR XPAR_XUARTPS_1_INTR static XScuGic Intc; //GIC static XUartPs Uart;//uart static void UartIntrHandler(void *CallBackRef) { XUartPs *InstancePtr = (XUartPs *) CallBackRef; u32 IsrStatus; u32 ReceivedCount=0; u32 CsrRegister; /* * Read the interrupt ID register to determine which * interrupt is active */ IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_IMR_OFFSET);//e0001000+10=regaddr=e0001010 IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET);//e0001000+14=regaddr=e0001014 /* Dispatch an appropriate handler. */ if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY | (u32)XUARTPS_IXR_RXFULL)) != (u32)0) { CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,//判断FIFO触发标准位 XUARTPS_SR_OFFSET);//e0001000+2c=regaddr=e000102c while((CsrRegister & XUARTPS_SR_RXEMPTY)== (u32)0){//读取FIFO中所有数据 //InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] =//每次循环读取1byte ; XUartPs_WriteReg(InstancePtr->Config.BaseAddress,//每次循环发送读取到的数据 XUARTPS_FIFO_OFFSET, XUartPs_ReadReg(InstancePtr->Config. BaseAddress, XUARTPS_FIFO_OFFSET)); ReceivedCount++;//计数 CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_SR_OFFSET); } } printf("this time ReceivedCount=%d\r\n",ReceivedCount); XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, IsrStatus); } void SetupInterruptSystem(XScuGic *GicInstancePtr, XUartPs *UartInstancePtr, u16 UartIntrId) { XScuGic_Config *IntcConfig; //GIC config Xil_ExceptionInit(); //initialise the GIC IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); XScuGic_CfgInitialize(GicInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler,//connect to the hardware GicInstancePtr); Xil_ExceptionEnable(); XScuGic_Connect(GicInstancePtr, UartIntrId, (Xil_InterruptHandler)UartIntrHandler,//set up the timer interrupt (void *)UartInstancePtr); XScuGic_Enable(GicInstancePtr, UartIntrId);//enable the interrupt for the Timer at GIC XUartPs_SetInterruptMask(UartInstancePtr, XUARTPS_IXR_RXOVR/* | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TNFUL*/ ); // XUartPs_EnableUart(UartInstancePtr);//enable interrupt on the timer Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); //Enable interrupts in the Processor. } int main() { XUartPs_Config *UartConfigPtr; //timer config // printf("------------START-------------\n"); UartConfigPtr = XUartPs_LookupConfig(UART_DEVICE_ID); XUartPs_CfgInitialize(&Uart,UartConfigPtr,UartConfigPtr->BaseAddress); //set up the interrupts SetupInterruptSystem(&Intc,&Uart,UART_IRPT_INTR); while(1); return 0; } |
Step4:右击工程,选择Debug as ->Debug configuration。
Step5:选中system Debugger,双击创建一个系统调试。
Step6:设置系统调试。
打开系统自带的窗口调试助手,点击运行按钮开始运行程序。
系统运行结果如下图所示:
9.2 程序分析
本章的程序与之前两章的程序都大同小异,一些函数都在我们之前两章中看到和介绍过。
首先我们先介绍下面三个宏定义。
第一个是我们的UART的设备ID,第二个是我们中断的设备ID,第三个是UART的中断号。
把鼠标停留在UART的中断号上,按下F3跟踪它,经过两次跟踪后,得到UART的中断号如下图所示:
我们可以在ug585中查看一下中断号82是否是串口中断。
可以看到,确实是串口中断,高电平触发。
再来看看main函数中的内容。首先依然是通过查找配置程序来获取串口的硬件配置。我们跟踪这个程序,看看他获取的配置是什么。
这个程序还是从一个配置表数组中查找的配置文件,继续往下剥离,看一看这个数组中的内容。
可以看到,这个数组里存放的是UART的设备ID,UART的基地址,时钟频率和一个不知道什么作用的对象。后两个参数是我们没用到的,因此就略过了。前两个都是我们在硬件工程中添加了中断后,系统自动生成的。
接下来还是一个熟悉的函数,对UART进行了初始化。可以看到这个函数的第一个参数指向了定义的UART指针,我们就跟踪一下这个指针。
我们发现它指向了一个结构体,那么我们继续跟踪看看结构体中内容。
这个结构体中的内容比较多,第一个对象是我们UART硬件的一些配置,它指向的是一个结构体。那么就来看看这个结构体吧。
可以看到,这些就是刚才我们查找配置程序获取到的硬件参数。
回到XUartPs结构体的分析。第二个对象是输入时钟频率,第三个是设备是否初始化并准备好,第四个是波特率,第五个是两个buffer,一个发送的一个接收的。挑选一个参看一下。
接着第七个是一个Hander,第八个是一个回掉函数,最后一个是platform具体是什么意思不得而知。
回到初始化程序。我们来看看这个函数与之前有什么不同了。
一开始是一长串的初始化,如下图所示:
接下来的这个函数是一个用于判断芯片类型的函数。
接下来,程序将Instance(也就是我们的UART硬件)的标志设置为XIL_COMPONENT_IS_READY,表明此时UART已经可以使用了。
接下来,程序将UART的波特率设置为了115200。
接下来的这一句是读取UART的模式寄存器。
我们可以来看看读取的什么内容,把鼠标停放在这个函数的上方,看到函数显示出了这个函数的原函数。
与我们定时器实验中讲到的读写寄存器的函数差不多,第一个参数是UART的基地址,这在我们一开始的分析中就提到过,我们反回去看看UART的基地址是多少。
可以知道,此处的基地址为0xE000100,直接计算:E0001000+0x0004= E0001004。打开ug585查看下这个寄存器的介绍。
可以看到,这是一个UART的模式寄存器,通过这个寄存器可以设置串口的数据位宽,有无停止位和奇偶校验位等信息。
再来看看下一句程序。这句是对刚才读出的寄存器的一个运算。
首先得到方框中这三个参数的值。这里我们已经查看程序得知这三个值分别为:6,A0,38。然后进行运算:ModeRegister=E0001004 & (~(6|A0|38))=E0001004 & 11 =0。
接下来的这一句也是一个运算,不多讲,直接运算。ModeRegister=0|(0|0|20)=20。
这段程序就是一个写寄存器的功能了。看看这个函数的原函数。
由此得出,这个函数读写的地址为刚才模式寄存器的地址,写入的数据就是运算得出的20h。参照刚才ug585里的模式寄存器说明,显而易见,经过这段程序之后,把UART设置为了8个数据位,1个停止位和无奇偶校验位的模式。
接下来的还有3个写寄存器的程序,分析方法与刚才的一致。这里就只给出它们实现的功能。分别是:设置UART的RX FIFO在8bit处触发、设置UART的超时为1(4个字符时间)、禁止所有中断轮询模式为默认的样式。
回到main函数的分析当中,接下来的函数实现的是建立起中断的功能,这个函数在我们上一章也进行过详细的讲解。这里我们关注一下下面这个函数。
当我们运行XScuGic_Connect这个函数的时候,实际运行的就是这个回调函数。这个函数也是真正实现UART发送与接收功能的函数。可以看到这个程序是通过读写寄存器的方式来工作的,我们可以用刚才我们讲到的方法对其进行分析,在程序中,我们也给出了分析的过程。大家可以认真的去看一看。
9.3 本章小结
本章主要详细的分析了UART中断的实现过程,通过本章,我们重点需要掌握的是怎样分析一个问题的方法。通过这几张中断部分的讲解,我们应该做到对中断部分得心应手的程度。
S02_CH09_UART串口中断实验的更多相关文章
- 基于ZYNQ 的UART中断实验之串口写数据到DDR3中
1.参考 UG585 网络笔记 2.理论知识 参见上一次实验:基于ZYNQ 的UART中断实验 3.实验目的 练习使用UART的中断实验,并将接收到的数据写入到DDR3中. 4.实验过程 建立工程,设 ...
- STM32F407 串口通信实验 视频第27节 个人笔记
前言 第26节也是串口,笔记链接在此:https://www.cnblogs.com/YuQiao0303/p/10019362.html github地址:https://github.com/Yu ...
- S02_CH08_ ZYNQ 定时器中断实验
S02_CH08_ ZYNQ 定时器中断实验 上一章实现了PS接受来自PL的中断,本章将在ZYNQ的纯PS里实现私有定时器中断.每隔一秒中断一次,在中断函数里计数加1,通过串口打印输出. 8.1中断原 ...
- STM8S和STM8L调试串口中断的注意点
1. STM8L串口中断注意点 在调试PM2.5传感器GP2Y1051的时候,发现在仿真的时候开始能够进行数据的接受,但是如果暂停之后就不能接受数据,其实只是接收了一次完整的数据. 问题程序 解决方法 ...
- Stm32L0串口中断接收使用
最新在做LoRa的项目,使用的是STM32L072和SX1276,需要做一个串口透传模块,刚开始做demo的时候不考虑功耗,所以串口发送和接收直接使用下列函数执行: HAL_UART_Transmit ...
- STM32 串口中断总结
原文:https://blog.csdn.net/weixin_42480952/article/details/82981409 最近在学习使用dma传输方式进行串口通讯,感觉这个很详细,存一下 . ...
- STM32单片机串口中断+DMA使用(含CUBE配置)
最近又要重新用32做点东西,发现一两年没怎么碰的结果就是,曾经熟得不行的东西都变得极度陌生,这种重新学习记忆的过程过于痛苦,果然还是要留下一些记录给之后失忆的自己的. 1.STM32CUBE配置 1. ...
- ARM实验5 —— 按键中断实验
key_int按键中断实验 实验内容: 通过开发板上的按键中断控制led灯进行跑马灯并打印信息. 通过简单事例说明猎户座4412处理器的GIC中断处理的应用,设置key2按键连接的引脚为中断模式,当识 ...
- STM32串口中断实例二
int main(void) { uint8_t a=;//LED高低电压控制 /* System Clocks Configuration */ RCC_Configuration(); //系统时 ...
随机推荐
- Echarts-树状图(源码 含flare.json)
刚刚发现官网实例里边的数据其实在:https://www.echartsjs.com/data/asset/data/flare.json 源码: html: <!DOCTYPE html> ...
- Ubuntu 14.04 下安装redis后运行redis-cli 报出redis Connection refused错误【已解决】
在运行redis-cli运行后爆出错误,看了网上的都没有用例如:改ip,注释bind 127.0.0.1,或者是先运行./redis-server redis.conf,都没有用 只需要: 找到red ...
- CF1217C
CF1217C 题意: 给定一个01串,一个good01串的定义是这个01串所代表的二进制数字刚好等于它的长度,允许前导零,问这个01串当中有几个good子串 解法: 枚举每一段连续的 $ 0 $ , ...
- ORM SQLAlchemy - 建立一个关系 relationship
relationship函数是sqlalchemy对关系之间提供的一种便利的调用方式, backref参数则对关系提供反向引用的声明 1 背景 如没有relationship,我们只能像下面这样调用关 ...
- Dubbo系列(三)dubbo的核心技术--RPC调用
dubbo的核心技术--RPC调用:分为俩部分RPC协议Protocol和方法调用Invoke: 一.RPC协议Protocol(Remote Procedure Call)远程过程调用协议 1.我们 ...
- GitHub排名TOP30的机器学习开源项目/贪心学院
对于机器学习者来说,阅读开源代码并基于代码构建自己的项目,是一个非常有效的学习方法.看看以下这些Github上平均star为3558的开源项目,你错了哪些? 1. FastText:快速文本表示和文本 ...
- pwn学习日记Day16 pwn原理理解
CTF-Pwn入门及栈溢出原理解释 CTF pwn 中最通俗易懂的堆入坑指南 看雪论坛
- linux之i2c子系统维护者源码仓库地址
仓库地址: git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
- k8s管理机密信息(9)
一.启动应用安全信息的保护: Secret介绍: 应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名密码或者秘钥.将这些信息直接保存在容器镜像中显然不妥,Kubernetes 提供的解决方案是 ...
- [C++]Yellow Cards - GYM - 102348A(Practice *) - CodeForces
1 Problem Description Problem The final match of the Berland Football Cup has been held recently. Th ...