PY32F003F18之DMA串口

news2024/11/18 22:53:47

PY32F003F18使用DMA串口,官方程序省FLASH,但不省内存。单片机内存够大,节省没意义,故做了修改,少用HAL库中的发送和接收,从里面抠出有用的部分,修修改改就可以了。

一、DMA串口初始化流程:

假定:串口发送引脚USART2_TX使用PA0,串口接收引脚USART2_RX使用PA1
1、使能USART2外设时钟,__HAL_RCC_USART2_CLK_ENABLE();

2、使能GPIOA时钟,__HAL_RCC_GPIOA_CLK_ENABLE();

3、将串口发送引脚USART2_TX映射到PA0

4、将串口接收引脚USART2_RX映射到PA1

5、设置串口帧格式和波特率

6、将DMA通道1映射到USART2_TX,将DMA通道2映射到USART2_RX

  __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
    HAL_SYSCFG_DMA_Req(0x0807);
    //配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
    //DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
    //DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

7、配置DMA串口发送,传输"从内存到外设"

8、配置DMA串口接收,传输"从外设到内存"

9、关闭串口接收中断

10、不使能"串口发送数据寄存器为空"产生中断

11、不使能"串口发送完成"产生中断

二、测试程序

#include "USART2.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "My_DMA.h"
#include "delay.h"

//PA0 ------> USART2_TX
//PA1 ------> USART2_RX

uint8_t USART2_TX_Buffer[USART2_TX_Buffer_Size]; //USART2发送缓冲区数组;
uint8_t USART2_TX_Buffer_Send_Index=0;          //USART2_TX_Buffer[]的发送索引值;
uint8_t USART2_TX_Buffer_Load_Index=0;          //USART2_TX_Buffer[]的装载索引值
uint8_t USART2_TX_Completed_Flag;
uint8_t USART2_TX_Overtime_Conter;//USART2发送超时计数器

uint8_t USART2_RX_Buffer[USART2_RX_Buffer_Size]; //USART2接收缓冲区数组
uint8_t USART2_RX_Buffer_StartIndex;//USART2_RX_Buffer[]的装载索引值
uint8_t USART2_RX_Buffer_EndIndex;//USART2_RX_Buffer[]的装载索引值
uint8_t USART2_RX1_Buffer[USART2_RX1_Buffer_Size]; //USART2接收缓冲区数组

void USART2_Init(uint32_t baudrate);
void Usart2Send(void);
void Usart2Receive(void);

void Usart2Send_DMA1_CH1_config(void);
void Usart2Receive_DMA1_CH2_config(void);

#if USART2Type == 0 
//函数功能:
//PA2是为USART2_TX,PA3是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
void USART2_Init(uint32_t baudrate)
{
  GPIO_InitTypeDef  GPIO_InitStructureure;
	UART_HandleTypeDef UART_HandleStructureure;

/HAL_UART_MspInit开始
  __HAL_RCC_USART2_CLK_ENABLE();//使能USART2外设时钟
  __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟

//串口引脚映射开始/
  GPIO_InitStructureure.Pin = GPIO_PIN_2;     //选择第2脚,PA2是为USART2_TX
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF4_USART2;       //将引脚复用为USART2
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA0初始化为USART2_TX

  GPIO_InitStructureure.Pin = GPIO_PIN_3;     //选择第3脚,PA3是USART2_RX
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF4_USART2;       //将引脚复用为USART2
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA1初始化为USART2_RX
//串口引脚映射结束/
/HAL_UART_MspInit结束

  UART_HandleStructureure.Instance          = USART2;              //接口为USART2
  UART_HandleStructureure.Init.BaudRate     = baudrate;            //波特率为115200bps
  UART_HandleStructureure.Init.WordLength   = UART_WORDLENGTH_8B;  //串口字长度为8
  UART_HandleStructureure.Init.StopBits     = UART_STOPBITS_1;     //串口停止位为1位
  UART_HandleStructureure.Init.Parity       = UART_PARITY_NONE;    //串口无需奇偶校验
  UART_HandleStructureure.Init.HwFlowCtl    = UART_HWCONTROL_NONE; //串口无硬件流程控制
  UART_HandleStructureure.Init.Mode         = UART_MODE_TX_RX;     //串口工作模式为发送和接收模式
	UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;//不使用自动波特率
//	UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_AUTOBAUDRATE_INIT;//使用自动波特率配置
//	UART_HandleStructureure.AdvancedInit.AutoBaudRateEnable=UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;//自动波特率使能
//	UART_HandleStructureure.AdvancedInit.AutoBaudRateMode=UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;//自动波特率模式
	HAL_UART_Init(&UART_HandleStructureure);
	//根据UART_HandleStructureure型结构初始化USART2
  __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
	HAL_SYSCFG_DMA_Req(0x0807);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
	//DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

  Usart2Send_DMA1_CH1_config();
	Usart2Receive_DMA1_CH2_config();

//  HAL_NVIC_SetPriority(USART2_IRQn, 0x01, 0);
	//设置串口2中断优先级为0x01,0无意义.USART2_IRQn表示中断源为串口2

//	__HAL_UART_ENABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
	//开启串口接收中断
	//串口接收数据时,使能"接收数据寄存器不为空"则产生中断(位RXNE=1)
	//Enable the UART Data Register not empty Interrupt

	__HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
	//关闭串口接收中断
	//串口接收数据时,不使能"接收数据寄存器不为空"则产生中断(位RXNE=0)

	__HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_TXE);
	//串口发送数据时,不使能"串口发送数据寄存器为空"产生中断(位TXE=0)
	//Disable the UART Transmit Complete Interrupt

	__HAL_UART_DISABLE_IT(&UART_HandleStructureure,UART_IT_TC);
	//串口发送数据时,不使能"串口发送完成"产生中断(位TC=1)
