STM32HAL库笔记

使用CubeMX创建工程:

进入CubeMX,先选好芯片,配置时钟源、系统定时、时钟树和其他所需功能,设置工程文件名和保存位置(最好预先新建一个文件夹用来保存工程,最后生成工程

HAL库常用函数:

1.系统与时钟控制

HAL_Init();                  // 初始化HAL库
SystemClock_Config();        // 系统时钟配置(通常由CubeMX生成)
HAL_Delay(uint32_t Delay);   // 毫秒级延时
HAL_GetTick();               // 获取系统时钟滴答数

2.GPIO

GPIO初始化(通常在CubeMX里配置)

GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

读写GPIO

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
GPIO_PinState state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);(GPIO翻转函数)

3.串口通信

发送与接收:

UART_HandleTypeDef huart1;
HAL_UART_Init(&huart1);                          // 初始化UART
HAL_UART_Transmit(&huart1, data, len, timeout);  // 阻塞式发送
HAL_UART_Receive(&huart1, data, len, timeout);   // 阻塞式接收
HAL_UART_Transmit_IT(&huart1, data, len);        // 中断发送
HAL_UART_Receive_IT(&huart1, data, len);         // 中断接收
HAL_UART_Transmit_DMA(&huart1, data, len);       // 使用DMA发送数据

回调函数:

// UART发送完成回调(中断或DMA模式)
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) 
{
  if (huart->Instance == USART1) 
  {  
     //释放发送缓冲区或触发下一操作
  }
}

// UART接收完成回调(中断或DMA模式)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{
  if (huart->Instance == USART1) 
  {
    //重新调用 HAL_UART_Receive_IT() 以持续接收
  }
}

// UART错误回调(帧错误、噪声错误等)
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
  if (huart->Instance == USART1)
  {    
     //重新初始化UART或记录错误日志
  }
}

4.定时器(TIM)

PWM输出:

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);         // 启动PWM
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 50); // 设置占空比

定时器中断:

HAL_TIM_Base_Start_IT(&htim2);   // 启动定时器中断

定时器溢出中断回调:

// 定时器溢出中断回调(周期计数完成)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 
{
  if (htim->Instance == TIM2) 
  {
    /* 定时任务处理逻辑 */
    // 例如:执行周期性任务(如LED闪烁)
  }
}

// 输入捕获完成回调(捕获到边沿信号)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) 
{
  if (htim->Instance == TIM3) 
  {
    /* 捕获值处理逻辑 */
    uint32_t capture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
  }
}

5.ADC和DAC

ADC采样:

HAL_ADC_Start(&hadc1);                           // 启动ADC
HAL_ADC_PollForConversion(&hadc1, timeout);      // 阻塞等待转换完成
uint32_t value = HAL_ADC_GetValue(&hadc1);       // 获取采样值

ADC回调函数:

// ADC转换完成回调(中断或DMA模式)
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) 
{
  if (hadc->Instance == ADC1)
  {
    /* 采样数据处理逻辑 */
    uint32_t adc_value = HAL_ADC_GetValue(hadc);
  }
}

// ADC转换错误回调(过载、校准错误等)
void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc) 
{
  if (hadc->Instance == ADC1) 
  {
    /* 错误恢复逻辑 */
    HAL_ADC_Start_IT(hadc);  // 尝试重启ADC
  }
}

DAC输出:
 

HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);    // 启动DAC

SPI:

阻塞式传输:

// 全双工阻塞式传输(发送并接收数据)
HAL_StatusTypeDef HAL_SPI_TransmitReceive(
  SPI_HandleTypeDef *hspi,      // SPI句柄(如&hspi1)
  uint8_t *pTxData,             // 发送数据缓冲区
  uint8_t *pRxData,             // 接收数据缓冲区
  uint16_t Size,                // 数据长度(字节数)
  uint32_t Timeout              // 超时时间(毫秒)
);

// 仅发送数据(阻塞式)
HAL_StatusTypeDef HAL_SPI_Transmit(
  SPI_HandleTypeDef *hspi,
  uint8_t *pData,
  uint16_t Size,
  uint32_t Timeout
);

// 仅接收数据(阻塞式)
HAL_StatusTypeDef HAL_SPI_Receive(
  SPI_HandleTypeDef *hspi,
  uint8_t *pData,
  uint16_t Size,
  uint32_t Timeout
);

中断非阻塞传输:

// 启动全双工中断传输
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(
  SPI_HandleTypeDef *hspi,
  uint8_t *pTxData,
  uint8_t *pRxData,
  uint16_t Size
);

