当前位置: 首页 > wzjs >正文

模版型网站网站快速收录入口

模版型网站,网站快速收录入口,内网做网站,wordpress 做的商城在串口通信中,除了轮询方式,中断方式能更高效地处理数据收发,尤其适合需要实时响应的场景。本文将详细介绍如何在 STM32 中配置 USART 中断(包括接收中断和空闲中断),并通过中断处理函数实现数据的实时接收…

        在串口通信中,除了轮询方式,中断方式能更高效地处理数据收发,尤其适合需要实时响应的场景。本文将详细介绍如何在 STM32 中配置 USART 中断(包括接收中断和空闲中断),并通过中断处理函数实现数据的实时接收与命令解析。

一、为什么需要 USART 中断

        轮询方式虽然简单,但在等待数据时会阻塞 CPU,导致系统效率低下。而中断方式让 CPU 可以在没有数据时处理其他任务,只有当数据到来或满足特定条件(如总线空闲)时,才会触发中断并暂停当前任务去处理串口数据。这种方式能显著提高系统的实时性和资源利用率。

对于串口通信,常用的中断有两种:

  • 接收中断(RXNE):当接收缓冲区有数据时触发,用于实时接收单个字节。
  • 空闲中断(IDLE):当串口总线在数据传输后处于空闲状态时触发,通常用于判断一帧数据(如一个字符串)接收完成。

二、开启 USART 中断(接收中断与空闲中断)

要使用中断,首先需要开启对应的中断使能位。以下是寄存器和库函数两种实现方式:

1. 寄存器方式

// 打开接收中断(RXNEIE,CR1寄存器第5位)和空闲中断(IDLEIE,CR1寄存器第4位)
USART1->CR1 |= (1 << 5);  // 使能接收缓冲区非空中断(RXNE)
USART1->CR1 |= (1 << 4);  // 使能空闲线路检测中断(IDLE)

2. 库函数方式

// 打开接收中断和空闲中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  // 使能RXNE中断
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  // 使能IDLE中断

三、配置中断控制器 NVIC

STM32 的中断由 NVIC(嵌套向量中断控制器)管理,需要配置中断优先级和使能中断通道。

1. 中断优先级分组

STM32 的中断优先级由抢占优先级响应优先级组成,通过优先级分组设置两者的位数。常用的分组方式是 “2+2”(2 位抢占优先级,2 位响应优先级),共支持 16 级优先级。

// 设置中断优先级分组为2(2位抢占优先级,2位响应优先级)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

2. 配置 USART1 中断通道

// 定义NVIC初始化结构体
NVIC_InitTypeDef nvic;// 指定中断通道为USART1
nvic.NVIC_IRQChannel = USART1_IRQn;
// 使能该中断通道
nvic.NVIC_IRQChannelCmd = ENABLE;
// 设置抢占优先级(1级)
nvic.NVIC_IRQChannelPreemptionPriority = 1;
// 设置响应优先级(1级)
nvic.NVIC_IRQChannelSubPriority = 1;// 初始化NVIC
NVIC_Init(&nvic);
  • 抢占优先级决定中断的嵌套能力(高抢占优先级的中断可以打断低抢占优先级的中断)。
  • 响应优先级决定同抢占优先级中断的执行顺序(数值越小,优先级越高)。

四、实现中断处理函数

        中断处理函数是中断发生时的执行逻辑,STM32 规定了固定的函数名(如USART1_IRQHandler)。我们需要在函数中区分中断类型(接收中断 / 空闲中断),并进行相应处理。

1. 全局变量定义

首先定义用于缓存数据和命令的全局变量:

uint8_t buffer[255] = {0};  // 接收缓冲区(最大255字节)
uint8_t data;               // 临时变量,用于清除中断标志
int cnt = 0;                // 缓冲区计数
// 命令定义
uint8_t cmd0[] = "关灯";    // 关灯命令
uint8_t cmd1[] = "开灯";    // 开灯命令
uint8_t cmd2[] = "放歌";    // 放歌命令

2. 寄存器方式的中断处理函数