/在串口中断服务函数中发送数据配置结束//

//  HAL_NVIC_EnableIRQ(USART2_IRQn);
	//使能串口2中断
	//USART2_IRQn表示中断源为串口2
}
#endif

#if USART2Type ==1
//函数功能:
//PA0是为USART2_TX,PA1是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
void USART2_Init(uint32_t baudrate)
{
  GPIO_InitTypeDef  GPIO_InitStructureure;
	UART_HandleTypeDef UART_HandleStructureure;

/HAL_UART_MspInit开始
  __HAL_RCC_USART2_CLK_ENABLE();//使能USART2外设时钟
  __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟

//串口引脚映射开始/
  GPIO_InitStructureure.Pin = GPIO_PIN_0;     //选择第0脚,PA0是为USART2_TX
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF9_USART2;       //将引脚复用为USART2
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA0初始化为USART2_TX

  GPIO_InitStructureure.Pin = GPIO_PIN_1;     //选择第1脚,PA1是USART2_RX
  GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
  GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
  GPIO_InitStructureure.Alternate = GPIO_AF9_USART2;       //将引脚复用为USART2
  HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//将PA1初始化为USART2_RX
//串口引脚映射结束/
/HAL_UART_MspInit结束

  UART_HandleStructureure.Instance          = USART2;              //接口为USART2
  UART_HandleStructureure.Init.BaudRate     = baudrate;            //波特率为115200bps
  UART_HandleStructureure.Init.WordLength   = UART_WORDLENGTH_8B;  //串口字长度为8
  UART_HandleStructureure.Init.StopBits     = UART_STOPBITS_1;     //串口停止位为1位
  UART_HandleStructureure.Init.Parity       = UART_PARITY_NONE;    //串口无需奇偶校验
  UART_HandleStructureure.Init.HwFlowCtl    = UART_HWCONTROL_NONE; //串口无硬件流程控制
  UART_HandleStructureure.Init.Mode         = UART_MODE_TX_RX;     //串口工作模式为发送和接收模式
	UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;//不使用自动波特率
//	UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_AUTOBAUDRATE_INIT;//使用自动波特率配置
//	UART_HandleStructureure.AdvancedInit.AutoBaudRateEnable=UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;//自动波特率使能
//	UART_HandleStructureure.AdvancedInit.AutoBaudRateMode=UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;//自动波特率模式
	HAL_UART_Init(&UART_HandleStructureure);
	//根据UART_HandleStructureure型结构初始化USART2

  __HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
	HAL_SYSCFG_DMA_Req(0x0807);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
	//DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

  Usart2Send_DMA1_CH1_config();
	Usart2Receive_DMA1_CH2_config();

//  HAL_NVIC_SetPriority(USART2_IRQn, 0x01, 0);
	//设置串口2中断优先级为0x01,0无意义.USART2_IRQn表示中断源为串口2

//	__HAL_UART_ENABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
	开启串口接收中断
	//串口接收数据时,使能"接收数据寄存器不为空"则产生中断(位RXNE=1)
	//Enable the UART Data Register not empty Interrupt

	__HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_RXNE);
	//关闭串口接收中断
	//串口接收数据时,不使能"接收数据寄存器不为空"则产生中断(位RXNE=0)
	
	__HAL_UART_DISABLE_IT(&UART_HandleStructureure, UART_IT_TXE);
	//串口发送数据时,不使能"串口发送数据寄存器为空"产生中断(位TXE=0)
	//Disable the UART Transmit Complete Interrupt

	__HAL_UART_DISABLE_IT(&UART_HandleStructureure,UART_IT_TC);
	//串口发送数据时,不使能"串口发送完成"产生中断(位TC=1)
/在串口中断服务函数中发送数据配置结束//

//  HAL_NVIC_EnableIRQ(USART2_IRQn);
	//使能串口2中断
	//USART2_IRQn表示中断源为串口2
	
}
#endif

//重定义fputc函数
//函数功能:发送ch的值给USART2串口
int fputc(int ch, FILE *f)
{
  _HAL_UART_SendByte(USART2, (unsigned char) ch);
  while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1	
	return ch;
}

//函数功能:串口2发送一个字节
void USART2_SendByte(  unsigned char ch )
{
  _HAL_UART_SendByte(USART2, (unsigned char) ch);
  while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1
}

void Usart2Send_DMA1_CH1_config(void)
{
	DMA_HandleTypeDef hdma_usart2_tx;

	__HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
	__HAL_RCC_DMA_CLK_ENABLE();   //使能DMA时钟

	///配置串口DMA发送开始
	hdma_usart2_tx.DmaBaseAddress = DMA1;                //选择DMA1传输
  hdma_usart2_tx.Instance = DMA1_Channel1;             //DMA1通道1
  hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//DMA传输方向:从内存到外设
  hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;    //不使能外设地址增量
  hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;        //使能内存地址增量
  hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//外设数据宽度为8位
  hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;   //存储器数据宽度为8位
  hdma_usart2_tx.Init.Mode = DMA_NORMAL;                        //DMA普通模式
  hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;              //DMA通道1优先级为低
  HAL_DMA_DeInit(&hdma_usart2_tx);
	HAL_DMA_Init(&hdma_usart2_tx);
///配置串口DMA发送结束

//	HAL_DMA_ChannelMap(&hdma_usart2_tx,DMA_CHANNEL_MAP_USART2_TX);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
}

