使用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 */