IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32通用串口驱动 -> 正文阅读

[嵌入式]STM32通用串口驱动

? ? ? ? 参考:STM32 FIFO RINGBUFF:https://blog.csdn.net/rou252051452/article/details/118607713

1.概述

? ? ? ? 本文实现如下功能:

  • 通用串口驱动
  • FIFO结合STM32的DMA实现串口数据的收发。

2.串口驱动相关结构体定义

串口参数结构体

typedef struct
{
	USART_TypeDef*			Uartx;			//指向物理串口的结构体
	UartIOCfg				CfgIO;			//串口收发管脚配置结构体
	USART_InitTypeDef		CfgUart;		//串口参数结构体
	NVIC_InitTypeDef 		CfgNvic;		//串口中断结构体
	UartCfgRx				CfgRx;			//串口接收DMA配置结构体
	UartCfgTx				CfgTx;			//串口发送DMA配置结构体
}SerialTypeDef;

串口IO配置结构体

typedef struct
{
	GPIO_TypeDef*			TxPort;				//发送端口
	GPIO_TypeDef*			RxPort;				//接收端口
	INT16U					TxPin;				//发送管脚
	INT16U					RxPin;				//接收管脚
}UartIOCfg;

接收DMA配置结构体

typedef struct
{
	DMA_Stream_TypeDef*	 	DmaStream;			//DMA流
	INT32U					DmaChannel;			//通道
	INT16U					Used;				//DMA使用量
	FifoTypeDef*			Fifo;				//流对应使用的FIFO。
	INT16U					FifoSize;			//接收fifo的大小。
	NVIC_InitTypeDef 		CfgNvic;			//DMA中断配置结构体
}UartCfgRx;

发送DMA配置结构体

typedef struct
{
	DMA_Stream_TypeDef*	 	DmaStream;			//DMA流
	INT32U					DmaChannel;			//通道
	FifoTypeDef*			Fifo;				//流对应使用的FIFO。
	INT16U					FifoSize;			//发送fifo的大小。
	INT8U*					Buff;				//发送的buff
	INT16U					BuffSize;			//发送buff的大小
	NVIC_InitTypeDef 		CfgNvic;
}UartCfgTx;

3.串口驱动实现

3.1 static局部函数

3.1.1串口IO初始化

/**
***************************************************
* @brief   bsp_uart_IOCfg
* @note    初始化IO为复用,USART或UART
* @param   serial   	指向串口参数
* @retval  NONE
* @data    2021.07.01
* @auth    WXL
* @his     1.0.0.0     2021.07.01     WXL
* 				create
***************************************************
**/
static void bsp_uart_IOCfg(SerialTypeDef* serial)
{
	GPIO_InitTypeDef 	GPIO_InitStructure;

	//IO初始化
	RCC_AHB1PeriphClockCmd(1<<( (((INT32U)serial->CfgIO.TxPort)-AHB1PERIPH_BASE) / 0x0400 ),ENABLE);
	GPIO_InitStructure.GPIO_Pin 	= (1 << serial->CfgIO.TxPin);
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_UP;
	GPIO_Init(serial->CfgIO.TxPort , &GPIO_InitStructure);

	RCC_AHB1PeriphClockCmd(1<<( ( ((INT32U)serial->CfgIO.RxPort)-AHB1PERIPH_BASE) / 0x0400 ),ENABLE);
	GPIO_InitStructure.GPIO_Pin 	= (1 << serial->CfgIO.RxPin);
	GPIO_Init(serial->CfgIO.RxPort , &GPIO_InitStructure);

	//IO复用
	if(serial->Uartx == USART1 || serial->Uartx == USART2 || serial->Uartx == USART3)
	{
		GPIO_PinAFConfig(serial->CfgIO.TxPort , serial->CfgIO.TxPin , 7);
		GPIO_PinAFConfig(serial->CfgIO.RxPort , serial->CfgIO.RxPin , 7);
	}
	if(serial->Uartx == UART4 || serial->Uartx == UART5 || serial->Uartx == USART6)
	{
		GPIO_PinAFConfig(serial->CfgIO.TxPort , serial->CfgIO.TxPin , 8);
		GPIO_PinAFConfig(serial->CfgIO.RxPort , serial->CfgIO.RxPin , 8);
	}
}

根据串口参数结构体的内容进行相关收发IO的初始化。注意一下几点:

  • 时钟使能

