流水灯和led
刚刚学习了流水灯+led的知识,完成代码的编写、修改和输出,最后利用ai8051u核心功能板显示输出,感觉非常不错!#include <AI8051U.H>// ==================== 硬件配置宏定义 ====================#define LED_PORT P1 // LED控制端口(P10-P17)#define LED_ON0 // 共阴极LED:0=亮,1=灭;共阳极则改为1#define LED_OFF 1// 按键引脚位掩码(P3口)- 替代P3_2/P3_3等位定义#define KEY1_MASK 0x04 // P32 = 第2位(0000 0100)#define KEY2_MASK 0x08 // P33 = 第3位(0000 1000)#define KEY3_MASK 0x10 // P34 = 第4位(0001 0000)#define KEY4_MASK 0x20 // P35 = 第5位(0010 0000)// ==================== 全局变量定义 ====================unsigned char led_mode = 1; // 模式:1=流水灯 2=单独LED 3=全亮/全灭unsigned char flow_dir = 0; // 流水灯方向:0=左→右 1=右→左unsigned char flow_pos = 0; // 流水灯当前位置(0-7)unsigned char single_led = 0; // 模式2下当前点亮的LED位bit all_led_state = 0; // 模式3下LED状态:0=全灭 1=全亮// 按键相关变量unsigned char key_value; // 按键扫描值unsigned char key_old, key_down;// 按键旧值/下降沿unsigned int key_dly = 0; // 按键消抖延时unsigned int led_dly = 0; // LED刷新延时// ==================== 函数声明 ====================void Timer0_Init(void);void Key_Scan(void);void LED_Proc(void);// ==================== 主函数 ====================void main(void){ // AI8051U核心配置 EAXFR = 1;// 使能扩展RAM访问 WTST = 0; // 关闭等待状态 CKCON = 0;// 时钟控制寄存器默认配置 // 端口模式配置:P1口推挽输出(LED),P3口准双向输入(按键) P1M0 = 0xFF; P1M1 = 0x00;// P1口推挽输出 P3M0 = 0x00; P3M1 = 0x00;// P3口准双向输入(默认上拉) // 定时器0初始化(1ms中断) Timer0_Init(); EA = 1;// 开启总中断 // 初始化LED为全灭 LED_PORT = 0xFF; while(1) { Key_Scan(); // 按键扫描 LED_Proc(); // LED逻辑处理 }}// ==================== 定时器0初始化(1ms中断) ====================void Timer0_Init(void){ TMOD |= 0x01;// 定时器0工作模式1(16位) // 11.0592MHz晶振,定时1ms初值 TH0 = 0xFC; TL0 = 0x66; ET0 = 1; // 开启定时器0中断 TR0 = 1; // 启动定时器0}// ==================== 定时器0中断服务函数(1ms) ====================void Timer0_Isr(void) interrupt 1{ // 重装初值 TH0 = 0xFC; TL0 = 0x66; // 计时变量累加 if(key_dly < 20) key_dly++; // 按键消抖20ms if(led_dly < 200) led_dly++; // LED刷新200ms}// ==================== 按键扫描函数(修正位操作问题) ====================void Key_Scan(void){ if(key_dly < 20) return;// 未到消抖时间 key_dly = 0; // 重置消抖延时 // 扫描P32-P35按键(低电平有效,通过位掩码判断) key_value = 0; if((P3 & KEY1_MASK) == 0) key_value = 1;// P32按键(模式切换) if((P3 & KEY2_MASK) == 0) key_value = 2;// P33按键(方向切换) if((P3 & KEY3_MASK) == 0) key_value = 3;// P34按键(LED加1) if((P3 & KEY4_MASK) == 0) key_value = 4;// P35按键(LED减1) // 下降沿检测:仅捕获按键按下的瞬间 key_down = key_value & (key_old ^ key_value); key_old = key_value; // 按键功能处理 switch(key_down) { case 1:// P32:模式切换(1→2→3→1) led_mode++; if(led_mode > 3) led_mode = 1; flow_pos = 0; single_led = 0; break; case 2:// P33:流水灯方向切换 flow_dir = !flow_dir; break; case 3:// P34:模式2下LED加1 if(led_mode == 2) { single_led++; if(single_led > 7) single_led = 0; } break; case 4:// P35:模式2下LED减1 if(led_mode == 2) { if(single_led == 0) single_led = 7; else single_led--; } break; default: break; }}// ==================== LED逻辑处理函数 ====================void LED_Proc(void){ if(led_dly < 200) return;// 未到刷新时间 led_dly = 0; // 重置LED延时 switch(led_mode) { // 模式1:流水灯 case 1: LED_PORT = 0xFF;// 先熄灭所有LED if(flow_dir == 0)// 左→右(P10→P17) { LED_PORT &= ~(1 << flow_pos); flow_pos++; if(flow_pos > 7) flow_pos = 0; } else// 右→左(P17→P10) { LED_PORT &= ~(1 << (7 - flow_pos)); flow_pos++; if(flow_pos > 7) flow_pos = 0; } break; // 模式2:单独LED控制 case 2: LED_PORT = 0xFF;// 熄灭所有LED LED_PORT &= ~(1 << single_led);// 点亮指定LED break; // 模式3:全亮/全灭切换 case 3: all_led_state = !all_led_state; LED_PORT = all_led_state ? 0x00 : 0xFF; break; default: led_mode = 1;// 异常模式切回流水灯 break; }}
请勿重复开贴
页:
[1]