void Usart2Receive_DMA1_CH2_config(void)
{
	DMA_HandleTypeDef hdma_usart2_rx;

	__HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
	__HAL_RCC_DMA_CLK_ENABLE();   //使能DMA时钟

  hdma_usart2_rx.DmaBaseAddress = DMA1;                //选择DMA1传输
  hdma_usart2_rx.Instance = DMA1_Channel2;             //DMA1通道2
//	HAL_DMA_ChannelMap(&hdma_usart2_rx,DMA_CHANNEL_MAP_USART2_RX);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

	///配置串口DMA接收开始
  hdma_usart2_rx.DmaBaseAddress = DMA1;                //选择DMA1传输
  hdma_usart2_rx.Instance = DMA1_Channel2;             //DMA1通道2
  hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;//DMA传输方向:从外设到内存
  hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;    //不使能外设地址增量
  hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;        //使能内存地址增量
  hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度为8位
  hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    //存储器数据宽度为8位
  hdma_usart2_rx.Init.Mode = DMA_NORMAL;                         //DMA普通模式
  hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;               //DMA通道2优先级为低
	HAL_DMA_DeInit(&hdma_usart2_rx);
	HAL_DMA_Init(&hdma_usart2_rx);
///配置串口DMA接收结束
//	HAL_DMA_ChannelMap(&hdma_usart2_rx,DMA_CHANNEL_MAP_USART2_RX);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

	__HAL_DMA_DISABLE(&hdma_usart2_rx);
	//将"DMA通道x配置寄存器DMA_CCRx"中的EN=0,DMA通道x不使能
//	My_DMA_SetConfig(&hdma_usart2_rx,(uint32_t)&USART2->DR,(uint32_t)&USART2_RX_Buffer,USART2_RX_Buffer_Size);
	My_DMA1_SetConfig(DMA1_Channel2,(uint32_t)&USART2->DR,(uint32_t)&USART2_RX_Buffer,USART2_RX_Buffer_Size,0);
	__HAL_DMA_ENABLE(&hdma_usart2_rx);
	//将"DMA通道x配置寄存器DMA_CCRx"中的EN=1,DMA通道x使能

	_HAL_UART_CLEAR_FLAG(USART2,UART_FLAG_RXNE);
	SET_BIT(USART2->CR3, USART_CR3_DMAR);
	//将"串口控制寄存器3(USART_CR3)中的DMAR位"置1,接收时使能DMA
		
	USART2_RX_Buffer_StartIndex=USART2_RX_Buffer_Size-_HAL_DMA_Transfer_Number_Get(DMA1_Channel2);//读DMA1通道2剩余空间
	USART2_RX_Buffer_EndIndex=USART2_RX_Buffer_StartIndex;
}

//函数功能:将USART2_TX_Buffer[]中的字符串通过"DMA通道1"写入串口发送寄存器
void Usart2Send1(void)
{
	DMA_HandleTypeDef hdma_usart2_tx;

	///配置串口DMA发送开始
	hdma_usart2_tx.DmaBaseAddress = DMA1;                //选择DMA1传输
  hdma_usart2_tx.Instance = DMA1_Channel1;             //DMA1通道1
  hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//DMA传输方向:从内存到外设

  __HAL_DMA_DISABLE(&hdma_usart2_tx);
	My_DMA_SetConfig(&hdma_usart2_tx, (uint32_t)&USART2_TX_Buffer,(uint32_t)&USART2->DR,strlen( (char*)USART2_TX_Buffer ));
	__HAL_DMA_ENABLE(&hdma_usart2_tx);
	//将"DMA通道x配置寄存器DMA_CCRx"中的EN=1,通道x使能
	_HAL_UART_CLEAR_FLAG(USART2,UART_FLAG_TC);
	SET_BIT(USART2->CR3, USART_CR3_DMAT);
	//将"串口控制寄存器3(USART_CR3)中的DMAT位"置1,发送时使能DMA

	while( __HAL_DMA_GET_FLAG(&hdma_usart2_tx,DMA_FLAG_TC1) == RESET)
	{//等待"DMA通道1"传输完成
	}
	__HAL_DMA_CLEAR_FLAG(DMA1_Channel1,DMA_FLAG_TC1);
	//将"DMA中断标志位清除寄存器DMA_IFCR"中的CTCIF1=0,通道1传输完成标志清零
}

//函数功能:将USART2_TX_Buffer[]中的字符串通过"DMA通道1"写入串口发送寄存器
void Usart2Send(void)
{
  _HAL_DMA_DISABLE(DMA1_Channel1);
	//将"DMA通道1配置寄存器DMA_CCR1"中EN=0,DMA通道1不使能
	My_DMA1_SetConfig(DMA1_Channel1,(uint32_t)&USART2_TX_Buffer,(uint32_t)&USART2->DR,strlen( (char*)USART2_TX_Buffer),1);
	_HAL_DMA_ENABLE(DMA1_Channel1);
	//将"DMA通道1配置寄存器DMA_CCR1"中的EN=1,通道1使能
	_HAL_UART_CLEAR_FLAG(USART2,UART_FLAG_TC);
	SET_BIT(USART2->CR3, USART_CR3_DMAT);
	//将"串口控制寄存器3(USART_CR3)中的DMAT位"置1,发送时使能DMA

	while( __HAL_DMA_GET_FLAG(DMA1,DMA_FLAG_TC1) == RESET)
	{//等待"DMA通道1"传输完成
	}
	__HAL_DMA_CLEAR_FLAG(DMA1_Channel1,DMA_FLAG_TC1);
	//将"DMA中断标志位清除寄存器DMA_IFCR"中的CTCIF1=0,通道1传输完成标志清零
}