????????????????STM32的标准库中RCC_AHB1PeriphClockCmd参数1可设置为RCC_AHB1Periph_GPIOA到RCC_AHB1Periph_GPIOK。对应内容如下

RCC_AHB1Periph_GPIOA =?1<<( (((INT32U)serial->CfgIO.TxPort)-AHB1PERIPH_BASE) / 0x0400;

RCC_AHB1Periph_GPIOxGPIOx
RCC_AHB1Periph_GPIOA0x00000001GPIOA(AHB1PERIPH_BASE + 0x0000)
RCC_AHB1Periph_GPIOB0x00000002GPIOB(AHB1PERIPH_BASE + 0x0400)
RCC_AHB1Periph_GPIOC0x00000004GPIOC(AHB1PERIPH_BASE + 0x0800)
RCC_AHB1Periph_GPIOD0x00000008GPIOD(AHB1PERIPH_BASE + 0x0C00)
RCC_AHB1Periph_GPIOE0x00000010GPIOE(AHB1PERIPH_BASE + 0x1000)
RCC_AHB1Periph_GPIOF0x00000020GPIOF(AHB1PERIPH_BASE + 0x1400)
RCC_AHB1Periph_GPIOG0x00000040GPIOG(AHB1PERIPH_BASE + 0x1800)
RCC_AHB1Periph_GPIOH0x00000080GPIOH(AHB1PERIPH_BASE + 0x1C00)
RCC_AHB1Periph_GPIOI0x00000100GPIOI(AHB1PERIPH_BASE + 0x2000)
RCC_AHB1Periph_GPIOJ0x00000200GPIOJ(AHB1PERIPH_BASE + 0x2400)
RCC_AHB1Periph_GPIOK0x00000400GPIOK(AHB1PERIPH_BASE + 0x2800)
  • 管脚复用

? ? ? ? ? ? ? ? USART1,USART2,USART3的收发管脚均复用为功能7。UART4,UART5,USART6管脚复用功能为8需要注意。

3.1.2串口参数初始化

/**
***************************************************
* @brief   bsp_usart_UartInit
* @note    串口参数初始化
* @param   serial   	指向串口参数
* @retval  NONE
* @data    2021.07.01
* @auth    WXL
* @his     1.0.0.0     2021.07.01     WXL
* 				create
***************************************************
**/
static void bsp_usart_UartInit(SerialTypeDef* serial)
{
	//使能时钟。
	if(serial->Uartx == USART1)
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	else if(serial->Uartx == USART2)
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	else if(serial->Uartx == USART3)
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
	else if(serial->Uartx == UART4)
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);
	else if(serial->Uartx == UART5)
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
	else if(serial->Uartx == USART6)
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);

	USART_Init(serial->Uartx, &serial->CfgUart);
	USART_Cmd(serial->Uartx, ENABLE);
}

根据串口参数结构体中的物理串口进行相应的时钟使能,参数配置。

3.1.3中断初始化

/**
***************************************************
* @brief   bsp_usart_NVICCfg
* @note    串口中断初始化
* @param   serial   	指向串口参数
* @retval  NONE
* @data    2021.07.01
* @auth    WXL
* @his     1.0.0.0     2021.07.01     WXL
* 				create
***************************************************
**/
static void bsp_usart_NVICCfg(SerialTypeDef* serial)
{
	USART_ITConfig(serial->Uartx, USART_IT_IDLE, ENABLE);
	NVIC_Init(&serial->CfgNvic);
	USART_DMACmd(serial->Uartx,USART_DMAReq_Rx,ENABLE);
	USART_DMACmd(serial->Uartx,USART_DMAReq_Tx,ENABLE);
}

3.1.4中断初始化