// 启动仅发送中断传输
HAL_StatusTypeDef HAL_SPI_Transmit_IT(
  SPI_HandleTypeDef *hspi,
  uint8_t *pData,
  uint16_t Size
);

// 启动仅接收中断传输
HAL_StatusTypeDef HAL_SPI_Receive_IT(
  SPI_HandleTypeDef *hspi,
  uint8_t *pData,
  uint16_t Size
);

DMA传输:

// 启动全双工DMA传输
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(
  SPI_HandleTypeDef *hspi,
  uint8_t *pTxData,
  uint8_t *pRxData,
  uint16_t Size
);

// 启动仅发送DMA传输
HAL_StatusTypeDef HAL_SPI_Transmit_DMA(
  SPI_HandleTypeDef *hspi,
  uint8_t *pData,
  uint16_t Size
);

// 启动仅接收DMA传输
HAL_StatusTypeDef HAL_SPI_Receive_DMA(
  SPI_HandleTypeDef *hspi,
  uint8_t *pData,
  uint16_t Size
);

回调函数:

// SPI传输完成回调(中断或DMA模式)
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) 
{
  if (hspi->Instance == SPI1) 
  {  // 判断SPI实例
     /* 处理接收数据 */
     // 示例:将接收数据存入全局变量
     memcpy(rx_buffer, spi_rx_data, sizeof(spi_rx_data));
  }
}

// SPI发送完成回调
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) 
{
  /* 发送完成后的逻辑 */
  // 例如:释放发送缓冲区
}

// SPI接收完成回调
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) 
{
  /* 接收完成后的逻辑 */
}

// SPI错误回调(模式错误、CRC错误等)
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) 
{
  if (hspi->Instance == SPI1) 
  {
    /* 错误处理 */
    // 例如:重新初始化SPI
       HAL_SPI_DeInit(hspi);
       HAL_SPI_Init(hspi);
  }
}

I2C:

主模式:

// 主模式阻塞式发送数据
HAL_StatusTypeDef HAL_I2C_Master_Transmit(
  I2C_HandleTypeDef *hi2c,      // I2C句柄(如&hi2c1)
  uint16_t DevAddress,          // 从设备地址(7位或10位)
  uint8_t *pData,               // 发送数据缓冲区
  uint16_t Size,                // 数据长度
  uint32_t Timeout              // 超时时间
);

// 主模式阻塞式接收数据
HAL_StatusTypeDef HAL_I2C_Master_Receive(
  I2C_HandleTypeDef *hi2c,
  uint16_t DevAddress,
  uint8_t *pData,
  uint16_t Size,
  uint32_t Timeout
);

// 主模式中断发送
HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(
  I2C_HandleTypeDef *hi2c,
  uint16_t DevAddress,
  uint8_t *pData,
  uint16_t Size
);

// 主模式中断接收
HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(
  I2C_HandleTypeDef *hi2c,
  uint16_t DevAddress,
  uint8_t *pData,
  uint16_t Size
);

从模式:

// 从模式中断接收数据
HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(
  I2C_HandleTypeDef *hi2c,
  uint8_t *pData,
  uint16_t Size
);

// 从模式中断发送数据
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(
  I2C_HandleTypeDef *hi2c,
  uint8_t *pData,
  uint16_t Size
);

回调函数:

// 主模式发送完成回调
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) 
{
  if (hi2c->Instance == I2C1) 
  {
    /* 发送完成后的逻辑 */
    // 示例:触发数据接收
    HAL_I2C_Master_Receive_IT(hi2c, DEV_ADDR, rx_data, RX_SIZE);
  }
}

// 主模式接收完成回调
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) 
{
  /* 处理接收数据 */
  // 示例:解析传感器数据
  sensor_value = (rx_data[0] << 8) | rx_data[1];
}

// 从模式发送完成回调
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) 
{
  /* 从设备发送完成处理 */
}

// 从模式接收完成回调
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) 
{
  /* 处理主设备发送的数据 */
}

// I2C错误回调(仲裁丢失、总线错误等)
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) 
{
  if (hi2c->Instance == I2C1) 
  {
    /* 错误恢复 */
    // 示例:重新初始化I2C
    HAL_I2C_DeInit(hi2c);
    HAL_I2C_Init(hi2c);
  }
}

7.中断回调函数