//函数功能:
//将"串口接收寄存器"通过"DMA1通道2"写入USART2_RX_Buffer[]
//接收完成后,将接收到的有效数据拷贝到USART2_RX1_Buffer[]中
void Usart2Receive(void)
{
	uint8_t i;
	uint8_t len_New;
	uint8_t len_Old;

	len_New=_HAL_DMA_Transfer_Number_Get(DMA1_Channel2);//读"DMA1通道2"剩余空间
	len_Old=len_New;
	USART2_RX_Buffer_EndIndex=USART2_RX_Buffer_Size-len_Old;
	if(USART2_RX_Buffer_StartIndex!=USART2_RX_Buffer_EndIndex)//发现新数据
	{
	  for(i=0;i<10;i++)//查询是否接收完成
	  {
		  delay_us(100);
		  len_New=_HAL_DMA_Transfer_Number_Get(DMA1_Channel2);//读DMA1通道2剩余空间
		  if(len_New!=len_Old)//接收没有完成
		  {
			  len_Old=len_New;
			  i=0;
		  }
		  else//接收超时,表示DMA接收完成
			{
		    USART2_RX_Buffer_EndIndex=USART2_RX_Buffer_Size-len_Old;
		    //记录尾部
		    for(i=0;USART2_RX_Buffer_StartIndex!=USART2_RX_Buffer_EndIndex;)
		    {//将接收到的数据保存到USART2_RX1_Buffer[]中;
			    USART2_RX1_Buffer[i]=USART2_RX_Buffer[USART2_RX_Buffer_StartIndex];
			    i++;
			    USART2_RX_Buffer_StartIndex++;
		    }
		    USART2_RX1_Buffer[i]='\0';

				i=11;//接收完成
			}
	  }

	  strcpy((char*)USART2_TX_Buffer,(char*)USART2_RX1_Buffer);
	  Usart2Send();//将接收到的数据回传

    Usart2Receive_DMA1_CH2_config();//重新初始化串口到DMA接收
	}
}
#ifndef __USART2_H
#define __USART2_H

#include "py32f0xx_hal.h"

#define USART2Type  1  //

#define _HAL_UART_SendByte(__INSTANCE__, __DATA__) (__INSTANCE__)->DR = ( (__DATA__) & (uint16_t)0x01FF );
//将(__DATA__)写入串口发送缓冲区

#define _HAL_UART_ReceiveByte(__INSTANCE__) ( (uint16_t)( (__INSTANCE__)->DR & (uint16_t)0x01FF) )
//读串口接收缓冲区

#define _HAL_UART_GET_FLAG(__INSTANCE__, __FLAG__) ( ( (__INSTANCE__)->SR & (__FLAG__) ) == (__FLAG__) )
//读串口中断标志位
//(__FLAG__)=UART_IT_RXNE,读"串口接收寄存器为非空时产生的中断标志位"
//(__FLAG__)=UART_IT_PE,读"串口奇偶校验错误产生的中断标志位"
//(__FLAG__)=UART_IT_ERR,读"帧错误、噪音错误和溢出错误时产生的中断标志位"
//(__FLAG__)=UART_IT_TXE时,读"串口发送寄存器为空产生的中断标志位"
//(__FLAG__)=UART_IT_TC时,读"发送完成产生的中断标志位"

#define _HAL_UART_CLEAR_FLAG(__INSTANCE__, __FLAG__) ( (__INSTANCE__)->SR = ~(__FLAG__) )
//清除串口中断标志位
//(__FLAG__)=UART_IT_RXNE,清除"串口接收寄存器为非空时产生的中断标志位"
//(__FLAG__)=UART_IT_PE,清除"串口奇偶校验错误产生的中断标志位"
//(__FLAG__)=UART_IT_ERR,清除"帧错误、噪音错误和溢出错误时产生的中断标志位"
//(__FLAG__)=UART_IT_TXE时,清除"串口发送寄存器为空产生的中断标志位"
//(__FLAG__)=UART_IT_TC时,清除"发送完成产生的中断标志位"