/**
***************************************************
* @brief   bsp_usart_DMACfg
* @note    串口DMA配置
* @param   serial   	指向串口参数
* @retval  0         成功
*          1         申请内存失败
* @data    2021.07.01
* @auth    WXL
* @his     1.0.0.0     2021.07.01     WXL
* 				create
***************************************************
**/
static INT8U bsp_usart_DMACfg(SerialTypeDef* serial)
{
	DMA_InitTypeDef  		DMA_InitStructure;

	//创建接收FIFO
	serial->CfgRx.Fifo = func_fifo_Create(serial->CfgRx.FifoSize);
	if(serial->CfgRx.Fifo == NULL)
		return 1;
	serial->CfgRx.Used = 0;
	//创建发送FIFO
	serial->CfgTx.Fifo = func_fifo_Create(serial->CfgTx.FifoSize);
	if(serial->CfgTx.Fifo == NULL)
	{
		func_fifo_Free(serial->CfgRx.Fifo);
		return 1;
	}
	//创建发送BUFF
	serial->CfgTx.Buff = malloc(serial->CfgTx.BuffSize);
	if(serial->CfgTx.Buff == NULL)
	{
		func_fifo_Free(serial->CfgRx.Fifo);
		func_fifo_Free(serial->CfgTx.Fifo);
		return 1;
	}


	//接收   DMA配置
	DMA_Stream_TypeDef* stream  = serial->CfgRx.DmaStream;
	INT32U				channle = serial->CfgRx.DmaChannel;
	if(stream < DMA2_Stream0)
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
	else
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
	DMA_DeInit(stream);
	while(DMA_GetCmdStatus(stream) != DISABLE)
	{}
	DMA_InitStructure.DMA_Channel 				= channle;
	DMA_InitStructure.DMA_PeripheralBaseAddr 	= (u32)&(serial->Uartx->DR);
	DMA_InitStructure.DMA_Memory0BaseAddr 		= (u32)serial->CfgRx.Fifo->Buf;
	DMA_InitStructure.DMA_DIR 					= DMA_DIR_PeripheralToMemory;
	DMA_InitStructure.DMA_BufferSize 			= serial->CfgRx.FifoSize;
	DMA_InitStructure.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc 			= DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize 	= DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize 		= DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode 					= DMA_Mode_Circular;
	DMA_InitStructure.DMA_Priority 				= DMA_Priority_Medium;
	DMA_InitStructure.DMA_FIFOMode 				= DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold 		= DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst		= DMA_PeripheralBurst_Single;
	DMA_Init(stream, &DMA_InitStructure);
	DMA_Cmd(stream, ENABLE);

	NVIC_Init(&serial->CfgRx.CfgNvic);
	DMA_Cmd(stream, ENABLE);
	DMA_ITConfig(stream, DMA_IT_TC, ENABLE);

	//发送
	stream  = serial->CfgTx.DmaStream;
	channle = serial->CfgTx.DmaChannel;
	if(stream < DMA2_Stream0)
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
	else
		RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
	DMA_DeInit(stream);
	while(DMA_GetCmdStatus(stream) != DISABLE)
	{}
	DMA_InitStructure.DMA_Channel 				= channle;
	DMA_InitStructure.DMA_PeripheralBaseAddr 	= (u32)&(serial->Uartx->DR);
	DMA_InitStructure.DMA_Memory0BaseAddr 		= (u32)serial->CfgTx.Buff;
	DMA_InitStructure.DMA_DIR 					= DMA_DIR_MemoryToPeripheral;
	DMA_InitStructure.DMA_BufferSize 			= 0;
	DMA_InitStructure.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc 			= DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize 	= DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize 		= DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode 					= DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority 				= DMA_Priority_Medium;
	DMA_InitStructure.DMA_FIFOMode 				= DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold 		= DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst		= DMA_PeripheralBurst_Single;
	DMA_Init(stream, &DMA_InitStructure);
	DMA_Cmd(stream, ENABLE);

	NVIC_Init(&serial->CfgTx.CfgNvic);
	DMA_Cmd(stream, ENABLE);
	DMA_ITConfig(stream, DMA_IT_TC, ENABLE);

	return 0;
}

串口DMA初始化需要完成如下内容:

  1. FIFO申请:申请用于DMA接收的FIFO,申请用于DMA发送的数据缓存FIFO
  2. BUFF申请:申请用于DMA发送时使用的BUFF
  3. 接收DMA配置为循环模式,地址为FIFO中的BUFF地址,使DMA完成自动循环写入FIFO中。在DMA中断中进行FIFO无数据写入,实现数据的FIFO接收。
  4. 发送DMA配置,配置发送地址为上面申请的BUFF地址,发送时将发送FIFO中的内容读取到BUFF中进行DMA发送。
  5. DMA中断配置,使能DMA完成中断。

3.1.5接收数据回调函数