// 外部中断通用回调函数(需用户实现)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) 
{
  switch (GPIO_Pin) 
  {
    case GPIO_PIN_0:  
      // 处理PA0/PB0等引脚的中断
      /* 例如:按键按下触发LED翻转 */
      HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
      break;
    case GPIO_PIN_1:  
      // 处理PA1/PB1等引脚的中断
      /* 例如:传感器信号触发数据采集 */
      Start_Sensor_Read();
      break;
    // ... 其他引脚处理
  }
}

下面是常用函数的应用(都需要在CubeMX里提前配置硬件和移植各外设驱动程序):

1.实现LED闪烁

main.c 在主函数的while循环里

  while (1)
  {
     HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
	 HAL_Delay(500);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

2.简易呼吸灯

 while (1)
  {
		for(Time=0; Time<10; Time++)
		{
			for(delay=0; delay<10;delay++)
			{
				HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
				HAL_Delay(Time);
				HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
				HAL_Delay(10-Time);
			}
		}
		for(Time=10; Time>0; Time--)
		{
			for(delay=0; delay<10;delay++)
			{
				HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
				HAL_Delay(Time);
				HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
				HAL_Delay(10-Time);
			}
		}

3.按键控制LED


#define K1 HAL_GPIO_ReadPin(K1_GPIO_Port, K1_Pin)

 while (1)
 {
	if(K1 == 0)
	{
		HAL_Delay(10);//消抖
		if(K1 == 0)
	    {
		 while(K1 == 0);//当按键按下并被释放时改变LED电平状态
		 HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
	}
 }

4.定时器软件呼吸灯

/* USER CODE BEGIN PD */
#define LED(a) HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, (GPIO_PinState)a)
/* USER CODE END PD */

/* USER CODE BEGIN PV */
uint8_t PWM_Period;
uint8_t light;
uint8_t Flag;
uint16_t time_10us, time_10ms;
/* USER CODE END PV */

//改变占空比
void PWM_LED(void)
{
	if(Flag == 0) //从暗到亮
	{
		if(light < 100)
		{
			light++;
			if(light >= 100)
			Flag = 1;
		}
	}
	else          //从亮到暗
	{
		if(light > 0)
		{
			light--;
			if(light == 0)
			Flag = 0;
		}
	}
}

int main()
{

 /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);
  /* USER CODE END 2 */

  while (1)
  {
		if(time_10ms == 1)//每10ms改变一次占空比
		{
			time_10ms = 0;
			PWM_LED();
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

}

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == htim1.Instance) //10us中断一次
	{
		time_10us++;
		if(time_10us >= 1000)    //10*1000 = 10000us = 10ms
		{
			time_10us = 0;
			time_10ms = 1;
		}
		
		PWM_Period++;
		if(PWM_Period >= 100)	//1ms 设置PWM周期
			PWM_Period = 0;
		
		if(PWM_Period < light)	//输出比较 OC
			LED(0);
		else
			LED(1);
	}
}
/* USER CODE END 4 */


5.硬件PWM呼吸灯

/* USER CODE BEGIN PV */
uint8_t Flag;
uint16_t light;
uint8_t time_1ms, time_10ms;
/* USER CODE END PV */

int main(void)
{
   /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);
  /* USER CODE END 2 */
  

  while (1)
  {
		if(time_10ms == 1)//每10ms改变一次占空比
		{
			time_10ms = 0;
			
			if(Flag == 0)
			{
				light+=10;
				if(light >= 999)
				Flag = 1;
			}
			else
			{
				light-=10;
				if(light == 0)
				Flag = 0;
			}
			
		   __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, light);	
			
		}

}

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == htim1.Instance)     //定时器1触发中断
    {
			time_1ms++;
			if(time_1ms >= 10)
			{
				time_1ms = 0;
				time_10ms = 1;
			}
    }
}
/* USER CODE END 4 */

6.舵机控制

/* USER CODE BEGIN PD */
#define K1 HAL_GPIO_ReadPin(K1_GPIO_Port, K1_Pin)
#define K2 HAL_GPIO_ReadPin(K2_GPIO_Port, K2_Pin)
/* USER CODE END PD */


/* USER CODE BEGIN PV */
uint8_t SG90;
/* USER CODE END PV */

/* USER CODE BEGIN 0 */
//标准的PWM信号周期为20ms,脉宽在0.5ms至2.5ms之间变化,对应0到180度的旋转角度
void SG90Angle_Set(uint8_t Angle)
{
	__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, Angle/180.0*2000+500);	
}
/* USER CODE END 0 */


