STM32串口中断的方式发送

2023-05-16

我将其改为真正的中断发送。

步骤一:初始化GPIO

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;         //LED1-PC10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;          //USART1 TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);          //A端口
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;             //USART1 RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //复用开漏输入
GPIO_Init(GPIOA, &GPIO_InitStructure);               //A端口

步骤二:开时钟

/* Enable USART1, GPIOA, GPIOD and AFIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC
                         | RCC_APB2Periph_AFIO, ENABLE);

在此说明,不用设置RCC_APB2Periph_AFIO也是可以的,也就是在此没有使用复用功能。这两个步骤与查询方式是一样的。

步骤三:初始化USART1

USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_Parity = USART_Parity_No;      //设置奇校验时,通信出现错误
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 /* Configure the USART1 */
USART_Init(USART1, &USART_InitStructure);
 /* Enable the USART Transmoit interrupt: this interrupt is generated when the
USART1 transmit data register is empty */ 
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
 /* Enable the USART Receive interrupt: this interrupt is generated when the
  USART1 receive data register is not empty */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
 /* Enable USART1 */
USART_Cmd(USART1, ENABLE);

在这里要使能USART1的外设中断,如USART_ITConfig(USART1, USART_IT_TXE, ENABLE);这就是使能发送中断,但发送寄存器空时能产生中断。

步骤四:编写中断函数

#define TxBufferSize1   (countof(TxBuffer1) - 1)
#define RxBufferSize1   (countof(TxBuffer1) - 1)
#define countof(a)   (sizeof(a) / sizeof(*(a)))      //表示数组a中元素的个数 
 
uint8_t TxBuffer1[] = "USART Interrupt Example: This is USART1 DEMO";
uint8_t RxBuffer1[RxBufferSize1],rec_f;
__IO uint8_t TxCounter1 = 0x00;
__IO uint8_t RxCounter1 = 0x00;
uint8_t NbrOfDataToTransfer1 = TxBufferSize1;
uint8_t NbrOfDataToRead1 = RxBufferSize1;
 
 
/*串口中断服务程序*/
void USART1_IRQHandler(void)
{
  unsigned int i;
  /*接收中断*/
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {   
    /* Read one byte from the receive data register */
    RxBuffer1[RxCounter1++] = USART_ReceiveData(USART1);
    if(RxCounter1 == NbrOfDataToRead1)  //接收数据达到需要长度,则将数据复制到发送数组中,并置标志
    {                     
      /* Disable the USART1 Receive interrupt */
      //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
        for(i=0; i< RxCounter1; i++) TxBuffer1[i]  = RxBuffer1[i];
        rec_f=1;
        RxCounter1=0;
        TxCounter1=0;
        USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  //打开发送中断,这句是关键
    }
  }
  /*发送中断*/
  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  {  
  
    USART_SendData(USART1, TxBuffer1[TxCounter1++]);
 
    if(TxCounter1 == NbrOfDataToTransfer1)//发送数据完成
    {   
      USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //关闭发送中断
    }   
  }   
} 

至此程序就结束了。

我们就会有个疑问,main()只包括前三个步骤的初始化和一个死循环,那么中断又是如何触发的呢,main()的结构如下:

int main(void)
{
 /* System Clocks Configuration */
 RCC_Configuration();
 /* NVIC configuration */
 NVIC_Configuration();
 /* Configure the GPIO ports */
 GPIO_Configuration();
 USART_Configuration();
 
 while (1)
 {
 }
}

原来是这样的:状态寄存器USART_SR的复位值为0x00C0H, 也就是第七位TXE和第六位TC复位值为1,而TXE=1,表明发送数据寄存器为空, TC=1表明发送已完成。而在USART的设置中有

	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

这两句使能中断,也就是说当TXE=1就会进入中断,所以程序初始化后就能进入中断,执行

