一准备工作软/硬件准备事先声明该单片机的芯片是STC89C52RC/LE52RC对应keil中的AT89C52。使用的软件是keil uVision5与AiCube-ISP-v6.96T一个常见问题的解答这一部分是关于单片机本身的。一些学习者可能已经在使用普中科技的单片机进行相关的学习了在这个过程也许会发现这样一个现象当编写好一个使用8*8LED点阵或1*8LED模块的程序时运行是正常的但是这时如果又编写了一个使用1*8LED模块或8*8LED点阵的程序时会发现在xtc中点击下载/编程后进度一直卡在“正在检测目标单片机”或者直接显示“连接超时请检查单片机”或者连接成功后单片机没有展现出预期的效果出现这个的原因可能是以下回答来自AI总而言之在涉及到关于8*8LED点阵与1*8LED模块的问题时可以尝试更换另一种连接方式来解决如果不起效果再另寻其他原因。二部分代码实验1点亮一个LED效果如下程序如下#include reg52.h /* 作用包含头文件 解释reg52.h是51单片机的寄存器定义头文件。它告诉编译器 单片机有哪些特殊功能寄存器如P0、P1、P2、P3 这些寄存器的地址是什么 可以定义位操作如sbit 类比就像C语言中的#include stdio.h包含了printf、scanf等函数的声明 */ sbit LED P2^0; /* 作用定义位变量 分解 sbitspecial bit特殊位声明用于定义单片机的某个具体引脚 LED你给这个引脚起的别名方便编程 P2^0表示P2口的第0位最低位 P2是51单片机的4个8位并行I/O口之一P0、P1、P2、P3 ^0表示第0位^1表示第1位...^7表示第7位 硬件对应在开发板上P2.0引脚通常连接着一个LED灯 注意51单片机的I/O口是准双向口既能输入也能输出 */ void main() { while(1) { LED 0;//阳极通常接到高电平这是固定的所以要想控制LED的亮灭所以只能通过 //控制LED阴极的状态来实现亮灭亮为0灭为1 } } /* 作用主函数程序入口 解释和标准C语言一样main()是程序开始执行的地方 51单片机特点main()函数永远不会返回所以通常是void类型 while(1)创建一个死循环程序在这里不断重复执行 单片机程序必须有无限循环否则程序执行完main()就结束了 括号{}内是循环体 */实验2点亮一排LED效果如下程序如下#include reg52.h void main() { while(1) { P2 0x00; /* P2是什么 P2是51单片机的第3个8位并行I/O口 它有8个引脚P2.0, P2.1, P2.2, P2.3, P2.4, P2.5, P2.6, P2.7 每个引脚可以独立控制输出0低电平或1高电平 2. 0x00是什么 0x前缀表示这是十六进制数 00十六进制数00 */ } }实验31*8LED流水灯简单实现程序如下#include reg52.h #include intrins.h // 包含_crol_循环左移函数 typedef unsigned int u16; typedef unsigned char u8; void delay(u16 t) { while(t--); } void main() { u8 led 0xFE; // 1111 1110只有P2.00低电平点亮第一个LED while(1) { P2 led; // 输出到P2口 delay(50000); // 延时 led _crol_(led, 1); // 循环左移1位 // 当移回初始状态时重置可选 if(led 0x7F) // 0111 1111只有P2.70 { delay(50000); } } }依次点亮再依次熄灭结构如下程序如下main.c#include led.h void main() { while(1) { led_server(); } }CONFIG.h#ifndef __CONFIG_H__ #define __CONFIG_H__ #include reg52.h typedef unsigned int u16; #endifdelay.c#include delay.h void delay_ms(u16 time) { u16 i,j; for (i 0; i time; i) //软件延时大约1000ms,即1秒 for (j 0; j 110; j); }DELAY.h#ifndef _DELAY_H_ #define _DELAY_H_ #include config.h //函数申明 void delay_ms(u16 time); #endifled.h#ifndef _DELAY_H_ #define _DELAY_H_ #include config.h //函数申明 void delay_ms(u16 time); #endifled.c#include led.h #define TIME 100 void led_server() { char i; for(i 0;i 8;i) { //将数字1左移i位 LED_PIN ~(1 i);// 低电平点亮 delay_ms(TIME); } for(i 7;i 0;i--) { LED_PIN | (1 i); // 高电平关闭 delay_ms(TIME); //延时1s } }任意形式的流水灯程序如下#include reg52.h typedef unsigned int u16; typedef unsigned char u8; // 在这里设置初始状态 #define INIT_PATTERN 0xEE // 可改为任意值0xAA, 0x55, 0x81等 void delay(u16 i) { while(i--); } void main(void) { u8 pattern INIT_PATTERN; bit msb; // 存储最高位 while(1) { // 显示当前状态 P2 pattern; delay(50000); // 方法1使用if判断 if(pattern 0x80) // 检查最高位是否为1 { msb 1; } else { msb 0; } // 左移 pattern pattern 1; // 如果原最高位是1最低位补1 if(msb) { pattern pattern | 0x01; } } }在宏定义那里可以有关初始值的修改实验48*8LED点阵显示显示单个字母以8*8LED点阵显示字母“O”为例效果如下程序如下/************************************************************************************** * 8*8LED点阵———显示数字实验 * 实现现象下载程序后点阵上显示数字0 注意事项一定要将J24短接片短接到GND端。 ***************************************************************************************/ #include reg51.h //此文件中定义了单片机的一些特殊功能寄存器 #includeintrins.h typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; sbit SRCLKP3^6; sbit RCLKP3^5; sbit SERP3^4; //SER是数据SRCLK是进一位信号RCLK是确定输出信号 u8 ledduan[]{0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00}; u8 ledwei[]{0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; /******************************************************************************* * 函 数 名 : delay * 函数功能 : 延时函数i1时大约延时10us *******************************************************************************/ void delay(u16 i) { while(i--); } /******************************************************************************* * 函数名 : Hc595SendByte(u8 dat) * 函数功能 : 向74HC595发送一个字节的数据 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void Hc595SendByte(u8 dat) { u8 a; SRCLK0; RCLK0; for(a0;a8;a) { SERdat7; dat1; SRCLK1; _nop_(); _nop_(); SRCLK0; } RCLK1; _nop_(); _nop_(); RCLK0; } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { u8 i; while(1) { P00x7f; for(i0;i8;i) { P0ledwei[i]; //位选 Hc595SendByte(ledduan[i]); //发送段选数据 delay(100); //延时 Hc595SendByte(0x00); //消隐 } } }回形流水灯灯会在最外层依次点亮像流水灯那样程序如下#include reg51.h #include intrins.h typedef unsigned int u16; typedef unsigned char u8; sbit SRCLK P3^6; sbit RCLK P3^5; sbit SER P3^4; u8 code row_mask[] {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}; u8 code col_mask[] {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; // 简化路径直接计算位置 u8 get_next_pos(u8 *row, u8 *col) { static u8 direction 0; // 0:右, 1:下, 2:左, 3:上 static u8 r 0, c 0; switch(direction) { case 0: // 向右移动 c; if(c 7) direction 1; // 到最右改为向下 break; case 1: // 向下移动 r; if(r 7) direction 2; // 到最下改为向左 break; case 2: // 向左移动 c--; if(c 0) direction 3; // 到最左改为向上 break; case 3: // 向上移动 r--; if(r 0) direction 0; // 到最上改为向右 break; } *row r; *col c; return 1; } void delay(u16 t) { while(t--); } void Hc595SendByte(u8 dat) { u8 i; for(i 0; i 8; i) { SER (dat 7) 1; dat 1; SRCLK 0; _nop_(); SRCLK 1; } RCLK 0; _nop_(); RCLK 1; _nop_(); RCLK 0; } void main() { u8 i, row, col; // 从左上角开始 row 0; col 0; while(1) { // 动态扫描显示当前点 for(i 0; i 8; i) { P0 row_mask[i]; // 选择行 if(i row) // 目标行 Hc595SendByte(col_mask[col]); // 点亮目标列 else Hc595SendByte(0x00); // 其他行灭 delay(5); Hc595SendByte(0x00); // 消隐 } // 延时控制流动速度 delay(1000); // 获取下一个位置 get_next_pos(row, col); // 如果回到起点稍微延时 if(row 0 col 0) delay(1000); } }实验58*8LED点阵显示英文字母A到Z效果一依次闪烁26个英文字母一个英文字母显示一段时间后切换到下一个英文字母从A循环到Z之后回到A继续循环程序如下// 完整修正版 - 字母方向一致 #include reg51.h #include intrins.h typedef unsigned int u16; typedef unsigned char u8; sbit SRCLK P3^6; sbit RCLK P3^5; sbit SER P3^4; // 修正后的字模库 - 所有字母方向一致 // 注意这里有两种可能的字模根据你的点阵实际效果选择一种 u8 code AlphabetFont[26][8] { // 版本A适用于行从上到下扫描的点阵 {0x00,0x18,0x24,0x42,0x7E,0x42,0x42,0x42}, // A {0x00,0x7C,0x42,0x42,0x7C,0x42,0x42,0x7C}, // B {0x00,0x3C,0x42,0x40,0x40,0x40,0x42,0x3C}, // C {0x00,0x7C,0x42,0x42,0x42,0x42,0x42,0x7C}, // D {0x00,0x7E,0x40,0x40,0x7C,0x40,0x40,0x7E}, // E {0x00,0x7E,0x40,0x40,0x7C,0x40,0x40,0x40}, // F {0x00,0x3C,0x42,0x40,0x4E,0x42,0x42,0x3C}, // G {0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42}, // H {0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x7C}, // I {0x00,0x1F,0x04,0x04,0x04,0x44,0x44,0x38}, // J {0x00,0x42,0x44,0x48,0x70,0x48,0x44,0x42}, // K {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7E}, // L {0x00,0x42,0x66,0x5A,0x42,0x42,0x42,0x42}, // M {0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x42}, // N {0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C}, // O {0x00,0x7C,0x42,0x42,0x7C,0x40,0x40,0x40}, // P {0x00,0x3C,0x42,0x42,0x42,0x4A,0x44,0x3A}, // Q {0x00,0x7C,0x42,0x42,0x7C,0x48,0x44,0x42}, // R {0x00,0x3C,0x42,0x40,0x3C,0x02,0x42,0x3C}, // S {0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10}, // T {0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C}, // U {0x00,0x42,0x42,0x42,0x42,0x24,0x24,0x18}, // V {0x00,0x42,0x42,0x42,0x42,0x5A,0x66,0x42}, // W {0x00,0x42,0x42,0x24,0x18,0x18,0x24,0x42}, // X {0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10}, // Y {0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x7E} // Z }; // 测试版本B行顺序反转的字模如果上面版本方向不对 u8 code AlphabetFont2[26][8] { {0x42,0x42,0x42,0x7E,0x42,0x24,0x18,0x00}, // A反转 {0x7C,0x42,0x42,0x7C,0x42,0x42,0x7C,0x00}, // B反转 {0x3C,0x42,0x40,0x40,0x40,0x42,0x3C,0x00}, // C反转 {0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x00}, // D反转 // ... 其他字母类似反转 }; // 关键尝试不同的行扫描顺序 // 版本1从上到下扫描默认 u8 code RowScan1[] {0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE}; // 版本2从下到上扫描 u8 code RowScan2[] {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}; // 版本3任意顺序扫描 u8 code RowScan3[] {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}; // 当前使用的扫描表 #define RowScan RowScan2 // 先试版本2如果不行换版本1 void delay(u16 i) { while(i--); } void Hc595SendByte(u8 dat) { u8 i; SRCLK 0; RCLK 0; for(i 0; i 8; i) { SER (dat 0x80) 7; dat 1; SRCLK 1; _nop_(); _nop_(); SRCLK 0; } RCLK 1; _nop_(); _nop_(); RCLK 0; } void main() { u8 letter 0; u16 i, scan_count; u8 direction_test 0; // 方向测试标志 while(1) { // 显示当前字母 for(scan_count 0; scan_count 50; scan_count) // 显示约0.25秒 { // 扫描显示整个字母 for(i 0; i 8; i) { P0 RowScan[i]; Hc595SendByte(AlphabetFont[letter][i]); delay(50); Hc595SendByte(0x00); } } // 切换到下一个字母 letter; if(letter 26) { letter 0; // 每轮结束后可以测试不同方向 direction_test ^ 1; // 切换方向测试 } } }效果二动态流水式的显示英文字母具体效果是显示的字母不会立即消失而是一段一段移动一个字母接着一个字母的显示就像是大街上的那种LED广告屏字不会突然消失而是从一边移动到另一边// 修正完整版 - 实现平滑流水式显示A-Z字母 #include reg51.h #include intrins.h typedef unsigned int u16; typedef unsigned char u8; sbit SRCLK P3^6; sbit RCLK P3^5; sbit SER P3^4; // 字母字模库8x8 u8 code AlphabetFont[26][8] { {0x00,0x18,0x24,0x42,0x7E,0x42,0x42,0x42}, // A {0x00,0x7C,0x42,0x42,0x7C,0x42,0x42,0x7C}, // B {0x00,0x3C,0x42,0x40,0x40,0x40,0x42,0x3C}, // C {0x00,0x7C,0x42,0x42,0x42,0x42,0x42,0x7C}, // D {0x00,0x7E,0x40,0x40,0x7C,0x40,0x40,0x7E}, // E {0x00,0x7E,0x40,0x40,0x7C,0x40,0x40,0x40}, // F {0x00,0x3C,0x42,0x40,0x4E,0x42,0x42,0x3C}, // G {0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42}, // H {0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x7C}, // I {0x00,0x1F,0x04,0x04,0x04,0x44,0x44,0x38}, // J {0x00,0x42,0x44,0x48,0x70,0x48,0x44,0x42}, // K {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7E}, // L {0x00,0x42,0x66,0x5A,0x42,0x42,0x42,0x42}, // M {0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x42}, // N {0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C}, // O {0x00,0x7C,0x42,0x42,0x7C,0x40,0x40,0x40}, // P {0x00,0x3C,0x42,0x42,0x42,0x4A,0x44,0x3A}, // Q {0x00,0x7C,0x42,0x42,0x7C,0x48,0x44,0x42}, // R {0x00,0x3C,0x42,0x40,0x3C,0x02,0x42,0x3C}, // S {0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10}, // T {0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C}, // U {0x00,0x42,0x42,0x42,0x42,0x24,0x24,0x18}, // V {0x00,0x42,0x42,0x42,0x42,0x5A,0x66,0x42}, // W {0x00,0x42,0x42,0x24,0x18,0x18,0x24,0x42}, // X {0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10}, // Y {0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x7E} // Z }; // 行扫描 u8 code RowScan[] {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}; // 显示缓冲区16列容纳2个字母 u8 display_buffer[16]; // 全局变量 u8 current_letter 0; u8 column_index 0; u8 buffer_offset 0; // 延时函数 void delay(u16 i) { while(i--); } // 74HC595发送一个字节 void Hc595SendByte(u8 dat) { u8 i; SRCLK 0; RCLK 0; for(i 0; i 8; i) { SER (dat 0x80) 7; dat 1; SRCLK 1; _nop_(); _nop_(); SRCLK 0; } RCLK 1; _nop_(); _nop_(); RCLK 0; } // 初始化显示缓冲区 void init_buffer(void) { u8 i; // 清空缓冲区 for(i 0; i 16; i) { display_buffer[i] 0x00; } // 初始化变量 current_letter 0; column_index 0; buffer_offset 0; } // 更新缓冲区每次左移一列添加新的一列 void update_buffer(void) { u8 i; // 整体左移一列 for(i 0; i 15; i) { display_buffer[i] display_buffer[i 1]; } // 获取当前字母的当前列 display_buffer[15] AlphabetFont[current_letter][column_index]; // 更新列索引 column_index; // 如果当前字母的8列都已显示切换到下一个字母 if(column_index 8) { column_index 0; current_letter; if(current_letter 26) { current_letter 0; // 从A重新开始 } } } // 显示当前缓冲区 void display_buffer_content(void) { u8 i, j; static u8 scan_count 0; // 显示多帧以保持稳定性 for(j 0; j 5; j) { // 逐行扫描 for(i 0; i 8; i) { P0 RowScan[i]; Hc595SendByte(display_buffer[i buffer_offset]); delay(2); Hc595SendByte(0x00); } } } // 主函数 void main(void) { // 初始化 init_buffer(); while(1) { // 显示当前内容 display_buffer_content(); // 每次显示后更新缓冲区左移效果 update_buffer(); // 控制滚动速度 delay(3000); } }上述两种方式速度可以自行调节补充说明这一部分是关于8*8LED点阵的简单演示要想理解代码为什么这样编写就必须深入了解该点阵的工作原理。但本人能力有限实在是无法清晰地清楚地将原理解释清楚所以在此推荐B站UP“爱上半导体”的视频具体的视频链接如下LED点阵广告屏发光的原理_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1xZ4y1Z7RP/?spm_id_from333.337.search-card.all.click还有一点就是注意在实际操作时一定要注意引脚的连接是否正确正确的引脚连接方式才会展现出正确的展示效果一种连接方式另一种连接方式不同的连接方式会产生不同的连接效果注意甄别实验6动态数码管点亮全部动态数码管显示0-7效果如下程序如下#include reg51.h typedef unsigned char u8; typedef unsigned int u16; sbit LSA P2^2; sbit LSB P2^3; sbit LSC P2^4; u8 code smguang[17]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; void delay(u16 i) { while(i--); } void display() { u16 num; for(num 0;num8;num) { switch(num) { case (0): LSA 1;LSB 1;LSC 1;break; case (1): LSA 0;LSB 1;LSC 1;break; case (2): LSA 1;LSB 0;LSC 1;break; case (3): LSA 0;LSB 0;LSC 1;break; case (4): LSA 1;LSB 1;LSC 0;break; case (5): LSA 0;LSB 1;LSC 0;break; case (6): LSA 1;LSB 0;LSC 0;break; case(7): LSA 0;LSB 0;LSC 0;break; } P0 smguang[num]; delay(100); P0 0xFF; } } void main() { while(1) { display(); P2 0x00; } }点亮前五个数码管显示“HELLO”效果展示程序如下#include reg52.h typedef unsigned int u16; typedef unsigned char u8; sbit LSAP2^2; sbit LSBP2^3; sbit LSCP2^4; u8 code smgduan[17]{0x76,0x79,0x38,0x38,0x3f,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; void delay(u16 i) { while(i--); } void DigDisplay() { u8 i; for(i0;i5;i) { switch(i) { case(0): LSA1;LSB1;LSC1; break; case(1): LSA0;LSB1;LSC1; break; case(2): LSA1;LSB0;LSC1; break; case(3): LSA0;LSB0;LSC1; break; case(4): LSA1;LSB1;LSC0; break; case(5): LSA0;LSB1;LSC0; break; case(6): LSA1;LSB0;LSC0; break; case(7): LSA0;LSB0;LSC0; break; } P0smgduan[i]; delay(100); P00x00; } } void main() { while(1) { DigDisplay(); } }实验7蜂鸣器简单的持续发声程序#include reg52.h sbit beep P2^5; // 简单延时函数 void delay_us(unsigned int us) { while(us--); } void main() { while(1) { beep ~beep; // 翻转电平 delay_us(500); // 延时约500us产生约1kHz频率 //人耳可以听到的声音频率是有范围的这里的delay就是起到调节频率的作用 } }实验8步进电机驱动步进电机模块位于P10-P13共四个引脚可以控制其驱动但是正常情况下只选择其中的一个进行使用使用将步进电机的一个引脚连接到与上述提到的四个引脚的旁边的“5V”引脚上。另一个引脚接到四个引脚的其中一个上这里以P13为例程序如下#include reg52.h sbit power P1^3; typedef unsigned int u16; void delay(u16 i) { while(i--); } void main() { while(1) { power 0; delay(100000); power 1; delay(100000); } }实验9矩阵键盘控制动态数码管启动后动态数码管的第一个会显示数字0按下矩阵按键后会对应显示S1---0 S2---1 S3---2 S4---3 S5---4 S6---5 S7---6 S8---7 S9---8 S10---9 S11---A S12---b S13---C S14---d S15---E S---F当然不是只能第一个动态数码管亮可以通过位选来选择哪个亮八个中的任意一个程序如下/************************************************************************************* * 实验现象下载程序后数码管显示0按下矩阵按键上的按键显示对应的数字 注意事项 ************************************************************************************** */ #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16; //对数据类型进行声明定义 typedef unsigned char u8; #define GPIO_DIG P0 //数码管P0.0-P0.7 #define GPIO_KEY P1 //矩阵按键8个IO管脚为P1.0-P1.7 u8 KeyValue; //用来存放读取到的键值 //数码管显示值需要翻转 u8 code smgduan[17]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//显示0~F的值 /******************************************************************************* * 函 数 名 : delay * 函数功能 : 延时函数i1时大约延时10us *******************************************************************************/ void delay(u16 i) { while(i--); } /******************************************************************************* * 函 数 名 : KeyDown * 函数功能 : 检测有按键按下并读取键值 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void KeyDown(void) { char a0; GPIO_KEY0x0f; if(GPIO_KEY!0x0f)//读取按键是否按下 { delay(1000);//延时10ms进行消抖 if(GPIO_KEY!0x0f)//再次检测键盘是否按下 { //测试列 GPIO_KEY0X0F; switch(GPIO_KEY) { case(0X07): KeyValue0;break; case(0X0b): KeyValue1;break; case(0X0d): KeyValue2;break; case(0X0e): KeyValue3;break; } //测试行 GPIO_KEY0XF0; switch(GPIO_KEY) { case(0X70): KeyValueKeyValue;break; case(0Xb0): KeyValueKeyValue4;break; case(0Xd0): KeyValueKeyValue8;break; case(0Xe0): KeyValueKeyValue12;break; } } } while((a50)(GPIO_KEY!0xf0)) //检测按键松手检测 { delay(100); a; } } /******************************************************************************* * 函 数 名 : main * 函数功能 : 主函数 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void main() { while(1) { KeyDown(); //按键判断函数 GPIO_DIG~smgduan[KeyValue]; // } }三补充说明在使用keil时应该注意keil官方软件没有汉化所以使用不会显示中文。但是有的使用者会发现如果给代码进行注释时中文注释会直接变为一串“”如下这个是可以调节的解决方法是点击edit后点击Configuration如图图中蓝色框那里选择Chinese之后的效果注释可以正常显示软件提供可能会有人需要相关的软件keilhttps://www.keil.com/https://www.keil.com/stchttps://www.stcmicro.com/cn/rjxz.htmlhttps://www.stcmicro.com/cn/rjxz.html上述的都是官方软件其中stc的无需注册可以直接下载。但是keil需要注册如果有人嫌注册麻烦的话可以私信我以提供相关的软件安装包以及部分代码再补充一个关于LED代码查询的程序。四总结感谢您阅读本文希望这篇关于单片机入门使用的分享能为您提供一些启发和帮助。如果您有任何想法、经验或建议都非常欢迎在评论区与我交流讨论或者与我私信交流。文中如有疏漏或错误之处也恳请各位读者朋友不吝指正共同完善内容。本文是在AI元宝的协助下完成后续还会不断更新、调整和补充更多相关内容努力为大家提供更有价值的技术分享。再次感谢您的支持期待与您一起进步