#define _HAL_UART_ENABLE_IT(__INSTANCE__, __INTERRUPT__)   ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__INSTANCE__)->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
                                                           (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__INSTANCE__)->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
                                                           ((__INSTANCE__)->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
//设置串口中断使能位
//(__INTERRUPT__)=UART_IT_RXNE,设置"串口接收寄存器为非空"时,使其产生中断
//(__INTERRUPT__)=UART_IT_PE,设置"串口奇偶校验错误"时,使其产生中断
//(__INTERRUPT__)=UART_IT_ERR,设置"帧错误、噪音错误和溢出错误"时,使其产生中断
//(__INTERRUPT__)=UART_IT_TXE时,设置"串口发送寄存器为空"时,使其产生中断
//(__INTERRUPT__)=UART_IT_TC时,设置"串口发送寄存器发送完成"时,使其产生中断

#define _HAL_UART_DISABLE_IT(__INSTANCE__, __INTERRUPT__)  ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__INSTANCE__)->CR1 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
                                                           (((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__INSTANCE__)->CR2 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
                                                           ((__INSTANCE__)->CR3 &= ~ ((__INTERRUPT__) & UART_IT_MASK)))
//设置串口中断不使能
//(__INTERRUPT__)=UART_IT_RXNE,设置"串口接收寄存器为非空"时,不使其产生中断
//(__INTERRUPT__)=UART_IT_PE,设置"串口奇偶校验错误"时,不使其产生中断
//(__INTERRUPT__)=UART_IT_ERR,设置"帧错误、噪音错误和溢出错误"时,不使其产生中断
//(__INTERRUPT__)=UART_IT_TXE时,设置"串口发送寄存器为空"时,不使其产生中断
//(__INTERRUPT__)=UART_IT_TC时,设置"串口发送寄存器发送完成"时,不使其产生中断


#define USART2_TX_Buffer_Size 		      15
extern uint8_t USART2_TX_Buffer[USART2_TX_Buffer_Size];
extern uint8_t USART2_TX_Buffer_Send_Index;//USART2_TX_Buffer[]的发送索引值;
extern uint8_t USART2_TX_Buffer_Load_Index;//USART2_TX_Buffer[]的装载索引值
extern uint8_t USART2_TX_Completed_Flag;
extern uint8_t USART2_TX_Overtime_Conter;//USART2发送超时计数器

#define USART2_RX_Buffer_Size 		      125
extern  uint8_t USART2_RX_Buffer[USART2_RX_Buffer_Size]; //USART2接收缓冲区数组
extern uint8_t USART1_RX_Buffer_StartIndex;//USART1_RX_Buffer[]的装载索引值
extern uint8_t USART1_RX_Buffer_EndIndex;//USART1_RX_Buffer[]的装载索引值

#define USART2_RX1_Buffer_Size 		      125
extern uint8_t USART2_RX1_Buffer[USART2_RX1_Buffer_Size]; //USART2接收缓冲区数组

extern void USART2_Init(uint32_t baudrate);
extern void Usart2Send(void);
extern void Usart2Receive(void);
#endif /* __USART2_H */
#include "My_DMA.h"

void My_DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
void My_DMA1_SetConfig(DMA_Channel_TypeDef *instance, uint32_t srcAddress, uint32_t dstAddress, uint32_t dataLength,uint8_t direction);

#define _HAL_DMA_CLEAR_FLAG(__INSTANCE__, __FLAG__) ( (__INSTANCE__)->IFCR |= (__FLAG__) )
//清除串口中断标志位
//(__FLAG__)=0x01,CGIF1=1,清除"通道1全局中断标志"
//(__FLAG__)=0x10,CGIF2=1,清除"通道2全局中断标志"
//(__FLAG__)=0x100,CGIF3=1,清除"通道3全局中断标志"

//SrcAddress:源数据地址
//DstAddress:目的数据地址
//DataLength:传输数据长度
void My_DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  /* Clear all flags */
	if(hdma->Instance==DMA1_Channel1) hdma->ChannelIndex=0x01;
	if(hdma->Instance==DMA1_Channel2) hdma->ChannelIndex=0x04;
	if(hdma->Instance==DMA1_Channel3) hdma->ChannelIndex=0x08;

  hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
	//将"DMA中断标志位清除寄存器DMA_IFCR"中的CGIFx设置为1,将DMA通道x全局中断标志清零

  /* Configure DMA Channel data length */
  hdma->Instance->CNDTR = DataLength;//传输数据长度

  /* Memory to Peripheral */
  if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)//从内存向外设传输
  {
    /* Configure DMA Channel destination address */
    hdma->Instance->CPAR = DstAddress;//目的数据地址

    /* Configure DMA Channel source address */
    hdma->Instance->CMAR = SrcAddress;//源数据地址
  }
  /* Peripheral to Memory */
  else//从外设向内存传输
  {
    /* Configure DMA Channel source address */
    hdma->Instance->CPAR = SrcAddress;//源数据地址

    /* Configure DMA Channel destination address */
    hdma->Instance->CMAR = DstAddress;//目的数据地址
  }
}


//srcAddress:源数据地址
//dstAddress:目的数据地址
//dataLength:传输数据长度
//direction>0,从内存向外设传输;direction=0,从外设向内存传输
void My_DMA1_SetConfig(DMA_Channel_TypeDef *instance, uint32_t srcAddress, uint32_t dstAddress, uint32_t dataLength,uint8_t direction)
{
	uint8_t ChannelIndex;
  /* Clear all flags */
	if(instance==DMA1_Channel1) ChannelIndex=0x01;
	if(instance==DMA1_Channel2) ChannelIndex=0x04;
	if(instance==DMA1_Channel3) ChannelIndex=0x08;

  DMA1->IFCR = (DMA_ISR_GIF1 << ChannelIndex);
	//将"DMA中断标志位清除寄存器DMA_IFCR"中的CGIFx设置为1,将DMA通道x全局中断标志清零

  /* Configure DMA Channel data length */
  instance->CNDTR = dataLength;//传输数据长度

  /* Memory to Peripheral */
  if( direction )//从内存向外设传输
  {
    /* Configure DMA Channel destination address */
    instance->CPAR = dstAddress;//目的数据地址

    /* Configure DMA Channel source address */
    instance->CMAR = srcAddress;//源数据地址
  }
  /* Peripheral to Memory */
  else//从外设向内存传输
  {
    /* Configure DMA Channel source address */
    instance->CPAR = srcAddress;//源数据地址

    /* Configure DMA Channel destination address */
    instance->CMAR = dstAddress;//目的数据地址
  }
}
#ifndef __My_DMA_H
#define __My_DMA_H

#include "py32f0xx_hal.h"

#define _HAL_DMA_ENABLE(__INSTANCE__)        ((__INSTANCE__)->CCR |= DMA_CCR_EN)
//将"DMA通道x配置寄存器DMA_CCRx"中EN=1,DMA通道x使能

#define _HAL_DMA_DISABLE(__INSTANCE__)       ((__INSTANCE__)->CCR &= ~DMA_CCR_EN)
//将"DMA通道x配置寄存器DMA_CCRx"中EN=0,DMA通道x不使能

#define _HAL_DMA_Transfer_Number_Get(__INSTANCE__)       ( (__INSTANCE__)->CNDTR )
//读DMA1通道x剩余空间

extern void My_DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
extern void My_DMA1_SetConfig(DMA_Channel_TypeDef *instance, uint32_t srcAddress, uint32_t dstAddress, uint32_t dataLength,uint8_t direction);
#endif /* __My_DMA_H */
#include "py32f0xx_hal.h"
#include "SystemClock.h"
#include "delay.h"
#include "LED.h"
#include "USART2.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "SystemClock.h"

const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";

int main(void)
{
	HSE_Config();
//	HAL_Init();//systick初始化
  delay_init();
	HAL_Delay(1000);

	USART2_Init(115200);
//PA0是为USART2_TX,PA1是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
//	printf("%s",CPU_Reset_REG);
	strcpy((char*)USART2_TX_Buffer,CPU_Reset_REG);
	Usart2Send();

	TIM1_LED_Init();
	TIM3_LED_Init();
	TIM_LED_Init();


  while (1)
  {
		delay_ms(100);
		Usart2Receive();
//	  strcpy((char*)USART2_TX_Buffer,"A234567890\r\n");
//	  Usart2Send();
  }
}

