单片机非阻塞串口中断收发数据
下面的程序使用 CH32V103C8T6评估板测试没有问题,使用中断完成了串口的非阻塞式收发,编程思路参考了51单片机非阻塞串口中断收发数据
usart_buf.h
/** usart_buf.h** Created on: 2022年6月19日* Author: lin*/
#ifndef USER_DEV_USART_BUF_H_
#define USER_DEV_USART_BUF_H_#include "ch32v10x.h"#define USART_USE 1 // 使用那个串口 1 2 3
#define BAUDRATE 115200 // 波特率
#define SEND_BUF_SIZE 128 // 发送缓存大小
#define RECEIVE_BUF_SIZE 128 // 接收缓存大小
#define END_CHAR '\n' // 接收字符结束标志
#define USARTx_PP 1 //抢占优先级
#define USARTx_SUB 1 //执行优先级typedef enum
{USART_ReceiveReady,USART_ReceiveComplete,
}USART_ReceiveStateType;extern uint8_t USART_Receive_Buf[RECEIVE_BUF_SIZE];
extern USART_ReceiveStateType USART_ReceiveState;extern void Init_USART(void);
extern void USART_SendStr(const char* Data);
extern void USART_SendBuf(const uint8_t* Data, uint16_t size);
extern void USART_SendNum(int32_t num);
extern void USART_SendByte(uint8_t Data);
extern void USART_SendHex8(uint8_t Data);
extern void USART_SendBin(uint32_t Data);#endif /* USER_DEV_USART_BUF_H_ */
usart_buf.c
/** usart_buf.c** Created on: 2022年6月19日* Author: lin*/
#include "usart_buf.h"/*-------------接口-------------*/
#if (USART_USE == 1)#define USART_Periph USART1#define USART_PORT GPIOA#define USART_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE)#define USART_TX GPIO_Pin_9#define USART_RX GPIO_Pin_10#define USARTx_IRQN USART1_IRQn
#elif (USART_USE == 2)#define USART_Periph USART2#define USART_PORT GPIOA#define USART_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE)#define USART_TX GPIO_Pin_2#define USART_RX GPIO_Pin_3#define USARTx_IRQN USART2_IRQn
#elif (USART_USE == 3)#define USART_Periph USART3#define USART_PORT GPIOB#define USART_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE)#define USART_TX GPIO_Pin_10#define USART_RX GPIO_Pin_11#define USARTx_IRQN USART3_IRQn
#endif//发送
typedef struct
{uint8_t buf[SEND_BUF_SIZE]; //存放待发送字节uint8_t* p_w; //当前写入指针uint8_t* p_s; //当前发送指针
} USART_SendBufTypeDef;
USART_SendBufTypeDef SendBufStruct = {.buf={0}, .p_s=(uint8_t*)(0), .p_w=(uint8_t*)(0)};//接收
uint8_t USART_Receive_Buf[RECEIVE_BUF_SIZE] = {0};
USART_ReceiveStateType USART_ReceiveState = USART_ReceiveReady;
static uint8_t dat = 0; //接收临时变量
static uint16_t byte_n = 0; //接收计数void Init_USART(void)
{GPIO_InitTypeDef GPIO_InitStruct;USART_InitTypeDef USART_InitStruct;NVIC_InitTypeDef NVIC_InitStruct;// 发送相关指针初始化SendBufStruct.p_s = SendBufStruct.buf;SendBufStruct.p_w = SendBufStruct.buf;USART_RCC; //开时钟GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Pin = USART_TX;GPIO_Init(USART_PORT, &GPIO_InitStruct);//GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Pin = USART_RX;GPIO_Init(USART_PORT, &GPIO_InitStruct);USART_InitStruct.USART_BaudRate = BAUDRATE;USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;USART_InitStruct.USART_Parity = USART_Parity_No;USART_InitStruct.USART_StopBits = USART_StopBits_1;USART_InitStruct.USART_WordLength = USART_WordLength_8b;USART_Init(USART_Periph, &USART_InitStruct);USART_ClearFlag(USART_Periph, USART_FLAG_TC); //串口状态寄存器 复位值0x000000C0 TC和TXE是1 表示发送完成 上电会进中断一次 初始化应该清除此标志USART_ClearFlag(USART_Periph, USART_FLAG_TXE);USART_ITConfig(USART_Periph, USART_IT_TC, ENABLE);USART_ITConfig(USART_Periph, USART_IT_RXNE, ENABLE);NVIC_InitStruct.NVIC_IRQChannel = USARTx_IRQN;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = USARTx_PP; //优先级配置NVIC_InitStruct.NVIC_IRQChannelSubPriority = USARTx_SUB;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);USART_Cmd(USART_Periph, ENABLE);
}#if (USART_USE == 1)
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART1_IRQHandler(void)
#elif (USART_USE == 2)
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void)
#elif (USART_USE == 3)
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART3_IRQHandler(void)
#endif
{//发送if(USART_GetITStatus(USART_Periph, USART_IT_TC) == SET){if(SendBufStruct.p_s != SendBufStruct.p_w){//USART_Periph->DATAR = (*(SendBufStruct.p_s) & (uint16_t)0x01FF); //发送完成后 又触发中断发送后续字节USART_SendData(USART_Periph, *(SendBufStruct.p_s));++SendBufStruct.p_s; //增加发送指针}else{SendBufStruct.p_s = SendBufStruct.buf; //发送完全部字节后 各指针归位 清中断标志SendBufStruct.p_w = SendBufStruct.buf;//USART_ClearITPendingBit(USART_Periph, USART_IT_TC);}USART_ClearITPendingBit(USART_Periph, USART_IT_TC);}//接收if(USART_GetITStatus(USART_Periph, USART_IT_RXNE) == SET){/*处理接收中断*/dat = (uint8_t)USART_ReceiveData(USART_Periph);if(dat != END_CHAR && USART_ReceiveState == USART_ReceiveReady && byte_n < RECEIVE_BUF_SIZE-1){USART_Receive_Buf[byte_n] = dat;++byte_n;}else{USART_Receive_Buf[byte_n] = '\0';USART_ReceiveState = USART_ReceiveComplete; // 此时可以处理,处理完成之后设置为USART_ReceiveReady在接收后续字符byte_n = 0;}USART_ClearITPendingBit(USART_Periph, USART_IT_RXNE);}}void USART_SendByte(uint8_t Data)
{*(SendBufStruct.p_w) = Data;++SendBufStruct.p_w;if(SendBufStruct.p_s == SendBufStruct.buf){USART_SendData(USART_Periph, *(SendBufStruct.p_s));++SendBufStruct.p_s;}
}void USART_SendStr(const char* Data)
{while(*Data){*(SendBufStruct.p_w) = *Data;++SendBufStruct.p_w; //指向当前字符串最后一个字符++Data;}//判断是否需要重新发送第一个字节触发 "发送完成中断"if(SendBufStruct.p_s == SendBufStruct.buf){USART_SendData(USART_Periph, *(SendBufStruct.p_s)); //发送起始字节,发送完成后进入中断处理后续字节++SendBufStruct.p_s;}
}void USART_SendBuf(const uint8_t* Data, uint16_t size)
{const uint8_t* end = Data+size;while(Data < end){*(SendBufStruct.p_w) = *Data;++SendBufStruct.p_w; //指向当前字符串最后一个字符++Data;}//判断是否需要重新发送第一个字节触发 "发送完成中断"if(SendBufStruct.p_s == SendBufStruct.buf){USART_SendData(USART_Periph, *(SendBufStruct.p_s));++SendBufStruct.p_s;}
}static void Num_To_Str(int32_t num, char* strBuf)
{uint8_t NumLen = 0;uint32_t NumBak;uint8_t i,j;uint8_t NegativeActivateFlag = 0;if(num == 0){strBuf[0] = '0';strBuf[1] = '\0';return;}if(num < 0){NegativeActivateFlag = 1;num = -num;strBuf[0] = '-';}NumBak = num;//首先判断数字位数while(num != 0){++NumLen;num /= 10;}for(i = 0; i < NumLen; ++i){num = NumBak;for(j = i; j < NumLen-1; ++j){num /= 10;}if(NegativeActivateFlag){strBuf[i+1] = num%10 + '0';}else{strBuf[i] = num%10 + '0';}}if(NegativeActivateFlag){strBuf[i+1] = '\0';}else{strBuf[i] = '\0';}}void USART_SendNum(int32_t num)
{char strBuf[10+1] = {0};Num_To_Str(num, strBuf);USART_SendStr(strBuf);
}static uint8_t dec_to_hex_4(uint8_t Data)
{if((Data&0x0F) <= 9){return (Data&0x0F)+48;}else{return (Data&0x0F)+55;}}void USART_SendHex8(uint8_t Data)
{USART_SendByte( dec_to_hex_4(Data>>4) );USART_SendByte( dec_to_hex_4(Data) );USART_SendByte(' ');
}void USART_SendBin(uint32_t Data)
{uint32_t i;USART_SendByte('<');for (i = 0; i < 32; ++i){if(i!=0 && i%4 == 0){USART_SendByte('_');}if(Data&0x80000000){USART_SendByte('1');}else{USART_SendByte('0');}Data <<= 1;}USART_SendByte('>');USART_SendByte('\n');
}
main.c
#include "debug.h"
#include "ch32v10x.h"
#include "usart_buf.h"
#include "gpio_toggle.h"int main(void)
{uint16_t i = 0;Delay_Init();Delay_Ms(500);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);Init_GPIO_Toggle();Init_USART();while(1){if(USART_ReceiveState == USART_ReceiveComplete){USART_SendStr("Receive:");USART_SendStr(USART_Receive_Buf);USART_SendStr("\n");USART_ReceiveState = USART_ReceiveReady; //准备接收}if(i%50 == 0){//USART_SendStr("Hello World\n");GPIO_Toggle();}++i;// USART_SendStr("World Hello\n");
// USART_SendStr("Hello World\n");
// USART_SendStr("123456\n");
// USART_SendStr("654321\n");
// USART_SendStr("aaaa5555\n");
// USART_SendStr("8\n");
// USART_SendBin(10);Delay_Ms(10);}
}
单片机非阻塞串口中断收发数据相关推荐
- tms320f28027 中断优先级_TMS320F28027 自带串口中断收发数据例子
[实例简介] TMS320F28027自带有串口,利用串口中断与上位机(电脑)进行数据交换,软件设置成 上位机所发数据要以'*'结束. 仅供DSP板的学习所用,软件用的是CCS4.1,编译如果不能通过 ...
- 51单片机连接维特智能JY61串口6轴加速度陀螺仪(通过串口中断实现数据的现实)
51单片机连接维特智能JY61串口6轴加速度陀螺仪(通过串口中断实现数据的现实) 1.JY61的初始化 利用USB转TTL模块连接只需要连接: 打开厂家赠送的上位机软件,模块出厂默认设置使用串口,波特 ...
- STM8S UART串口使用中断收发数据
STM8S UART串口使用中断收发数据 原来调过STM8L的串口,逻辑简单,中断清晰,换成STM8S105K4后,虽然也是用STD库, 除去函数名.宏名等语言层面的差异以外,中断处理方面也有些不一样 ...
- Keil实例仿真AT89C51串口UART收发数据(附程序)
目录 一.引言 二.所用软件 1.串口调试工具 2.虚拟串口软件 3.Keil μVision5 三.软件设置 1.串口调试助手软件设置 2.虚拟串口软件设置 3.Keil C51设置 A.调试(.i ...
- QT入门第十四天 串口通信协议+收发数据+波特率+数据位+停止位+奇偶校验+串口识别射频RFID的卡号
QT入门第十四天 串口通信[QT入门第十四天 串口通信协议+收发数据+波特率+数据位+停止位+奇偶校验+串口识别射频RFID的卡号 第一章 常见的硬件通信接口协议 [1]硬件通信接口协议 [2]使用串 ...
- STM32F0系列串口DMA收发数据
关于STM32F0系列串口DMA收发数据详解 这里用的库函数版本,芯片型号为stm32f030c8t6.在用到串口DMA时,要按以下几个步骤进行. 1.确定使用的串口号,这里,我用的是usart2,对 ...
- PHp批量推送数据太慢,PHP非阻塞批量推送数据-php教程
明天看到论坛外面有人问如PHP何批量非梗阻向效劳器推送数据,这里大略总结下. 相干保举:<PHP教程> 一.最简略的方法: 一个剧本同时跑屡次,用参数来跑指定范畴.如果要推送10000用户 ...
- STM32G070RBT6基于STM32CubeMX创建串口中断接收数据
STM32G070RBT6基于STM32CubeMX创建串口中断接收数据
- 单片机串口高效收发数据的实现方法
想学习单片机的同学可以关注.私信我或者在评论区回复我要入门.这一期我们探讨传统数据收发不足之后,如何使用带FIFO的串口来减少接收中断次数,通过一种自定义通讯协议格式,给出帧打包方法:之后介绍一种特殊 ...
最新文章
- TFRecord tf.train.Feature
- php 文件管理系统_如何编写程序实现图书管理系统的个人图书借阅查询功能
- Activiti概述
- How does Spring @Transactional Really Work?--转
- 图像处理之log---log算子
- Java的IO:BIO | NIO | AIO
- 支付宝支付-手机浏览器H5支付
- Vue源码学习: 关于对Array的数据侦听
- 2022-2028年中国差旅管理行业市场全景调查及投资潜力研究报告
- 21世纪语言教程5c,21世纪核心素养5C模型
- ASIC和FPGA设计流程
- Ubuntu安装yum
- [轉]值得研究 邓亚萍代表的到底是哪个“国家”?
- Photoshop——更改图片比例
- 示波器界面的中英文切换
- 简单数据处理(相关系数,协方差,t检验)
- Unity3D 解决检测碰撞某类物体的一种方法
- 2022年中职网络空间安全国赛竞赛题解析仅代表自己的建议——2022年中职网络安全国赛竞赛试题9解析
- Java6、7章总结复习
- 针对等额本金还款模式的客户,写一个程序按顺序输入贷款总额(单位为万元)、月利率、贷款总月数,输出第一个月客户还款金额(单位为元,取整数)。