uchar ScanKey() { uchar ret = 0; uchar key; uchar line, row; do { DDRB=0X0F; KEYBOARD = 0xf0; //扫描列 key =PINB&0XF0; if(key == 0xf0) break; //没有键按下 //有键按下 delay_nms(1); //延时消除抖动 key = PINB&0XF0; //再次读端口值 if(key == 0xf0) break; //没有键按下 switch(key) //有键按下,记录行值 { case 0x70: line = 3; break; case 0xb0: line = 2; break; case 0xd0: line = 1; break; case 0xe0: line = 0; break; } DDRB=0XF0; KEYBOARD = 0x0f; //扫描行 key = PINB&0X0F; if(key == 0x0f) break; //没有键按下 delay_nms(1); //延时消除抖动 key = PINB&0X0F; //再次读端口值 if(key == 0x0f) break; //没有键按下 switch(key) //有键按下,记录列值 { case 0x07: row = 3; break; case 0x0b: row = 2; break; case 0x0d: row = 1; break; case 0x0e: row = 0; break; } //查找对应的键值 ret = key_map[row][line]; // 行列 } while(0); return ret; }给这个代码画一个流程图
时间: 2024-04-25 18:26:10 浏览: 81
抱歉,我作为语言模型无法绘制流程图,但我能够为您描述一下这段代码的流程:
1. 初始化变量 ret、key、line 和 row 为 0
2. 进入 do-while 循环
3. 将 DDRB 设为输出模式,将 KEYBOARD 的值设为 0xf0(11110000),用于扫描列
4. 读取 PINB 的值,并将其与 0xf0 进行按位与操作,保存在 key 变量中
5. 如果 key 的值等于 0xf0,说明没有键按下,跳出循环
6. 如果 key 的值不等于 0xf0,说明有键按下,进行消抖处理,再次读取 PINB 的值,保存在 key 变量中
7. 如果 key 的值仍然等于 0xf0,说明没有键按下,跳出循环
8. 根据 key 的值,记录下当前按下键的所在行数,保存在 line 变量中
9. 将 DDRB 设为输出模式,将 KEYBOARD 的值设为 0x0f(00001111),用于扫描行
10. 读取 PINB 的值,并将其与 0x0f 进行按位与操作,保存在 key 变量中
11. 如果 key 的值等于 0x0f,说明没有键按下,跳出循环
12. 如果 key 的值不等于 0x0f,说明有键按下,进行消抖处理,再次读取 PINB 的值,保存在 key 变量中
13. 如果 key 的值仍然等于 0x0f,说明没有键按下,跳出循环
14. 根据 key 的值,记录下当前按下键的所在列数,保存在 row 变量中
15. 在 key_map 数组中查找出对应键值,保存在 ret 变量中
16. 循环结束,返回 ret 变量的值
相关问题
void SMG_CX(uchar yi,uchar er,uchar san,uchar si,uchar wu,uchar liu,uchar qi,uchar ba) { P2=((P2&0x1f)|0xc0); P0=0x01; P2&=0x1f; P2=((P2&0x1f)|0xe0); P0=tabe[yi]; P2&=0x1f; Delay(1);
这段代码看起来是一个函数定义,函数名为 SMGX,接受8个参数(yi, er, san, si, wu, liu, qi, ba),参数类型为 uchar。
在函数内部,它使用了一些操作来控制某些硬件设备(可能是涉及到数码管的显示)。具体的操作如下:
1. 将 P2 寄存器的值与 0x1F 进行按位与运算,并将结果与 0xC0 进行按位或运算,然后将结果赋值给 P2 寄存器。这个操作的目的是设置 P2 寄存器的值。
2. 将 P0 寄存器的值设置为 0x01。
3. 将 P2 寄存器的值与 0x1F 进行按位与运算,并将结果赋值给 P2 寄存器。
4. 将 P2 寄存器的值与 0x1F 进行按位与运算,并将结果与 0xE0 进行按位或运算,然后将结果赋值给 P2 寄存器。这个操作的目的是设置 P2 寄存器的值。
5. 将 P0 寄存器的值设置为 tabe[yi]。tabe 是一个数组,根据参数 yi 的值取得对应的元素。
6. 将 P2 寄存器的值与 0x1F 进行按位与运算,并将结果赋值给 P2 寄存器。
7. 延时 1 毫秒(通过调用 Delay 函数)。
这段代码只展示了函数的一部分,如果想要完整理解它的作用,还需要看到函数的后续部分。
代码解释#include <reg51.h> #define uchar unsigned char #define uint unsigned int // c0de for 7Seg MPX CA, from 0 to 9 and A to F and - // if want to use in CC, add ~ uchar code numberDisplayTable[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, 0xbf}; // delay time for notes uint code noteDelayTime[] = {64021, 64103, 64260, 64400, 64524, 64580, 64684, 64777, 64820, 64898, 64968, 65030, 65058, 65110, 65157, 65178}; sbit BEEP = P3 ^ 0; uchar keyNumber; void delay(uchar x) { uchar i; while (x--) for(i = 0; i < 120; i++); } void scanKey() { uchar tmp, k; P1 = 0x0f; delay(2); tmp = P1 ^ 0x0f; switch (tmp) { case 1: k = 0; break; case 2: k = 1; break; case 4: k = 2; break; case 8: k = 3; break; default:// no key down? return; } // set low 4 bits to 0, so place in 4 rows P1 = 0xf0; delay(2); // after button push, 11110000 will turned into XXXX0000, 1 0 in X, 3 1 in X // so we extract the 0 out tmp = (P1 >> 4) ^ 0x0f; // set 0,4,8,12 for row 0 ~ 3 switch (tmp) { case 1: k += 0; break; case 2: k += 4; break; case 4: k += 8; break; case 8: k += 12; break; default: return; } keyNumber = k; } // play sound via int0 void playNote() interrupt 1 { TH0 = noteDelayTime[keyNumber] / 256; TL0 = noteDelayTime[keyNumber] % 256; BEEP = ~BEEP; } void main() { // display - at start P0 = 0xbf; TMOD = 0x01; IE = 0x82; while (1) { // send scanner P1 = 0xf0; // if button down if (P1 != 0xf0) { scanKey(); P0 = ~numberDisplayTable[keyNumber]; // enable timer TR0 = 1; } else { // stop timer TR0 = 0; } delay(2); } }
这是一段8051单片机的程序代码,主要实现了一个数字键盘的输入和对应的数字音符的播放功能。具体来说,代码中使用了一个数字表来表示0~9和A~F以及“-”这些数字在数码管上的显示方式(使用了共阴极的7段数码管),同时也定义了一个数组来表示每个音符需要延时的时间。在主函数中,程序通过扫描数字键盘的输入来获取用户按下的键号,并根据键号找到对应的音符延时时间,然后通过定时器来实现音符的播放。同时,程序也根据键号将对应的数字在数码管上进行显示。整个程序的逻辑比较清晰,主要是通过数字表和延时时间表来实现功能。
阅读全文