三、测试结果

 四、不用HAL库DMA函数的目的

因为HAL库的DMA传输函数,需要将UART_HandleTypeDef,DMA_HandleTypeDef结构型数据申请为全局变量,才可以使用,太浪费内存了。
UART_HandleTypeDef UART_HandleStructureure;
DMA_HandleTypeDef hdma_usart2_tx;
DMA_HandleTypeDef hdma_usart2_rx;

实在太浪费了。
贴出官方的测试代码,以示如下:

#include "USART2.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()

//PA0 ------> USART2_TX
//PA1 ------> USART2_RX
UART_HandleTypeDef UART_HandleStructureure;
DMA_HandleTypeDef hdma_usart2_tx;
DMA_HandleTypeDef hdma_usart2_rx;

uint8_t aTxBuffer[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
uint8_t aRxBuffer[12] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

void USART2_Init(uint32_t baudrate);
void USART2_Work(void);

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
	GPIO_InitTypeDef  GPIO_InitStructureure;

	if(huart->Instance==USART2)
	{
    __HAL_RCC_USART2_CLK_ENABLE();//使能USART2外设时钟
    __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
		__HAL_RCC_SYSCFG_CLK_ENABLE();//使能RCC外设时钟
		__HAL_RCC_DMA_CLK_ENABLE();   //使能DMA时钟

//串口引脚映射开始/
    GPIO_InitStructureure.Pin = GPIO_PIN_0;     //选择第0脚,PA0是为USART2_TX
    GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
    GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
    GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    GPIO_InitStructureure.Alternate = GPIO_AF9_USART2;       //将引脚复用为USART2
    HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	  //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	  //将PA0初始化为USART2_TX

    GPIO_InitStructureure.Pin = GPIO_PIN_1;     //选择第1脚,PA1是USART2_RX
    GPIO_InitStructureure.Mode = GPIO_MODE_AF_PP;            //复用功能推挽模式
    GPIO_InitStructureure.Pull = GPIO_PULLUP;                //引脚上拉被激活
    GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //引脚速度为最高速
    GPIO_InitStructureure.Alternate = GPIO_AF9_USART2;       //将引脚复用为USART2
    HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	  //根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	  //将PA1初始化为USART2_RX
//串口引脚映射结束/

    HAL_NVIC_SetPriority(USART2_IRQn, 0, 1);
	  //设置串口2中断优先级为0x00,1无意义
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 1);
	  //设置DMA1通道1中断优先级为0x00,1无意义
	  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 1, 0);
	  //设置DMA1通道2和通道3中断优先级为0x01,0无意义
	}
}

//函数功能:
//PA0是为USART2_TX,PA1是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
void USART2_Init(uint32_t baudrate)
{
  UART_HandleStructureure.Instance          = USART2;              //接口为USART2
  UART_HandleStructureure.Init.BaudRate     = baudrate;            //波特率为115200bps
  UART_HandleStructureure.Init.WordLength   = UART_WORDLENGTH_8B;  //串口字长度为8
  UART_HandleStructureure.Init.StopBits     = UART_STOPBITS_1;     //串口停止位为1位
  UART_HandleStructureure.Init.Parity       = UART_PARITY_NONE;    //串口无需奇偶校验
  UART_HandleStructureure.Init.HwFlowCtl    = UART_HWCONTROL_NONE; //串口无硬件流程控制
  UART_HandleStructureure.Init.Mode         = UART_MODE_TX_RX;     //串口工作模式为发送和接收模式
	UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_NO_INIT;//不使用自动波特率
//	UART_HandleStructureure.AdvancedInit.AdvFeatureInit=UART_ADVFEATURE_AUTOBAUDRATE_INIT;//使用自动波特率配置
//	UART_HandleStructureure.AdvancedInit.AutoBaudRateEnable=UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;//自动波特率使能
//	UART_HandleStructureure.AdvancedInit.AutoBaudRateMode=UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;//自动波特率模式
	HAL_UART_Init(&UART_HandleStructureure);
	//根据UART_HandleStructureure型结构初始化USART2

//	HAL_SYSCFG_DMA_Req(0x0807);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
	//DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

	hdma_usart2_tx.DmaBaseAddress = DMA1;                //选择DMA1传输
  hdma_usart2_tx.Instance = DMA1_Channel1;             //DMA1通道1
  hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//DMA传输方向:从内存到外设
  hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;    //不使能外设地址增量
  hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;        //使能内存地址增量
  hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//外设数据宽度为8位
  hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;   //存储器数据宽度为8位
  hdma_usart2_tx.Init.Mode = DMA_NORMAL;                        //DMA普通模式
  hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;              //DMA通道1优先级为低
	HAL_DMA_Init(&hdma_usart2_tx);
	__HAL_LINKDMA(&UART_HandleStructureure, hdmatx, hdma_usart2_tx);
  //这里必须要连接DMA句柄
  //令UART_HandleStructureure.hdmatx=&hdma_usart2_tx;//记录
  //令hdma_usart2_tx.Parent=&UART_HandleStructureure;//记录

  hdma_usart2_rx.DmaBaseAddress = DMA1;                //选择DMA1传输
  hdma_usart2_rx.Instance = DMA1_Channel2;             //DMA1通道2
  hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;//DMA传输方向:从外设到内存
  hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE;    //不使能外设地址增量
  hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE;        //使能内存地址增量
  hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据宽度为8位
  hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    //存储器数据宽度为8位
  hdma_usart2_rx.Init.Mode = DMA_NORMAL;                         //DMA普通模式
  hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW;               //DMA通道2优先级为低
	HAL_DMA_Init(&hdma_usart2_rx);
	__HAL_LINKDMA(&UART_HandleStructureure, hdmarx, hdma_usart2_rx);
  //连接DMA句柄
	//令UART_HandleStructureure.hdmarx=&hdma_usart2_rx;//记录
	//令hdma_usart2_rx.Parent=&UART_HandleStructureure;//记录
HAL_DMA_ChannelMap(&hdma_usart2_tx,DMA_CHANNEL_MAP_USART2_TX);
HAL_DMA_ChannelMap(&hdma_usart2_rx,DMA_CHANNEL_MAP_USART2_RX);

//	HAL_SYSCFG_DMA_Req(0x0807);
	//配置"SYSCFG配置寄存器3(SYSCFG_CFGR3)"
	//DMA1_MAP[4:0]=7,将DMA通道1映射到USART2_TX
	//DMA2_MAP[4:0]=8,将DMA通道2映射到USART2_RX

  HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
  HAL_NVIC_EnableIRQ(USART2_IRQn);
	//使能串口2中断
	//USART2_IRQn表示中断源为串口2
}

