通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。
百度百科原理介绍:https://baike.baidu.com/item/UART/4429746?fr=aladdin
1.初始化函数:XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);
首先是对结构变量的初始化,基地址,ID ,频率,波特率的设置
XUartPs_SetBaudRate(InstancePtr, BaudRate); //欧特吕设置函数
接下来设置数据模式寄存器来设置工作模式:数据位数、有无停止位,有无奇偶校验、时钟有无分频等。
ModeRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_MR_OFFSET);
//
/* Mask off what's already there */
ModeRegister &= (~((u32)XUARTPS_MR_CHARLEN_MASK |
(u32)XUARTPS_MR_STOPMODE_MASK |
(u32)XUARTPS_MR_PARITY_MASK));
//
/* Set the register value to the desired data format */
ModeRegister |= ((u32)XUARTPS_MR_CHARLEN_8_BIT |
(u32)XUARTPS_MR_STOPMODE_1_BIT |
(u32)XUARTPS_MR_PARITY_NONE);
//
/* Write the mode register out */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_MR_OFFSET,
ModeRegister);
/* Set the RX FIFO trigger at 8 data bytes. */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
XUARTPS_RXWM_OFFSET, 0x08U); //设置接收8bit触发
/* Set the RX timeout to 1, which will be 4 character time */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
XUARTPS_RXTOUT_OFFSET, 0x01U);
//设置接收超时,意思就是经过多少个周期后,没有接收数据,就停止接收,4*设置的值 个周期
/* Disable all interrupts, polled mode is the default */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_IDR_OFFSET,
XUARTPS_IXR_MASK);
2.XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)UartPs_Intr_Handler, UartInstPtr);
//设置中断触发时的回调函数,即中断触发处理函数
3.XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask)
//设置中断使能触发器,主要涉及两个寄存器的写
/* Write the mask to the IER Register */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
XUARTPS_IER_OFFSET, TempMask);
/* Write the inverse of the Mask to the IDR register */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
XUARTPS_IDR_OFFSET, (~TempMask));
4. XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout)
* This function sets the Receive Timeout of the UART.
*
* @param InstancePtr is a pointer to the XUartPs instance.
* @param RecvTimeout setting allows the UART to detect an idle connection
* on the reciever data line.
* Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the
* timeout function.
5.UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData)
//中断触发处理函数,首先判断是哪一种中断产生,不同触发方式,采取不同的处理方法
(1)/* All of the data has been sent */
(2)/* All of the data has been received */
(3) /*
* Data was received, but not the expected number of bytes, a
* timeout just indicates the data stopped for 8 character times
*/
(4) /*
* Data was received with an error, keep the data but determine
* what kind of errors occurred
*/
(5)/*
* Data was received with an parity or frame or break error, keep the data
* but determine what kind of errors occurred. Specific to Zynq Ultrascale+
* MP.
*/
(6)/*
* Data was received with an overrun error, keep the data but determine
* what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
*/
中断函数必要的几个函数:
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
XScuGic Intc; //GIC
void Setup_Intr_Exception(XScuGic * IntcInstancePtr)
{
/* Enable interrupts from the hardware */
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)IntcInstancePtr);
Xil_ExceptionEnable();
}
int Init_Intr_System(XScuGic * IntcInstancePtr)
{
int Status;
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
外设中断函数的写法:
1.外设初始化,查找ID,基地址,进行必要的外设参数的初始化。
2.外设中断的初始化:查找中断外设的ID,初始化,三个Xil_Exception函数的编写,允许ARM处理器中断;
3.中断函数的连接,中断ID号,使能中断。
头文件:
/*
* uartps_intr.h
*
* Created on: 2019年5月3日
* Author: Administrator
*/
#ifndef SRC_UARTPS_INTR_H_
#define SRC_UARTPS_INTR_H_
#include "xparameters.h"
#include "xplatform_info.h"
#include "xuartps.h"
#include "xil_exception.h"
#include "xil_printf.h"
#include "xscugic.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID XPAR_XUARTPS_1_INTR
#define TEST_BUFFER_SIZE 10
XUartPs UartPs;//uart
XScuGic Intc; //GIC
static u8 SendBuffer[TEST_BUFFER_SIZE]; /* Buffer for Transmitting Data */
static u8 RecvBuffer[TEST_BUFFER_SIZE]; /* Buffer for Receiving Data */
volatile int TotalReceivedCount;
volatile int TotalSentCount;
int TotalErrorCount;
int Init_UartPsIntr(XUartPs *UartInstPtr,u16 DeviceId);
int UartPs_Setup_IntrSystem(XScuGic *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId);
void UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData);
#endif /* SRC_UARTPS_INTR_H_ */
子函数文件:
/*
* uartps_intr.c
*
* Created on: 2019年05月02日
* www.osrc.cn
* copyright by cz123 msxbo
*/
#include "uartps_intr.h"
int Init_UartPsIntr(XUartPs *UartInstPtr,u16 DeviceId )
{
int Status;
XUartPs_Config *Config;
u32 IntrMask;
if (XGetPlatform_Info() == XPLAT_ZYNQ_ULTRA_MP) {
#ifdef XPAR_XUARTPS_1_DEVICE_ID
DeviceId = XPAR_XUARTPS_1_DEVICE_ID;
#endif
}
Config = XUartPs_LookupConfig(DeviceId);//基地址0xE0001000,时钟100 000 000
if (NULL == Config) {
return XST_FAILURE;
}
Status = XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handlers for the UART that will be called from the
* interrupt context when data has been sent and received, specify
* a pointer to the UART driver instance as the callback reference
* so the handlers are able to access the instance data
*/
XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)UartPs_Intr_Handler, UartInstPtr);
/*
* Enable the interrupt of the UART so interrupts will occur, setup
* a local loopback so data that is sent will be received.
*/
IntrMask =
XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
XUARTPS_IXR_RXOVR;
if (UartInstPtr->Platform == XPLAT_ZYNQ_ULTRA_MP) {
IntrMask |= XUARTPS_IXR_RBRK;
}
XUartPs_SetInterruptMask(UartInstPtr, IntrMask);
XUartPs_SetRecvTimeout(UartInstPtr, 8);
return XST_SUCCESS;
}
void UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
int i = 0;
/* All of the data has been sent */
if (Event == XUARTPS_EVENT_SENT_DATA) {
TotalSentCount = EventData;
}
/* All of the data has been received */
if (Event == XUARTPS_EVENT_RECV_DATA) {
TotalReceivedCount = EventData;
if(TotalReceivedCount == TEST_BUFFER_SIZE) {
for(i=0;iCpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Enable interrupts from the hardware */
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)IntcInstancePtr);
Xil_ExceptionEnable();
/*
* interrupt for the device occurs, the device driver handler
* performs the specific interrupt processing for the device
*/
Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,
(Xil_ExceptionHandler) XUartPs_InterruptHandler,
(void *) UartInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Enable the interrupt for the device */
XScuGic_Enable(IntcInstancePtr, UartIntrId);
return XST_SUCCESS;
}
测试主程序:
#include "uartps_intr.h"
int main(void)
{
Init_UartPsIntr(&UartPs,UART_DEVICE_ID);
UartPs_Setup_IntrSystem(&Intc, &UartPs, UART_INT_IRQ_ID);
//测试函数
XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
while(1);
return 0;
}