if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
 {  
    /* Write one byte to the transmit data register */
      USART_SendData(USART1, TxBuffer[TxCounter++]);
    if(TxCounter == NbrOfDataToTransfer)
    {
      /* Disable the USART1 Transmit interrupt */
      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    }
 }

因此建议的是在初始化时不好启用TXE中断,只在要发送数据(尤其是字符串、数组这样的系列数据)时才启用TXE。在发送完成后立即将其关闭,以免引起不必要的麻烦。
对于发送,需要注意TXE和TC的差别——这里简单描述一下,假设串口数据寄存器是DR、串口移位寄存器是SR以及TXD引脚TXDpin,其关系是DR->SR->TXDpin。当DR中的数据转移到SR中时TXE置1,如果有数据写入DR时就能将TXE置0;如果SR中的数据全部通过TXDpin移出并且没有数据进入DR,则TC置1。并且需要注意TXE只能通过写DR来置0,不能直接将其清零,而TC可以直接将其写1清零。
对于发送单个字符可以考虑不用中断,直接以查询方式完成。
对于发送字符串/数组类的数据,唯一要考虑的是只在最后一个字符发送后关闭发送中断,这里可以分为两种情况:对于发送可显示的字符串,其用0x00作为结尾的,因此在ISR中就用0x00作为关闭发送中断(TXE或者TC)的条件;第二种情况就是发送二进制数据,那就是0x00~0xFF中间的任意数据,就不能用0x00来判断结束了,这时必须知道数据的具体长度。

来自 http://huangchuanlong.blog.163.com/blog/static/14709020201281921233833/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32串口中断的方式发送 的相关文章

  • 如何更改闪存的起始地址?

    我正在使用 STM32F746ZG 和 FreeRTOS Flash的起始地址是0x08000000 但我想把它改成0x08040000 我通过谷歌搜索了这个问题 但没有找到解决方案 我更改了链接器脚本 如下所示 MEMORY RAM xr
  • 在地址“0xXXXXXX”处中断,没有可用的调试信息,或在程序代码之外

    配置 使用 Nucleo L476RG 使用 GNU ARM Eclipse 我从 STM32CubeMX 生成了一个极简代码 我已经在我的板载 ST Link 中刷新了 J link 驱动程序 一直在尝试为我的代码运行调试器 但我的程序计
  • 在 MCU 内部 FLASH 中从一个固件跳转到另一个固件

    我目前正在开发针对 STM32F030C8 的引导加载程序固件应用程序 我在分散文件中指定引导加载程序应用程序将占用主内存位置 0x08000000 到 0x08002FFF 扇区 0 到扇区 2 我还编写了一个主固件应用程序 存储在0x0
  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • CMSIS 库是否应该包含在版本控制中? [复制]

    这个问题在这里已经有答案了 通常 我曾经在版本控制中包含芯片供应商 ST 提供的设备特定标头和源以及 CMSIS Core 标头 数量不多 也没有更新的习惯 我使用STM32微控制器 但我不使用立方体框架 or the 标准外设库 最近 我
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • 物联网网关

    物联网网关是 连接物联网设备和互联网的重要桥梁 它负责将物联网设备采集到的数据进行处理 存储和转发 使其能够与云端或其它设备进行通信 物联网网关的作用是实现物联网设备与云端的无缝连接和数据交互 物联网网关功能 数据采集 物联网网关可以从物联
  • [屏驱相关]【SWM166-SPI-Y1.28C1测评】+ 有点惊艳的开箱

    耳闻华芯微特许久了 看到论坛得评测活动赶紧上了末班车 毕竟对有屏幕得板子也是很喜欢得 京东快递小哥客客气气 微笑着把快递给了我 好评 直接拆了包 在此之前没看过视频号 所以这个圆盘盘得模具还是有点惊喜的 正面照如下 开机有灯光秀 还有动画
  • 最终启动顺序错误 - STM32L476 的 Eclipse System Workbench 调试

    我正在尝试调试和运行 STM32L476 的简单汇编代码 我已经设置了 Eclipse Oxygen 在 Eclipse 中安装了最新版本的 System Workbench 插件并安装了 ST Link 驱动程序 IDE 成功构建了程序
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • Freertos低功耗管理

    空闲任务中的低功耗Tickless处理 在整个系统运行得过程中 其中大部分时间都是在执行空闲任务的 空闲任务之所以执行 因为在系统中的其他任务处于阻塞或者被挂起时才会执行 因此可以将空闲任务的执行时间转换成低功耗模式 在其他任务解除阻塞而准
  • CMSIS & STM32,如何开始? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 STM32 上使用 CMSIS 启动项目 网上一搜 没找到具体的教程 有些使用 SPL 开始项
  • 库函数点亮Led

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 例如 随着人工智能的不断发展 机器学习这门
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • 在 Contiki 程序中使用 malloc

    考虑以下 Contiki 程序 include
  • STM32F0、ST-link v2、OpenOCD 0.9.0:打开失败

    我在用着发射台 http www ti com ww en launchpad about htmlgcc arm none eabi 4 9 2015q2 为 STM32F0 进行编译 现在我想使用该集合中的 arm none eabi
  • HAL_Delay() 陷入无限循环

    我被 HAL Delay 函数困住了 当我调用此函数 HAL Delay 时 控制陷入无限循环 在寻找问题的过程中 我发现了这个 http www openstm32 org forumthread2145 threadId2146 htt
  • 读取STM32 MCU SPI数据寄存器的值

    有很多类似的问题 但似乎没有一个问题完全相同 我正在将 STML4 MCU 连接到 6 轴传感器 LSM6DS3 我已经成功地在 I2C 中实现了所有内容 但想要 SPI 的额外速度 和 DMA 如果我能让这些第一步工作起来的话 因此 第一