//重定义fputc函数
//函数功能:发送ch的值给USART2串口
int fputc(int ch, FILE *f)
{
  _HAL_UART_SendByte(USART2, (unsigned char) ch);
  while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1	
	return ch;
}

//函数功能:串口2发送一个字节
void USART2_SendByte(  unsigned char ch )
{
  _HAL_UART_SendByte(USART2, (unsigned char) ch);
  while( _HAL_UART_GET_FLAG(USART2,USART_SR_TC)!= SET); //等待发送完成标志位被置1
}

void USART2_Work(void)
{
    /* 通过DMA方式接收数据 */
    if (HAL_UART_Receive_DMA(&UART_HandleStructureure, (uint8_t *)aRxBuffer, 12) != HAL_OK)
    {
    }
    /* 等待接收数据完成 */
    while(HAL_UART_GetState(&UART_HandleStructureure) != HAL_UART_STATE_READY)
    {}

    /* 通过DMA方式发送数据 */
    if (HAL_UART_Transmit_DMA(&UART_HandleStructureure, (uint8_t *)aRxBuffer, 12) != HAL_OK)
    {
    }
    /* 等待发送数据完成 */
    while(HAL_UART_GetState(&UART_HandleStructureure) != HAL_UART_STATE_READY)
    {}
}

//DMA通道1负责串口发送
void DMA1_Channel1_IRQHandler(void)
{
	HAL_DMA_IRQHandler(&hdma_usart2_tx);
//若为"DMA通道x半传输中断",则清除“DMA通道x半传输中断”标志位
//若为“DMA通道x传输完成中断”,则清除“DMA通道x传输完成中断”标志位
//若为"DMA通道x传输错误中断",则不使能"DMA通道x传输完成中断"、"DMA通道x半传输中断"和"通道x传输错误中断",清除通道x全局中断标志
//  HAL_DMA_IRQHandler(UART_HandleStructureure.hdmatx);
}

//DMA通道2负责串口接收
void DMA1_Channel2_3_IRQHandler(void)
{
	HAL_DMA_IRQHandler(&hdma_usart2_rx);
//若为"DMA通道x半传输中断",则清除“DMA通道x半传输中断”标志位
//若为“DMA通道x传输完成中断”,则清除“DMA通道x传输完成中断”标志位
//若为"DMA通道x传输错误中断",则不使能"DMA通道x传输完成中断"、"DMA通道x半传输中断"和"通道x传输错误中断",清除通道x全局中断标志
//  HAL_DMA_IRQHandler(UART_HandleStructureure.hdmarx);
}

void USART2_IRQHandler(void)
{
  HAL_UART_IRQHandler(&UART_HandleStructureure);
}

耗内存,占用FLASH较小。FLASH那么大,节省没啥用。思绪再三,还是修改掉。

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

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

相关文章

未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序

1.第一步&#xff1a;下载 Microsoft Access Database Engine Microsoft Access Database Engine 2010 Redistributable Download 2.第二步: 安装下载的引擎软件 3.第三步&#xff1a;重新连接&#xff1b; 代码如下: private void button1_Click(object sender, EventArgs …

【M malloc送书第二期】朋友圈大佬都去读研了,这份备考书单我码住了!

文章目录 01 《**数据结构与算法分析**》02 《计算机网络&#xff1a;自顶向下方法》03 《现代操作系统》04 《深入理解计算机系统》01 《概率论基础教程&#xff08;原书第10版》03 《线性代数及其应用》 八九月的朋友圈刮起了一股晒通知书潮&#xff0c;频频有大佬晒出“研究…

从统计语言模型到预训练语言模型---统计语言模型

语言模型 从历史上来看&#xff0c; 自然语言处理的研究范式变化是从规则到统计&#xff0c; 从统计机器学习到基于神经网络的深度学习&#xff0c;这同时也是语言模型发展的历史。要了解语言模型的发展历史&#xff0c;首先我们需要认识什么是语言模型。语言模型的目标是建模…

RT-Thread I/O设备模型框架

I/O 设备模型框架 RT-Thread提供了一套简单的I/O设备模型框架&#xff0c;如图所示&#xff0c;它位于硬件和应用程序之间&#xff0c;共分成三层&#xff0c;从上到下分别是I/O设备管理层、设备驱动框架层、设备驱动层。 应用程序通过I/O设备管理接口获得正确的设备驱动&…

【AI视野·今日CV 计算机视觉论文速览 第249期】Tue, 19 Sep 202

AI视野今日CS.CV 计算机视觉论文速览 Tue, 19 Sep 2023 (showing first 100 of 152 entries) Totally 152 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers GEDepth: Ground Embedding for Monocular Depth Estimation Authors Xiaodong Yang…

【vue3页面展示代码】展示代码codemirror插件

