ZYNQ嵌入式学习(5)

UART简介

不需要了解时序。
UART是全双工异步收发的,没有时钟。
UART的操作通过配置和模式寄存器控制。
UART由独立的接受和发送路径构成。每个路径包含深度为64字节的FIFO。FIFO中断状态为支持轮询或中断方式。
轮询方式:不停地读取寄存器看有没有数据。
中断方式:只有当接收到串口数据后才打断主进程来接收数据。
数据位宽:6/7/8bit
停止位:1/1.5/2bit


发送FIFO

CPU通过APB接口将数据写入发送FIFO,直到发送模块(Transmitter,执行并转串)将数据从FIFO中读出并送到移位寄存器。CPU通过操纵TxFIFO寄存器来写数据。
写入数据后,TxFIFO的空标志被清零,发送模块检测到非空后,开始从TxFIFO中读出数据,并转为串行。

接收FIFO

接收FIFO存储来源于接收模块(Receiver,执行串转并)的数据,写入RxFIFO。CPU通过APB接口读取RxFIFO寄存器。
阈值触发:当RxFIFO接收到设定的阈值位数的数据后,阈值触发标志位变为1。可用于产生中断。

模式切换

寄存器操作

中断和状态寄存器

有两个状态寄存器:

  • 中断状态寄存器可以被读取状态和产生中断。(sticky)
  • 状态寄存器仅能读取状态。(dynamic)
    中断状态寄存器和掩码寄存器(只读)按位与。仅有都为1的位才能产生中断,送入中断控制器。

    通过中断使能寄存器和中断除能寄存器来控制中断掩码寄存器。

    收发FIFO寄存器的几种中断:空、满、触发阈值、接近满、溢出。

发送数据

轮询

  1. 检查TxFIFO是否为空
  2. 向TxFIFO中写数(64B)
  3. 等待TxFIFO空后再次写入

中断

  1. 除能TxFIFO空中断
  2. 向TxFIFO中写数(64B)
  3. 检查TxFIFO中还有没有空间可以写数
  4. 重复2、3
  5. 使能中断
  6. 等待TxFIFO为空后返回1

接收数据

轮询

  1. 等待RxFIFO中数据达到阈值或接收超时
  2. 从RxFIFO中读数据
  3. 重复2直到RxFIFO空
  4. 若接收超时,清除超时位

中断

  1. 使能中断
  2. 等待RxFIFO中数据达到阈值或接收超时
  3. 从RxFIFO中读数据
  4. 重复2、3
  5. 清除中断

读写数据操纵的都是TX_RX_FIFO0寄存器,其中包含收发两个FIFO。

实验:串口中断数据环回

/******************************************************************************
*
* Copyright (C) 2009 - 2014 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/

/*
 * helloworld.c: simple test application
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */
/*
 * 20230307运行成功!
 */
#include <stdio.h>
//#include "platform.h"
#include "xil_printf.h"
#include "xuartps.h"
#include "xparameters.h"
#include "xscugic.h"
#include "xuartps_hw.h"

#define UART_DEVICE_ID		XPAR_XUARTPS_0_DEVICE_ID
#define UART_INT_IRQ_ID		XPAR_XUARTPS_0_INTR
#define INTC				XScuGic
#define INTC_DEVICE_ID		XPAR_SCUGIC_0_DEVICE_ID
//#define TEST_BUFFER_SIZE	100

XUartPs UartPs	;
XUartPs_Config *Config;
INTC InterruptController;	// 中断控制器驱动实例
//u8 RecvBuffer[TEST_BUFFER_SIZE];

void Handler();
void uart_init();
void uart_intr_handler();
void uart_intr_init(INTC *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId);
int SetupInterruptSystem(INTC *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId);
int main()
{
	// 串口初始化
	uart_init();
	xil_printf("Uart initializes successfully!");
	// 串口中断初始化(包含:1.对Uart的中断进行配置;2.对PS的中断控制器(Gic)进行配置)
	uart_intr_init(&InterruptController, &UartPs, UART_INT_IRQ_ID);

	while(1); // 让程序停在这个位置,用来检测中断,只有cpu收到中断指令,才会跳出while(1),进入中断服务子程序
    return 0;
}


// 串口初始化函数
void uart_init(){
	Config = XUartPs_LookupConfig(UART_DEVICE_ID);
	XUartPs_CfgInitialize(&UartPs, Config, Config->BaseAddress);
	// 设置串口工作模式
	XUartPs_SetOperMode(&UartPs, XUARTPS_OPER_MODE_NORMAL);
	// 设置串口波特率(默认就是115200)
	XUartPs_SetBaudRate(&UartPs, 115200);
	// 设置接收FIFO中断事件触发阈值,这里设置为1Byte,即每接收到1字节的数据就要产生一次中断,在中断函数中处理此中断
	XUartPs_SetFifoThreshold(&UartPs, 1);
}

// 串口中断初始化函数
void uart_intr_init(INTC *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId){
	/*
	 * 以下为中断控制器Gic配置
	 */
	XScuGic_Config *IntcConfig;
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);
	// 关联中断ID和中断处理函数
	XScuGic_Connect(IntcInstancePtr, UartIntrId, (Xil_ExceptionHandler) uart_intr_handler, (void *) UartInstancePtr);
	// 设置并打开中断异常处理功能
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler,IntcInstancePtr);
	Xil_ExceptionEnable();

	/*
	 * 以下为Uart中断配置
	 */
	// 设置UART中断触发方式,即哪些状态位能够产生中断
	u32 IntrMask;
	IntrMask = XUARTPS_IXR_RXOVR; 	// 接收fifo触发阈值中断位
	XUartPs_SetInterruptMask(UartInstancePtr, IntrMask);

	/*
	 * 使能UART中断
	 */
	XScuGic_Enable(IntcInstancePtr, UartIntrId);
}

// 中断处理函数
void uart_intr_handler(XUartPs *UartInstancePtr){
	// 读取中断状态寄存器
	u32 rec_data = 0;
	u32 IsrStatus;
	IsrStatus = XUartPs_ReadReg(UartInstancePtr->Config.BaseAddress,
				   XUARTPS_IMR_OFFSET);		// 获取中断掩码寄存器值,此处应该只有最低位为1,对应接收触发阈值中断
	IsrStatus &= XUartPs_ReadReg(UartInstancePtr->Config.BaseAddress,
				   XUARTPS_ISR_OFFSET);		// 获取对应的中断状态寄存器的值
	// 若满足中断掩码寄存器和中断状态寄存器的与为1,再和接收fifo触发阈值位相与,为高电平,则确实为所需类型中断
	/*
	 * 接收处理
	 */
	if(IsrStatus & XUARTPS_IXR_RXOVR) {
		// 读取出Rxfifo中接收到的数据(仅一个字节)
		//	rec_data = XUartPs_Recv(UartInstancePtr, RecvBuffer, TEST_BUFFER_SIZE);
		rec_data = XUartPs_RecvByte(UartInstancePtr->Config.BaseAddress);
		// 清除中断状态寄存器的接收fifo触发阈值位
		XUartPs_WriteReg(UartInstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
				XUARTPS_IXR_RXOVR);
	}
	/*
	 * 发送处理
	 */
	XUartPs_SendByte(UartInstancePtr->Config.BaseAddress, rec_data);

}



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值