/**
***************************************************
  * @brief   bsp_uart_rx_callback
  * @note    IDLE中断和DMA完成中断回调函数。
  * @param   com     	端口。
  * 		 par		1   DMA完成中断
  * 		 			0   IDLE中断。
  * @retval  NONE
  * @data    2021.01.20
  * @auth    WXL
  * @his     1.0.0.1     2021.01.20     WXL
  * 		  新建文件
***************************************************
**/
static void bsp_uart_rx_callback(SerialTypeDef* serial,INT8U par)
{
    INT16U count = 0;
    INT16U used = 0;

    //DMA完成中断调用。
    if(par == 1)
    {
    	count = serial->CfgRx.FifoSize - serial->CfgRx.Used;//计算本次接收元素个数。
    	serial->CfgRx.Used = 0;								//DMA为Circular模式,中断中需要清零该变量。
    }
    //IDLE中断调用。
    else
    {
    	//计算本次接收元素个数。
    	used = serial->CfgRx.FifoSize - DMA_GetCurrDataCounter(serial->CfgRx.DmaStream);
        count = used - serial->CfgRx.Used;
        serial->CfgRx.Used = used;
    }
	//更新接收FIFO的指针。
    func_fifo_PushNoData(serial->CfgRx.Fifo, count);
}

? ? ? ? 在接收DMA完成中断和串口IDLE中断中调用。计算写入量,将FIFO进行相应操作。以上函数均为局部函数,不对外开放。

3.2全局函数

3.2.1设置串口配置参数为默认

/**
***************************************************
  * @brief   bsp_uart_ParaSetDefault
  * @note    设置串口参数未默认IDLE中断和DMA完成中断回调函数。
  * @param   serial     	指向设置的串口
  * @retval  NONE
  * @data    2021.01.20
  * @auth    WXL
  * @his     1.0.0.1     2021.01.20     WXL
  * 		  新建文件
***************************************************
**/
void bsp_uart_ParaSetDefault(SerialTypeDef* serial)
{
	serial->Uartx = USART1;

	serial->CfgIO.RxPin		= 10;
	serial->CfgIO.RxPort	= GPIOA;
	serial->CfgIO.TxPin 	= 9;
	serial->CfgIO.TxPort	= GPIOA;

	serial->CfgUart.USART_BaudRate 				= 115200;
	serial->CfgUart.USART_HardwareFlowControl 	= USART_HardwareFlowControl_None;
	serial->CfgUart.USART_Mode 					= USART_Mode_Tx | USART_Mode_Rx;
	serial->CfgUart.USART_Parity 				= USART_Parity_No;
	serial->CfgUart.USART_StopBits				= USART_StopBits_1;
	serial->CfgUart.USART_WordLength				= USART_WordLength_8b;

	serial->CfgNvic.NVIC_IRQChannel 					= USART1_IRQn;
	serial->CfgNvic.NVIC_IRQChannelPreemptionPriority	= 1;
	serial->CfgNvic.NVIC_IRQChannelSubPriority			= 1;
	serial->CfgNvic.NVIC_IRQChannelCmd					= ENABLE;

	serial->CfgRx.DmaChannel  = DMA_Channel_4;
	serial->CfgRx.DmaStream 	= DMA2_Stream5;
	serial->CfgRx.FifoSize 	= 200;
	serial->CfgRx.CfgNvic.NVIC_IRQChannel 					= DMA2_Stream5_IRQn;
	serial->CfgRx.CfgNvic.NVIC_IRQChannelPreemptionPriority	= 1;
	serial->CfgRx.CfgNvic.NVIC_IRQChannelSubPriority		= 1;
	serial->CfgRx.CfgNvic.NVIC_IRQChannelCmd				= ENABLE;

	serial->CfgTx.DmaChannel 	= DMA_Channel_4;
	serial->CfgTx.DmaStream  	= DMA2_Stream7;
	serial->CfgTx.FifoSize   	= 200;
	serial->CfgTx.BuffSize   	= 100;
	serial->CfgTx.CfgNvic.NVIC_IRQChannel 					= DMA2_Stream7_IRQn;
	serial->CfgTx.CfgNvic.NVIC_IRQChannelPreemptionPriority	= 1;
	serial->CfgTx.CfgNvic.NVIC_IRQChannelSubPriority		= 1;
	serial->CfgTx.CfgNvic.NVIC_IRQChannelCmd				= ENABLE;
}

3.2.2串口初始化