技术版本&#xff1a; vue 3.2.40、codemirror 6.0.1、less 4.1.3、vue-codemirror 6.1.1、 codemirror/lang-vue 0.1.2、codemirror/theme-one-dark 6.1.2 效果图&#xff1a; 1.安装插件 yarn add codemirror vue-codemirror codemirror/lang-vue codemirror/theme-one-dar…

ChatGpt介绍和国产ChatGpt对比

1.ChatGPT是美国OpenAI研发的聊天机器人程序&#xff0c;2022年11月30日发布。ChatGPT是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过理解和学习人类的语言来进行对话。 2.ChatGPT是一种基于自然语言处理的聊天机器人程序。它使用深度学习技术&#xff0c;通过对…

A+CLUB管理人支持计划第八期 | 量创投资

免责声明 本文内容仅对合格投资者开放&#xff01; 私募基金的合格投资者是指具备相应风险识别能力和风险承担能力&#xff0c;投资于单只私募基金的金额不低于100 万元且符合下列相关标准的单位和个人&#xff1a; &#xff08;一&#xff09;净资产不低于1000 万元的单位&…

抖 X-Bongus 参数逆向 python案例实战

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 知识点&#xff1a; 动态数据抓包 requests发送请求 X-Bogus 参数逆向 开发环境: python 3.8 运行代码 pycharm 2022.3 辅助敲代码 requests pip ins…

python从入门到精通(一)

自己也有三四年的码龄了&#xff0c;目前&#xff0c;重拾起自己的博客&#xff0c;记录自己的学习笔记&#xff0c;为大家提供优质内容&#xff0c;也来巩固自己的学习内容。 很开心也成功成为了一名研究生&#xff0c;张张的研究方向是图像处理和计算机视觉这一块&#xff0c…

k8s手动下载镜像、通过容器创建镜像方法

手动下载镜像 1、首先pull镜像到本地 docker pull <镜像名称>:<标签>2、转储镜像 docker save -o /path/to/save/image.tar 3、解压 tar -xvf /path/to/save/image.tar补充 1、如果要将tar还原成镜像 docker load -i /path/to/save/image.tar或者用输入重定向…

Win10专业版开启远程桌面

Win10专业版开启远程桌面 方法一&#xff1a; 一、按“Win R”键&#xff0c;然后输入“sysdm.cpl”并按下回车键打开系统属性。 二、选择“远程”选项卡&#xff0c;在远程桌面中勾选“允许远程连接到此计算机”就可以开启远程桌面&#xff1b; 方法二&#xff1a; 一、打…

融云受邀参加 Web3.0 顶级峰会「Meta Era Summit 2023」

本周四 19:00-20:00&#xff0c;融云直播课 社交泛娱乐出海最短变现路径如何快速实现一款 1V1 视频应用&#xff1f; 欢迎点击上方小程序报名~ 9 月 12 日&#xff0c;由中国香港 Web3.0 媒体 Meta Era 主办的“Meta Era Summit 2023”在新加坡收官&#xff0c;融云作为战略合作…

Window11专业版安装Java环境

目录 一、首先准备好一个Java的环境包 二、在Windows11上双击运行此环境包 三、根据提示安装完成后&#xff0c;在此电脑上属性中搜索环境变量 四、配置环境变量、并验证 一、首先准备好一个Java的环境包 二、在Windows11上双击运行此环境包 按着要求进行下一步操作&#…

数据丢失防护工具

什么是数据丢失防护 数据丢失防护 &#xff08;DLP&#xff09; 涉及系统地识别、定位和评估具有内容和上下文感知的数据和用户活动&#xff0c;以应用策略或主动响应来防止数据丢失。静态、使用和动态数据必须受到持续监控&#xff0c;以发现企业数据存储、使用或共享方式的偏…

Docker-如何获取docker官网x86、ARM、AMD等不同架构下的镜像资源

文章目录 一、概要二、资源准备三、环境准备1、环境安装2、服务器设置代理3、注册docker账号4、配置docker源 四、查找资源1、服务器设置代理2、配置拉取账号3、查找对应的镜像4、查找不同版本镜像拉取 小结 一、概要 开发过程中经常会使用到一些开源的资源&#xff0c;比如经…

股票量化系统QTYX开启全自动实盘之路——第一弹easytrader库搭建本地自动交易环境...

搭建全自动化量化系统 股票量化交易系统QTYX最终形态是一款全自动化的量化交易系统。 接下来我们通过一个系列逐步把QTYX升级为全自动的系统。当前为第一篇&#xff1a;使用easytrader库搭建本地自动交易环境 股票的自动化交易接口在2015年之后就被管制了&#xff0c;于是对于普…

黑马JVM总结(十七)

&#xff08;1&#xff09;G1_简介 下面介绍一种Grabage one的垃圾回收器&#xff0c;在jdk9的时候称为默认的回收器&#xff0c;废除了之前的CMS垃圾回收器&#xff0c;它的内部也是并发的垃圾回收器 我们可以想到堆内存过大&#xff0c;肯定会导致回收速度变慢&#xff0c;因…

游戏开发玩法设计的重要性

玩法设计在游戏开发中非常重要&#xff0c;因为它直接影响着玩家的游戏体验和游戏的吸引力。一个精心设计的玩法可以使游戏更具趣味性、挑战性和可玩性&#xff0c;从而吸引更多的玩家并提高游戏的成功度。以下是玩法设计的重要性&#xff1a; 吸引力和沉浸感&#xff1a; 精心…

2023_Spark_实验九:Scala函数式编程部分演示

需求&#xff1a; 1、做某个文件的词频统计//某个单词在这个文件出现次数 步骤&#xff1a; 1、文件单词规律&#xff08;空格分开&#xff09; 2、单词切分 3、单词的统计 &#xff08;k,v&#xff09;->(k:单词&#xff0c;V&#xff1a;数量&#xff09; 4、打印 框…