高云FPGA系列教程(8):ARM串口数据接收(中断和轮询方式)

文章目录

    • @[toc]
      • 1. GW1NSR-4C串口外设简介
      • 2. FPGA配置
      • 3. 常用函数
      • 4. 轮询方式接收数据
      • 5. 中断方式接收数据

本文是高云FPGA系列教程的第8篇文章。

本篇文章介绍片上ARM Cortex-M3硬核处理器串口外设的使用,演示轮询方式和中断方式接收串口数据,并进行回环测试,基于TangNano 4K开发板。

参考文档:Gowin_EMPU(GW1NS-4C)软件编程 参考手册

1. GW1NSR-4C串口外设简介

GW1NSR-4C ARM部分共有2个串口外设,都挂载在APB1总线上,最高支持波特率921.6Kbit/s,无奇偶校验位,8位数据位,1位停止位,支持高速测试模式 HSTM(High Speed Test Mode),即每个时钟周期输出1位数据,可以在短时间内传输大量数据。

官方手册上没有描述发送和接收缓存FIFO的深度,所以不确定是否支持缓存。

2. FPGA配置

FPGA部分需要在云源软件中手动使能EMPU串口外设,如下图所示。


不需要其他配置,使用起来非常简单。

3. 常用函数

高云串口驱动函数常用的有以下几个:

//串口初始化,指定波特率和中断使能,高速测试模式等
ErrorStatus UART_Init(UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct)
//获取接收缓存区状态,当接收到数据时,返回SET
FlagStatus UART_GetRxBufferFull(UART_TypeDef* UARTx)
//获取发送缓存区状态
FlagStatus UART_GetTxBufferFull(UART_TypeDef* UARTx)
//发送一个字节
void UART_SendChar(UART_TypeDef* UARTx,char txchar)
//发送字符串
void UART_SendString(UART_TypeDef* pUARTx, char *str)
//接收一个字节,轮询或接收中断时调用,自动
char UART_ReceiveChar(UART_TypeDef* UARTx)
//获取接收中断的状态,当被触发时返回SET
ITStatus UART_GetRxIRQStatus(UART_TypeDef* UARTx)
//获取发送中断的状态
ITStatus UART_GetTxIRQStatus(UART_TypeDef* UARTx)
//清除接收中断
void UART_ClearRxIRQ(UART_TypeDef* UARTx)
//清除发送中断
void UART_ClearTxIRQ(UART_TypeDef* UARTx)

下面来介绍串口接收数据的两种方式:轮询方式和中断方式。

4. 轮询方式接收数据

初始化时不使能接收中断:

void uart0_init(uint32_t BaudRate)
{UART_InitTypeDef UART_InitStruct;UART_InitStruct.UART_Mode.UARTMode_Tx = ENABLE;UART_InitStruct.UART_Mode.UARTMode_Rx = ENABLE;UART_InitStruct.UART_Int.UARTInt_Tx = DISABLE;UART_InitStruct.UART_Int.UARTInt_Rx = DISABLE;UART_InitStruct.UART_Ovr.UARTOvr_Tx = DISABLE;UART_InitStruct.UART_Ovr.UARTOvr_Rx = DISABLE;UART_InitStruct.UART_Hstm = DISABLE;UART_InitStruct.UART_BaudRate = BaudRate;//Baud RateUART_Init(UART0, &UART_InitStruct);
}

主循环中直接把收到的数据通过串口发送出去:

while(1)
{if(UART_GetRxBufferFull(UART0)){cnt_idle = 0;rx = UART_ReceiveChar(UART0);printf("rec data: %c\r\n", rx);}
}

这种简单粗暴的方式,会导致数据丢失,可能是串口接收部分没有FIFO导致:

我们可以采用缓冲区配合超时空闲的方式来处理,首先定义一个缓冲数组用来存储收到的数据,并通过一个计时器来判断当前是否空闲,若空闲则把数据返回:

uint8_t rx = 0;
uint8_t buf[256];
uint16_t buf_idx = 0;
uint32_t cnt_idle = 0;//空闲超时方式接收不丢失数据
while(1)
{//空闲时间计数器if(buf_idx != 0){cnt_idle++;}else {cnt_idle = 0;}//数据缓存到数组中if(UART_GetRxBufferFull(UART0)){cnt_idle = 0;buf[buf_idx] = UART_ReceiveChar(UART0);buf_idx++;}//长时间没有接收到串口数据,把缓冲区数据返回if(cnt_idle > 5000)   //明显感觉=500000{UART_SendString(UART0, buf);cnt_idle = 0;buf_idx = 0;memset(buf, 0, sizeof(buf)/sizeof(buf[0]));}
}

实际测试效果很不错,数据没有任何丢失:

下面来介绍通过串口接收中断的方式来缓存数据。

5. 中断方式接收数据