随机推荐

  • 蚁群算法实现三维避障轨迹规划(Matlab)

    关于蚁群算法 其实大多数优化算法都是 试错 的过程 xff0c 不同的是如何利用在 试错 过程中得到的经验 蚁群算法在 试错 的过程中通过留下信息素对未来的试错过程加以提示 xff0c 从而保证一定的收敛性 代码分析 我写了一份matlab
  • CAN总线基础知识(2)——CAN的数据帧

    CAN总线基础知识 xff08 2 xff09 CAN结构上由7个段组成 xff08 仲裁段包括上篇说的can id 和 RTR xff09 xff0c 如图所示 其中根据仲裁段ID码长度的不同 xff0c 分为标准帧 xff08 CAN2
  • 一种通过printf打印的调试程序的方法

    我们在写代码的时候 xff0c 有时候需要调试程序的时候 xff0c 对于初学者 xff0c 可以通过简单的增加printf函数打印 xff0c 这样能够来跟踪程序的踪迹 xff0c 举个很简单的代码 xff1a include lt st
  • 详解Unity中的Nav Mesh新特性|导航寻路系统 (二)

    前言 第一篇我们简要概述了新版NavMesh的一些新增功能 xff0c 以及旧版的对比 本篇我们来讲一讲NavMeshSurface NavMeshLink这两个组件的参数以及如何应用 xff0c 接下来就进入正题吧 本系列提要 Unity
  • ROS安装包--rqt

    ROS安装包 rqt 安装命令刷新缓存 安装命令 sudo apt get install ros kinetic rqt sudo apt get install ros kinetic rqt common plugins sudo a
  • 【无标题】

    ROS自定义话题传输出现md5sum错误 问题描述 提前从一个程序中使用rosbag record命令对某一话题进行了录制 xff0c 之后用rostopic echo命令确定了录入了信息 但是给另一程序发布的时候 xff0c 终端报错 x
  • 关于CAN标准帧和扩展帧为什么分别占位是11bit和29bit

    关于CAN标准帧和扩展帧为什么分别占位是11bit和29bit 文章目录 关于CAN标准帧和扩展帧为什么分别占位是11bit和29bit前言一 关于标准帧二 关于扩展帧总结写在结尾 前言 之前一直没明白CAN标准帧和扩展帧为什么分别占位是1
  • 旭日x3派个人配置总结(ubuntu server + xrdp)

    旭日x3派基本设置 旭日x3派使用文档 首发 多方位玩转旭日x3派 XRDP 43 Xface4远程桌面设置 安装xrdp并解决闪退 黑屏问题 ROS2 Foxy配置 解决 Failed to connect to raw githubus
  • 思岚S2激光雷达1—初次连接

    1 去官网下载Robostudio xff0c 我这里是windows http www slamtec com robostudio 2 连接激光雷达 3 去官网下载SDK 4 在SDK文件夹里的tools里面找驱动下载驱动 5 电脑成功
  • ZED2双目相机1:标定

    一 下载及安装 xff08 1 xff09 按照下面这个链接 xff1a https blog csdn net TengYun zhang article details 123072847 下载完是这样的 xff1a xff08 2 x
  • ZED2双目相机2:畸变矫正

    1 运行ZED2相机 xff08 注意是在ZED WS工作空间里 xff09 xff08 1 xff09 关闭anconda xff08 如果有的话 xff09 xff1a conda deactivate span class token
  • 用android代码实现一个可以万能播放器

    要实现一个万能播放器需要使用多媒体库 xff0c 可以使用Android自带的MediaPlayer类以及ExoPlayer库 以下是一个简单的示例代码 xff1a 在XML布局文件中添加一个SurfaceView和几个按钮 xff1a s
  • 初出茅庐的小李第108篇博客二进制打印

    二进制打印介绍 C语言在格式化打印的时候有很多格式控制 xff0c 比如十进制打印用 d输出 xff0c 十六进制用 x输出 xff0c 八进制用 o格式输出 xff0c 但是当我们期望看一个数据的二进制的时候就必须借助计算器或者其他比较不
  • QGroundControl 自定义命令小工具的使用

    Custom Command Widgets 不用编译qgc的源码 xff0c 仅仅需要编写一个QML UIs文件这个小工具窗口可以被加载 xff0c 并且从重启之后仍然可以使用 xff0c 而且不受操作系统的限制主要有两个用途 xff11
  • HTTP请求方式GET和POST代码示例

    HTTP请求方式GET和POST代码示例 1 HTTP名词解释1 2 HTTP传输方式1 2 1GET名词解释1 2 1POST名词解释 1 3Http中Post 和Get代码实现 1 HTTP名词解释 HTTP大名叫做超文本传输协议 xf
  • Postman工具常见操作

    Postman常见操作 1 新建GET或POST请求 xff08 1 xff09 打开Postman xff0c 选择File gt New xff08 2 xff09 选择Request xff0c 进入 xff08 3 xff09 输入
  • Ubuntu18.04+ROS melodic 跑通VINS-MONO的一些踩坑记录

    VINS MONO的一些踩坑记录 0 本机环境 笔者的环境为Ubuntu 18 04 43 ros melodic 43 opencv 4 1 1 43 Eigen 3 3 9 43 ceres solver 1 14 跟VINS MONO
  • GPIO库函数开发和寄存器开发的区别

    函数原型为 xff1a void GPIO SetBits GPIO TypeDef GPIOx uint16 t GPIO Pin xff08 1 xff09 gt 箭头操作符要求左操作数必须是个指针GPIO TypeDef GPIOx
  • C++ 编译

    C 43 43 编译原理 参考博客 https www cnblogs com kevinWu7 p 10163443 html C C 43 43 编译就是要将C C 43 43 的代码映射到相应的机器码 xff0c 以及讨论其中的内存管
  • STM32串口中断的方式发送

    我将其改为真正的中断发送 步骤一 xff1a 初始化GPIO GPIO InitTypeDef GPIO InitStructure GPIO InitStructure GPIO Pin 61 GPIO Pin 10 LED1 PC10