int main(void)
{ 
    /* USER CODE BEGIN 2 */
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
    /* USER CODE END 2 */


  while (1)
  {
		
			if(K1 == 0)
			{
				if(SG90 < 180)
				SG90++;
			}
			if(K2 == 0)
			{
				if(SG90 > 0)
				SG90--;
			}
			
			SG90Angle_Set(SG90);

         }
   } 
 

}

7.烟雾传感器ADC采集

/* USER CODE BEGIN PD */
#define MQ HAL_GPIO_ReadPin(MQ_GPIO_Port, MQ_Pin)//DO
/* USER CODE END PD */

/* USER CODE BEGIN PV */
float MQ_Value;
/* USER CODE END PV */


int main(void)
{

  /* USER CODE BEGIN 2 */
	OLED_Init();
  /* USER CODE END 2 */

while (1)
  {    
        //ADC采集的值为0-4095,对应引脚电压的0-3.3v
		HAL_ADC_Start(&hadc1);//开启ADC1采集
		if(HAL_ADC_PollForConversion(&hadc1, 999) == HAL_OK)//999为等待时间
		MQ_Value = HAL_ADC_GetValue(&hadc1)/4095.0*3.3;//把采集到的值赋给MQ_Value
		HAL_ADC_Stop(&hadc1);//关闭ADC1采集
		
		OLED_ShowString(0, 0, "气体浓度:", OLED_8X16);
		OLED_ShowFloatNum(80, 0, MQ_Value, 1, 1, OLED_8X16);
		
		OLED_ShowString(0, 16, "触发:", OLED_8X16);
		if(MQ == 0)
			OLED_ShowString(48, 16, "是", OLED_8X16);
		else
			OLED_ShowString(48, 16, "否", OLED_8X16);
		OLED_Update();
    
  }
   

 }

8.DHT11温湿度传感器

/* USER CODE BEGIN PV */
uint16_t time_1ms, time_500ms;
//uint16_t temp, humi;
/* USER CODE END PV */

/* USER CODE BEGIN 0 */
void Sensor_Function()
{
	DHT11_Read_Data(&temp, &humi);
	
}

void Display_Function()
{
    OLED_ShowHumi(0, 16, humi);
	OLED_ShowFloatNum(0, 0, temp, 2, 1, OLED_8X16);
	
}
/* USER CODE END 0 */



int main(void)
{
   /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);  //定时器中断开始初始化
	OLED_Init();
	DHT11_Init();
  /* USER CODE END 2 */

  while (1)
  {
		if(time_500ms == 1)//每500ms采集一次
		{
			time_500ms = 0;
			Sensor_Function();
			Display_Function();
		}
  }



}

/* USER CODE BEGIN 4 */
//定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == htim1.Instance)        //定时器1触发中断
	{
		time_1ms++;
		if(time_1ms >= 500)
		{
				time_1ms= 0;
				time_500ms = 1;
		}
	}
}
/* USER CODE END 4 */

9.串口通信

/* USER CODE BEGIN PD */
uint8_t USART2_TX_BUF[200];
#define u2_printf(...)  HAL_UART_Transmit(&huart2,USART2_TX_BUF,sprintf((char *)USART2_TX_BUF,__VA_ARGS__),0xffff)
/* USER CODE END PD */

/* USER CODE BEGIN PV */
//串口2的数据获取
uint8_t uart2_value;      //串口传的单个数据
//串口的储存数组,串口的接收时间,串口存值的数量
uint8_t uart2_buf[36],uart2_time,uart2_num;
uint8_t uart2_rx_flag;//串口的获取值的标志位
uint8_t dis_buf[36];
/* USER CODE END PV */

int main(void)
{
     /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);  //定时器中断开始初始化
	HAL_UART_Receive_IT(&huart2, &uart2_value, 1);
	OLED_Init();
    /* USER CODE END 2 */