初始化时使能串口接收中断,并通过NVIC开启串口中断请求。

void uart0_init(uint32_t BaudRate)
{UART_InitTypeDef UART_InitStruct;NVIC_InitTypeDef InitTypeDef_NVIC;UART_InitStruct.UART_Mode.UARTMode_Tx = ENABLE;UART_InitStruct.UART_Mode.UARTMode_Rx = ENABLE;UART_InitStruct.UART_Int.UARTInt_Tx = DISABLE;UART_InitStruct.UART_Int.UARTInt_Rx = ENABLE;   //开启接收中断UART_InitStruct.UART_Ovr.UARTOvr_Tx = DISABLE;UART_InitStruct.UART_Ovr.UARTOvr_Rx = DISABLE;UART_InitStruct.UART_Hstm = DISABLE;UART_InitStruct.UART_BaudRate = BaudRate;//Baud RateUART_Init(UART0, &UART_InitStruct);//Enable UART0 interrupt handlerInitTypeDef_NVIC.NVIC_IRQChannel = UART0_IRQn;InitTypeDef_NVIC.NVIC_IRQChannelPreemptionPriority = 1;InitTypeDef_NVIC.NVIC_IRQChannelSubPriority = 1;InitTypeDef_NVIC.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&InitTypeDef_NVIC);
}

串口中断服务函数,数据缓存到数组中,并清零空闲计数器:

void UART0_Handler(void)
{char rx = 0;if(UART_GetRxIRQStatus(UART0) == SET){rx = UART_ReceiveChar(UART0);buf[buf_idx] = rx;buf_idx++;cnt_idle = 0;}UART_ClearRxIRQ(UART0);
}

需要注释掉系统默认提供的串口中断服务函数,否则编译会报错。

主循环中通过一个计数器来判断串口是否空闲,当超时没有收到新的数据时,认为串口空闲,把缓冲区的数据返回:

uint8_t rx = 0;
uint8_t buf[256];
uint16_t buf_idx = 0;
uint32_t cnt_idle = 0;while(1)
{//长时间没有接收到串口数据if(buf_idx != 0)cnt_idle++;else cnt_idle = 0;if(cnt_idle > 5000)   //明显感觉=500000{printf("rx: %s", buf);cnt_idle = 0;buf_idx = 0;memset(buf, 0, sizeof(buf)/sizeof(buf[0]));}
}

下载,运行,数据完整:


本文是高云FPGA系列教程的第8篇文章。

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

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

相关文章

如何搭建一个react项目(详细介绍)

要搭建一个基本的 React 项目,你需要执行以下步骤。在开始之前,请确保你已经安装了 Node.js 和 npm(Node 包管理器)。 搭建一个React项目 1,创建项目目录2,初始化项目3,安装 React 和 ReactDOM4…

安卓机型固件系统分区的基础组成 手机启动规律初步常识 各分区的基本含义与说明

此贴为基本常识。感兴趣的友友可以了解手机的启动顺序和各模式的基本操作与意义。另外了解手机系统分区各文件夹的含义 分区说明对应贴:安卓机型固件中分区对应说明 手机开机基本启动顺序 当我们按下手机开机键的时候。基本的启动顺序为 注意:该结构图…

交流耐压试验目的

试验目的 交流耐压试验是鉴定电力设备绝缘强度最有效和最直接的方法。 电力设备在运行中, 绝缘长期受着电场、 温度和机械振动的作用会逐渐发生劣化, 其中包括整体劣化和部分劣化,形成缺陷, 例如由于局部地方电场比较集中或者局部…

Facebook最佳聊单工具--SaleSmartly,智能回复+控评+群控分流

关于SaleSmartlySaleSmartly--全渠道客户沟通平台,它可以帮助企业实现聊天自动化、智能化,提高员工效率,降低人工成本,提升客服质量。 在管理facebook时,你遇到的痛点: (1)FB聊单如何实现业务最…

AUTOSAR汽车电子嵌入式编程精讲300篇-车载CAN总线网络的异常检测(续)

目录 车载 CAN 总线网络异常检测技术 3.1 车载 CAN 总线网络异常检测技术概述 3.1.1基于统计的异

7-3 成绩等级

7-3 成绩等级 给出一个成绩&#xff0c;要求输出成绩等级‘A’,‘B’,‘C’,‘D’,‘E’.(90分以上为’A’,80到89分为’B’,70到79分为’C’,60到69分为’D’,60分以下为’E’。 输入格式: 在一行输入一个整数n&#xff08;n<100)。 输出格式: 在一行中输出成绩相对应的等…

大麦订单生成器最新版 大麦订单一键生成截图

