如何用纯C语言结合查理复用在ATmega328P上实现Walking Zero
实现Walking Zero LED功能的解决方案
核心逻辑
Walking Zero的核心是初始状态所有LED全亮,随后依次将单个LED切换为熄灭状态并循环。既然你已经实现了Walking One(全灭后依次点亮单个LED),可以直接基于现有逻辑取反改造,无需重新搭建框架。
先明确硬件电平匹配
首先确认LED的驱动逻辑:
- 若LED为高电平点亮:亮对应引脚输出
1,灭对应0,和你给出的{1111111, 0111111,...}模式完全匹配。 - 若LED为低电平点亮:亮对应引脚输出
0,灭对应1,需对下文代码的电平输出做反向调整。
基于Walking One的改造代码示例
假设你用的是STM32 HAL库,且LED接在PB0-PB6(7个引脚):
// Walking Zero 实现代码 uint8_t led_mask = 0x01; // 初始掩码:对应第一个要熄灭的LED(PB0) const uint8_t full_on = 0x7F; // 7位全亮状态(0b1111111) while (1) { // 计算当前LED状态:全亮状态减去要熄灭的位 uint8_t current_state = full_on & (~led_mask); // 逐个设置PB0-PB6的电平(高电平点亮) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, (current_state & 0x01) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, (current_state & 0x02) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, (current_state & 0x04) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, (current_state & 0x08) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, (current_state & 0x10) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, (current_state & 0x20) ? GPIO_PIN_SET : GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, (current_state & 0x40) ? GPIO_PIN_SET : GPIO_PIN_RESET); delay(1000); // 替换为你的延时函数 // 移位掩码,循环回到第一个LED led_mask <<= 1; if (led_mask > 0x40) { // 掩码超出第7位(PB6)时重置 led_mask = 0x01; } }
简化寄存器操作版本(更高效)
直接操作GPIOB的输出寄存器,代码更简洁:
uint8_t led_mask = 0x01; GPIOB->ODR |= 0x7F; // 初始设置PB0-PB6全亮 while (1) { GPIOB->ODR = 0x7F & (~led_mask); // 熄灭对应位的LED delay(1000); led_mask <<= 1; if (led_mask > 0x40) { led_mask = 0x01; } }
适配PB0-PB3的情况
如果你实际只用了4个LED(PB0-PB3),只需修改以下参数:
full_on改为0x0F(0b1111)- 掩码循环条件改为
if (led_mask > 0x08) - 只保留PB0-PB3的电平设置代码
内容的提问来源于stack exchange,提问作者Alejandro
相关产品推荐
相关产品推荐