while (1)
  {
		if(uart2_rx_flag == 1)//当接收完一帧数据
		{
			uart2_rx_flag = 0;
			
			memcpy(dis_buf, uart2_buf, sizeof(dis_buf));//把存储接收数据数组赋给定义的数组
			memset(uart2_buf, '\0', sizeof(uart2_buf));//清空存储接收数据的数组
			OLED_Clear();//清屏
		}
		
		u2_printf("Hello!");//串口发送
		OLED_ShowString(0, 0, (char *)dis_buf, OLED_8X16);//在OLED上显示接收的数据
		OLED_Update();
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
    /* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */
//定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == htim1.Instance)        //定时器1触发中断
	{
		//定时器中串口处理过程
		if(uart2_num != 0) //串口接收到数据传来
		{
			uart2_time++;       //计时开始
			if(uart2_time >= 10)//如果接收完数据后的时间大于等于10代表一帧数据接受完成
			{
				uart2_time = 0;   
				uart2_num = 0;
				uart2_rx_flag = 1;//把接收数据标志位设为1
			}
		}
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == huart2.Instance)//串口2触发中断
	{
		//获取串口2的数据,uart2_value
		HAL_UART_Receive_IT(&huart2, &uart2_value, 1);
		//将数据一个一个存储到uart2_buf中
		uart2_buf[uart2_num++] = uart2_value;		
		uart2_time = 0;//每接收存储完一个数据就开始计时
	}
}
/* USER CODE END 4 */









10.串口DMA通信

/* USER CODE BEGIN PV */
// 串口接收缓冲区
uint8_t rx_data[256] = {0};
/* USER CODE END PV */

int main(void)
{
    /* USER CODE BEGIN 2 */
	// 使用Ex函数,接收不定长数据
	HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx_data, sizeof(rx_data));
	// 关闭DMA传输过半中断(HAL库默认开启,但我们只需要接收完成中断)
	__HAL_DMA_DISABLE_IT(huart2.hdmarx, DMA_IT_HT);
	OLED_Init();
  /* USER CODE END 2 */



}

/* USER CODE BEGIN 4 */
// 不定长数据接收完成回调函数
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
		if (huart->Instance == USART2)
		{
				// 使用DMA将接收到的数据发送回去
				HAL_UART_Transmit_DMA(&huart2, rx_data, Size);
			
				if(rx_data[0] == 0xAA && rx_data[2] == 0xBB)
				{
					if(rx_data[1] == 0x01)
						HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
					if(rx_data[1] == 0x02)
						HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
				}
			
				// 重新启动接收,使用Ex函数,接收不定长数据
				HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx_data, sizeof(rx_data));
				// 关闭DMA传输过半中断(HAL库默认开启,但我们只需要接收完成中断)
				__HAL_DMA_DISABLE_IT(huart2.hdmarx, DMA_IT_HT);
		}
}
/* USER CODE END 4 */

11.ADC的DMA采集


/* USER CODE BEGIN PV */
uint16_t AD_Value[2];
/* USER CODE END PV */

int main(void)
{
     /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);
	HAL_ADCEx_Calibration_Start(&hadc1);     //校准ADC
	HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, 2); //开启ADC1DMA采集   
	OLED_Init();
    /* USER CODE END 2 */

  while (1)
  {
		OLED_ShowNum(0, 0, AD_Value[0]/4095.0*100, 4, OLED_8X16);
		OLED_ShowNum(0, 32,AD_Value[1]/4095.0*100, 4, OLED_8X16);
		OLED_Update();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

}


/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == htim1.Instance)        //定时器1触发中断
    {
			static uint16_t time;
			
			time++;
			if(time >= 100)
			{
				HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
				time = 0;
			}
    }
}
/* USER CODE END 4 */

12.外部中断(测试红外传感器触发次数)


/* USER CODE BEGIN PV */
uint16_t IR_num;
uint8_t Flag_IR;
uint8_t Flag_delay, delay_time;
/* USER CODE END PV */

int main(void)
{
    /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start_IT(&htim1);
	OLED_Init();
    /* USER CODE END 2 */

 while (1)
  {
		OLED_ShowNum(0, 32, IR_num, 3, OLED_8X16);
		OLED_Update();
		HAL_Delay(3000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
    /* USER CODE END 3 */
}

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == htim1.Instance)   //定时器1触发中断
    {

			
			if(Flag_delay)//标志位为1时开始计时
			{
				delay_time++;
				if(delay_time >= 20)//达到指定计时条件再把标志位设为0
				Flag_delay = 0;
			}
			else
				delay_time = 0;//标志位为0就不计时
    }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//GPIO中断回调函数
{
  if(GPIO_Pin == IR_Pin)//如果是红外传感器引脚引起GPIO中断
    {
	    if(HAL_GPIO_ReadPin(IR_GPIO_Port, IR_Pin) && Flag_delay == 0)
	    {
          IR_num++;
	      Flag_delay = 1;//当红外传感器触发1次把标志位设为1避免触发一次导致IR_num一直增加
		}
    }
}
/* USER CODE END 4 */



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值