蓝桥杯嵌入式——点亮led,lcd与led引脚冲突解决

一:点亮led

 1.led点亮原理

  led的点亮由PC8~15的高低电平控制,引脚的高低电平输入由一个SN74锁存器控制,当锁存器的PD2引脚为高电平(1)时,可以改变右端1D~8D的引脚状态,然后输入到左端控制led。

2:led配置

在软件中将手册里led对应的引脚设置为Output模式,在PGIO中将其设置为默认高电平,led默认为熄灭状态。

3.led点亮代码

void led_show(uint8_t led,uint8_t mode)
{
  HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET)   //PIOD2设置为高电平,也就是打开锁存器
  if(mode)
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led-1),GPIO_PIN_RESET);
  else
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8<<(led-1),GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET)   //PIOD2设置为低电平,也就是关闭锁存器
}

三:解决led与lcd引脚冲突

   2025年用的板子中,led8个引脚完全与lcd重合,在使用时会出现引脚冲突问题。

  led由锁存器控制电平能否输入,所以为了时其使用不被lcd影响可以先将其GPIOD-2置低。但是使用按键控制led的功能时会将其锁存器打开,此时lcd也在不断的更新引脚电平导致引脚冲突再次出现,此时可以在每一个lcd函数中加入保持led引脚输出的电平语句解决如下面中的tem,其功能就是在执行LCD函数后保持原来led引脚的电平值

step1.在lcd初始化前将锁存器设置为低电平,使得后面lcd初始化时不会改变原来led电平值

step2.去所有lcd函数中添加保持原来GPIOC值得语句

### 蓝桥杯嵌入式开发板示例代码 以下是基于蓝桥杯嵌入式竞赛中常见的 STM32G431RBT6 开发板的相关示例代码,涵盖了 LCD LED 的基本操作。这些代码可以帮助理解如何处理 LCD 显示 LED 控制之间的潜在冲突。 #### 示例 1: 初始化 GPIO 并控制 LED 此代码展示了如何初始化 GPIO 引脚并实现简单的 LED 点亮功能。 ```c #include "stm32g4xx_hal.h" void LED_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟 GPIO_InitTypeDef GPIO_InitStruct = {0}; // 配置PA5为推挽输出模式 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); } void LED_Toggle(void) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换PA5的状态 } ``` #### 示例 2: 使用 DMA 实现 LCD 数据传输 为了减少 CPU 占用率,可以利用 DMA 来完成 LCD 数据的写入操作[^1]。 ```c #include "stm32g4xx_hal.h" #include "lcd_driver.h" // 假设存在一个LCD驱动头文件 void LCD_DMA_Transfer(uint8_t *data, uint16_t length) { // 配置DMA通道用于数据传输 __HAL_RCC_DMAMUX1_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); DMA_HandleTypeDef hdma; hdma.Instance = DMA1_Channel1; hdma.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma.Init.PeriphInc = DMA_PINC_DISABLE; hdma.Init.MemInc = DMA_MINC_ENABLE; hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma.Init.Mode = DMA_NORMAL; hdma.Init.Priority = DMA_PRIORITY_HIGH; HAL_DMA_Init(&hdma); // 将DMA绑定到LCD外设地址 __HAL_LINKDMA(lcd_handle, hdmatx, hdma); // 启动DMA传输 HAL_DMA_Start(&hdma, (uint32_t)data, (uint32_t)LCD_DATA_REG, length); HAL_LCD_WriteDMALine(LINE_NUMBER); // 假设有一个函数来触发DMA传输至指定行 } ``` #### 示例 3: 解决 LCD LED 冲突的方法之一 —— 中断分离法 通过中断机制将 LCD 更新 LED 控制分开执行,从而避免两者竞争同一资源引发的问题[^2]。 ```c // 定义全局变量标志位 volatile uint8_t lcd_update_flag = 0; void TIM_IRQHandler(void) { if (__HAL_TIM_GET_FLAG(&htim2, TIM_IT_UPDATE) != RESET && \ __HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_UPDATE) != RESET) { __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE); if (!lcd_update_flag) { LED_Toggle(); // 如果当前未更新LCD,则切换LED状态 } else { lcd_update_flag = 0; // 清除LCD更新标记 } } } void Update_LCD(void) { lcd_update_flag = 1; // 设置LCD正在更新标志 LCD_DMA_Transfer(buffer_data, buffer_length); // 触发DMA传输 } ``` 以上代码片段分别实现了基础的硬件配置、高级的数据传输优化以及针对特定问题的有效解决方案。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值