/**
***************************************************
* @brief   bsp_uart_init
* @note    Serial初始化,完成端口IO,中断及DMA的初始化工作
* @param   serial   	指向串口参数
* @retval  0         成功
*          1         申请内存失败
* @data    2021.07.01
* @auth    WXL
* @his     1.0.0.0     2021.07.01     WXL
* 				create
***************************************************
**/
INT8U bsp_uart_init(SerialTypeDef* serial)
{
	if(bsp_usart_DMACfg(serial) == 1)
		return 1;
	//IO初始化
	bsp_uart_IOCfg(serial);
	//串口参数初始化
	bsp_usart_UartInit(serial);
	//中断配置初始化
	bsp_usart_NVICCfg(serial);
	return 0;
}

3.2.3串口发送函数

/**
***************************************************
* @brief   bsp_uart_Transmittx
* @note    串口发送数据
* @param   serial   	指向串口参数
* @retval  0         	成功
*          1         	DMA繁忙,未发送。
* @data    2021.07.01
* @auth    WXL
* @his     1.0.0.0     2021.07.01     WXL
* 				create
***************************************************
**/
INT8U bsp_uart_Transmit(SerialTypeDef* Uartx)
{
    INT8U count = 0;

    //DMA发送繁忙,不进行操作。
	if(DMA_GetCurrDataCounter(Uartx->CfgTx.DmaStream)!= 0)
		return 1;

	if(Uartx->CfgTx.Fifo->CntUsed == 0)
		return 0;

	if(Uartx->CfgTx.Fifo->CntUsed > Uartx->CfgTx.BuffSize)
	{
		count = Uartx->CfgTx.BuffSize;
	}
	else
		count = Uartx->CfgTx.Fifo->CntUsed;
	//将数据从FIFO中拷贝到DMA的发送缓冲区,重启DMA。
	func_fifo_Pull(Uartx->CfgTx.Fifo, count, Uartx->CfgTx.Buff);
	DMA_Cmd(Uartx->CfgTx.DmaStream,DISABLE);
	while (DMA_GetCmdStatus(Uartx->CfgTx.DmaStream) != DISABLE)
	{}
	DMA_SetCurrDataCounter(Uartx->CfgTx.DmaStream,count);
	DMA_Cmd(Uartx->CfgTx.DmaStream, ENABLE);
    return 0;
}

3.3中断函数

3.3.1DMA发送中断

/**
***************************************************
  * @brief   DMA2_Stream7_IRQHandler
  * @note    DMA2_Stream7的中断函数。    	USART1_TX
  * @param   NONE
  * @retval  NONE
  * @data    2021.01.20
  * @auth    WXL
  * @his     1.0.0.1     2021.01.20     WXL
  * 		  新建文件
***************************************************
**/
void DMA2_Stream7_IRQHandler()
{
	if(DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7))
	{
		DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_FEIF7 | DMA_FLAG_DMEIF7 | DMA_FLAG_TEIF7 | DMA_FLAG_HTIF7 | DMA_FLAG_TCIF7);
		bsp_uart_Transmit(&Serial1);
	}
}

3.3.2DMA接收中断

/**
***************************************************
  * @brief   DMA2_Stream5_IRQHandler
  * @note    DMA2_Stream5的中断函数。  	USART1_RX
  * @param   NONE
  * @retval  NONE
  * @data    2021.01.20
  * @auth    WXL
  * @his     1.0.0.1     2021.01.20     WXL
  * 		  新建文件
***************************************************
**/
void DMA2_Stream5_IRQHandler(void)
{
	if(DMA_GetITStatus(DMA2_Stream5,DMA_IT_TCIF5))
	{
		DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5 | DMA_FLAG_TCIF5);
		bsp_uart_rx_callback(&Serial1,1);
	}
}

3.3.3串口中断

/**
***************************************************
  * @brief   USART1_IRQHandler
  * @note    串口1中断函数,用于处理接收完成
  * @param   NONE
  * @retval  NONE
  * @data    2021.01.20
  * @auth    WXL
  * @his     1.0.0.1     2021.01.20     WXL
  * 		  新建文件
***************************************************
**/
void USART1_IRQHandler(void)
{
    INT16U data = 0;
	if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
    {
        //清除IDLE标志位
        data = USART1->SR;
        data = USART1->DR;
        bsp_uart_rx_callback(&Serial1,0);
    }
}

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-16 11:27:52  更:2021-07-16 11:28:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 23:45:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码