void USART1_IRQHandler(void)
{// 接收中断(RXNE:接收缓冲区非空)if (USART1->SR & (0X1 << 5))  // 判断SR寄存器第5位(RXNE标志){buffer[cnt++] = USART1->DR;  // 读取数据寄存器,保存到缓冲区// 注意:读取DR会自动清除RXNE标志}// 空闲中断(IDLE:总线空闲)if (USART1->SR & (0X1 << 4))  // 判断SR寄存器第4位(IDLE标志){// 清除空闲中断标志(必须先读SR,再读DR)data = USART1->SR;  // 读SR寄存器data = USART1->DR;  // 读DR寄存器(数据无用,仅用于清除标志)// 命令匹配与执行if (strcmp((char*)cmd0, (char*)buffer) == 0){GPIOB->ODR |= (0X1 << 5);  // PB5置高,关灯}else if (strcmp((char*)cmd1, (char*)buffer) == 0){GPIOB->ODR &= ~(0X1 << 5);  // PB5置低,开灯}else if (strcmp((char*)cmd2, (char*)buffer) == 0){play_two_tigers();  // 调用放歌函数(需提前实现)}// 清空缓冲区,准备下次接收memset(buffer, 0, cnt);cnt = 0;}
}

3. 库函数方式的中断处理函数

void USART1_IRQHandler(void)
{// 接收中断(RXNE)if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){buffer[cnt++] = USART_ReceiveData(USART1);  // 读取数据到缓冲区USART_ClearITPendingBit(USART1, USART_IT_RXNE);  // 清除接收中断标志}// 空闲中断(IDLE)if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET){// 清除空闲中断标志(先读SR,再读DR)data = USART1->SR;  // 读SR寄存器data = USART_ReceiveData(USART1);  // 读DR寄存器// 命令匹配与执行if (strcmp((char*)cmd0, (char*)buffer) == 0){GPIO_SetBits(GPIOB, GPIO_Pin_5);  // PB5置高,关灯}else if (strcmp((char*)cmd1, (char*)buffer) == 0){GPIO_ResetBits(GPIOB, GPIO_Pin_5);  // PB5置低,开灯}else if (strcmp((char*)cmd2, (char*)buffer) == 0){play_two_tigers();  // 调用放歌函数}// 清空缓冲区memset(buffer, 0, cnt);cnt = 0;}
}

4. 关键逻辑说明

  • 接收中断(RXNE):每次收到一个字节就触发,将数据存入buffer并递增计数cnt
  • 空闲中断(IDLE):当串口在数据传输后空闲(无数据达一定时间)时触发,此时认为一帧数据接收完成。我们需要:
    1. 清除空闲中断标志(必须先读SR再读DR,否则标志无法清除);
    2. 对比缓冲区数据与预设命令,执行对应操作(如开灯、关灯);
    3. 清空缓冲区,重置计数,准备下一次接收。

五、完整代码示例(库函数版)

将上述配置整合,完整代码如下:

#include "stm32f10x.h"
#include <string.h>// 全局变量
uint8_t buffer[255] = {0};
uint8_t data;
int cnt = 0;
uint8_t cmd0[] = "关灯";
uint8_t cmd1[] = "开灯";
uint8_t cmd2[] = "放歌";// 函数声明
void USART1_Init(void);
void GPIO_Init_LED(void);
void play_two_tigers(void);  // 假设已实现int main(void)
{// 初始化LED(PB5)GPIO_Init_LED();// 初始化USART1(含中断配置)USART1_Init();while (1){// 主循环可处理其他任务,中断会实时响应}
}// USART1初始化(含GPIO、USART配置和中断使能)
void USART1_Init(void)
{// 1. 使能时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);// 2. 配置GPIO(PA9=TX,PA10=RX)GPIO_InitTypeDef gpio;// PA9:复用推挽输出gpio.GPIO_Pin = GPIO_Pin_9;gpio.GPIO_Mode = GPIO_Mode_AF_PP;gpio.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio);// PA10:浮空输入gpio.GPIO_Pin = GPIO_Pin_10;gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &gpio);// 3. 配置USART1USART_InitTypeDef usart;usart.USART_BaudRate = 9600;usart.USART_WordLength = USART_WordLength_8b;usart.USART_StopBits = USART_StopBits_1;usart.USART_Parity = USART_Parity_No;usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;usart.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_Init(USART1, &usart);// 4. 配置中断优先级NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef nvic;nvic.NVIC_IRQChannel = USART1_IRQn;nvic.NVIC_IRQChannelCmd = ENABLE;nvic.NVIC_IRQChannelPreemptionPriority = 1;nvic.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&nvic);// 5. 使能USART中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);// 6. 使能USART1USART_Cmd(USART1, ENABLE);
}// LED初始化(PB5推挽输出)
void GPIO_Init_LED(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef gpio;gpio.GPIO_Pin = GPIO_Pin_5;gpio.GPIO_Mode = GPIO_Mode_Out_PP;gpio.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB, &gpio);
}// 中断处理函数
void USART1_IRQHandler(void)
{if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){buffer[cnt++] = USART_ReceiveData(USART1);USART_ClearITPendingBit(USART1, USART_IT_RXNE);}if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET){data = USART1->SR;data = USART_ReceiveData(USART1);if (strcmp((char*)cmd0, (char*)buffer) == 0){GPIO_SetBits(GPIOB, GPIO_Pin_5);  // 关灯}else if (strcmp((char*)cmd1, (char*)buffer) == 0){GPIO_ResetBits(GPIOB, GPIO_Pin_5);  // 开灯}else if (strcmp((char*)cmd2, (char*)buffer) == 0){play_two_tigers();  // 放歌}memset(buffer, 0, cnt);cnt = 0;}
}

六、总结与注意事项

  1. 中断标志的清除

    • 接收中断(RXNE):读取DR寄存器后自动清除。
    • 空闲中断(IDLE):必须先读SR寄存器,再读DR寄存器才能清除,否则会重复触发中断。
  2. 缓冲区溢出处理
    示例中未处理缓冲区溢出(cnt超过 255),实际应用中需添加判断(如if (cnt >= 255) cnt = 0;)。

  3. 命令匹配的局限性
    示例使用strcmp匹配命令,要求输入与命令完全一致(包括长度)。实际应用中可使用字符串查找函数(如strstr)提高灵活性。

  4. 中断优先级的设置
    根据系统需求调整抢占优先级和响应优先级,确保关键中断优先执行。

0voice · GitHub

http://www.dtcms.com/wzjs/362107.html

相关文章:

  • 郑州做网站优化电话今日微博热搜榜前十名
  • 太原网站快速排名优化百度信息流代理
  • 上海网站空间续费百度营销推广官网
  • 网站做https好处申请网址怎么申请的
  • 威海+网站建设搜索引擎优化免费
  • 免费提升学历长沙网站优化指导
  • 泸西县住房和城乡建设局网站网络推广图片大全
  • 和小学生做的黄色网站苏州网站优化公司
  • 画册设计说明seo的中文含义
  • 怎样做平台网站怎么在百度发帖
  • 建设个公司网站需要多少费用重庆疫情最新消息
  • 模板网站有什么不好友链购买有效果吗
  • 建设网站终身免费重庆seo教程博客
  • wordpress .net版本东莞seo建站公司哪家好
  • WordPress小说网站源码怎么去推广自己的店铺
  • 邯郸创建网站要多少钱推广通
  • 9e做网站怎样提高百度推广排名
  • 网站维护托管职业技能培训网上平台
  • 德州聊城网站建设如何进行搜索引擎优化?
  • 简单的j网站建设方案书活动宣传推广方案怎么写
  • 电脑单页网站建设外链网站是什么
  • 用网站做的人工智能全球网站排名查询网
  • 那些网站可以做海报seo值怎么提高
  • 网站建设服务联享科技营销策略手段有哪些
  • 旅游网站建设要如何做360免费建站官网
  • 怎么做导航网站股票发行ipo和seo是什么意思
  • 微官网怎么关注常用的seo查询工具
  • 网站开发 合作协议百度站长工具平台登录
  • 汕头网站建站公司今日头条新闻10条简短
  • 网站 可以做无形资产吗北京网站优化步