1.可以一键添加&#xff0c;生成的假订单没有水印&#xff0c;界面也很真实。 2.在软件中输入生成的信息&#xff0c;这是产品信息&#xff0c;选择生成的产品图像&#xff0c;最后生成它。 后台一键生成&#xff0c;独立后台管理 教程&#xff1a;解压源码&#xff0c;修改…

用于无功补偿的固定电容晶闸管控制反应器研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

03MyBatis-Plus中的常用注解

常用注解 TableName MyBatis-Plus根据BaseMapper中指定的泛型(实体类型名)确定数据库中操作的表,如果根据实体类型名找不到数据库中对应的表则会报表不存在异常 //向表中插入一条数据 Test public void testInsert(){User user new User(null, "张三", 23, "…

深入学习 Redis Sentinel - 基于 DockerCompose 编排哨兵分布式架构,理解工作原理

目录 一、哨兵模式 1.1、为何引入哨兵模式 1.2、Redis Sentinel 分布式架构 1.2.1、概述 1.2.2、工作原理&#xff08;redis 哨兵的核心功能&#xff09; 1. 监控&#xff1a; 2. 自动故障转移&#xff1a; 3. 通知 1.2.3、问题&#xff1a;哨兵结点只有一个可以么&am…

SpringCloud——微服务

微服务技术栈 在之前的开发过程中&#xff0c;我们将所有的服务都部署在一台服务器中&#xff0c;当我们的服务开始越来越多&#xff0c;业务越来越复杂&#xff0c;当一台服务器不能承担我们的业务的时候&#xff0c;就需要将不同的业务分开部署在不同的服务器上&#xff0c;…

Feign实战-Springboot集成OpenFeign Demo以及参数详解

最近整理一下微服务的文章&#xff0c;先拿一直用的OpenFeign开刀 思考&#xff1a;微服务之间如何方便优雅的实现服务间的远程调用 一、说说openFeign是什么吧&#xff1f; 说到这个&#xff0c;那不得不先说说RPC 1.什么是RPC RPC 全称是 Remote Procedure Call &#x…

Appium混合页面点击方法tap的使用

原生应用开发&#xff0c;是在Android、IOS等移动平台上利用官方提供的开发语言、开发类库、开发工具进行App开发&#xff1b;HTML5&#xff08;h5&#xff09;应用开发&#xff0c;是利用Web技术进行的App开发。目前&#xff0c;市面上很多app都是原生和h5混合开发&#xff0c…

消息队列常见问题

什么是消息队列&#xff1f;请简要解释消息队列的工作原理。 答&#xff1a;消息队列是一种异步通信机制&#xff0c;用于在应用程序之间传递消息。它主要包括生产者&#xff08;Producer&#xff09;、消息队列&#xff08;Message Queue&#xff09;和消费者&#xff08;Con…

竞赛选题 基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

知识库系统推荐,强大的全文检索与文档分类管理功能

在我们日常企业运营管理过程中&#xff0c;会积累大量的文档资料&#xff0c;对于我们全体成员来说&#xff0c;这些知识文档都是巨大的财富&#xff0c;所以整合并搭建一套知识库系统是非常有必要的。 知识库系统推荐 我们日常工作中产生大量的文档&#xff0c;随着存储技术的…

pte初步认识学习

我们的时间的确很少&#xff0c;但是我们每天都乐意将珍贵的时间浪费在大量毫无意义的事情上 目录 pte介绍 PTE口语评分规则 pte架构 计算机科学23 QS排名 《芭比》 pte介绍 PTE口语评分规则 有抑扬顿挫 对于连读 不能回读 native pte对于个别单词没有读好&#xff0c…

MySQL学习系列(2)-每天学习10个知识

目录 1. INNER JOIN 和 ON 子句2. 死锁3. SELECT * 和 SELECT column1, column24. 数据库的视图5. MySQL的触发器类型6. MySQL表的备份和恢复7. MySQL存储引擎8. 索引优化9. MySQL中的子查询10. 使用连接&#xff08;JOIN&#xff09;从多个表中检索数据 &#x1f44d; 点赞&am…

【性能优化下】组织结构同步优化二,全量同步/增量同步,断点续传实现方式

看到这一篇文章的 xdm &#xff0c;应该对组织结构同步有一些想法了吧&#xff0c;如果没有&#xff0c;可以看前面两篇文章&#xff0c;可以通过如下地址查看一下&#xff1a; 【性能优化上】第三方组织结构同步优化一&#xff0c;你 get 到了吗&#xff1f; 坑爹&#xff0c…

Golang 中 int 类型和字符串类型如何相互转换?

在日常开发中&#xff0c;经常需要将数字转换为字符串或者将字符串转换为数字。在 Golang 中&#xff0c;有一些很简便的方法可以实现这个功能&#xff0c;接下来就详细讲解一下如何实现 int 类型和字符串类型之间的互相转换。 使用 strconv 包 strconv 包提供的 Itoa 和 Ato…