本帖最后由 CListery 于 2024-7-10 15:42 编辑
第十九和二十课:
1. 通过 bdata 关键字修饰的变量可以通过 sbit 再对该变量的位起别名,这样就可以更加方便的进行单独某一位的修改
2. 数码管和 LED 的 IO 口相同时,为了避免刷新 LED 或数码管时互相影响,可以通过在定时器中断的不同的瞬间开关控制脚的高低电平实现 IO 口的复用
3. 为了程序的可移植性,不要直接使用 IO 口,而是通过重新定义的方式给 IO 口重新命名,如果更换其他引脚不同的芯片时,只需要修改定义的地方就可以了
复习心得:
1. 可以通过 #define 来直接访问数组的某一位,类似 sbit 功能
u8 SEG_DATA[2] = {0xFF, 0xFF};
#define SEG0 SEG_DATA[0]
#define SEG1 SEG_DATA[1]
2. 使用 #define 时需要注意
#define LED_EN P40 // 这里不能使用 P4^0
3. 代码
led.h
- #ifndef __LED_H
- #define __LED_H
-
- #include "stc32g.h"
- #include "stc32_stc8_usb.h"
-
- // 数码管使能
- #define SEG_ENABLE P7
- // 数码管显示控制
- #define SEG_SHOW_CONTROL P6
- // 发光二极管使能
- #define LED_ENABLE P40
- // 发光二极管显示控制
- #define LED_SHOW_CONTROL P6
-
- // 数码管显示位总控制变量
- extern u8 SEG_POS_ENABLE[8];
- // 数码管分位控制变量
- #define SPE0 SEG_POS_ENABLE[0]
- #define SPE1 SEG_POS_ENABLE[1]
- #define SPE2 SEG_POS_ENABLE[2]
- #define SPE3 SEG_POS_ENABLE[3]
- #define SPE4 SEG_POS_ENABLE[4]
- #define SPE5 SEG_POS_ENABLE[5]
- #define SPE6 SEG_POS_ENABLE[6]
- #define SPE7 SEG_POS_ENABLE[7]
-
- // 数码管显示的数据总控制变量,对应 SEG_NUM_MAP 的值
- extern u8 SEG_SHOW_DATA[8];
- // 数码管每位显示的数据变量,对应 SEG_NUM_MAP 的值
- #define SSD0 SEG_SHOW_DATA[0]
- #define SSD1 SEG_SHOW_DATA[1]
- #define SSD2 SEG_SHOW_DATA[2]
- #define SSD3 SEG_SHOW_DATA[3]
- #define SSD4 SEG_SHOW_DATA[4]
- #define SSD5 SEG_SHOW_DATA[5]
- #define SSD6 SEG_SHOW_DATA[6]
- #define SSD7 SEG_SHOW_DATA[7]
-
- // 发光二极管使能总控制变量
- extern u8 bdata LED_SHOW_DATA;
- // 发光二极管使能每位控制变量
- extern bit LSD0;
- extern bit LSD1;
- extern bit LSD2;
- extern bit LSD3;
- extern bit LSD4;
- extern bit LSD5;
- extern bit LSD6;
- extern bit LSD7;
-
- void refreshLight();
-
- #endif
复制代码
led.c
- #include "led.h"
-
- // 数码管显示数据
- u8 SEG_NUM_MAP[11] = {
- 0xC0, // 0
- 0xF9, // 1
- 0xA4, // 2
- 0xB0, // 3
- 0x99, // 4
- 0x92, // 5
- 0x82, // 6
- 0xF8, // 7
- 0x80, // 8
- 0x90, // 9
- 0xFF // 不显示
- };
-
- u8 SEG_POS_DATA[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};
-
- u8 SEG_POS_ENABLE[8] = {1, 1, 1, 1, 1, 1, 1, 1};
-
- u8 SEG_SHOW_DATA[8] = {11, 11, 11, 11, 11, 11, 11, 11};
-
- u8 bdata LED_SHOW_DATA = 0xFF;
- sbit LSD0 = LED_SHOW_DATA^0;
- sbit LSD1 = LED_SHOW_DATA^1;
- sbit LSD2 = LED_SHOW_DATA^2;
- sbit LSD3 = LED_SHOW_DATA^3;
- sbit LSD4 = LED_SHOW_DATA^4;
- sbit LSD5 = LED_SHOW_DATA^5;
- sbit LSD6 = LED_SHOW_DATA^6;
- sbit LSD7 = LED_SHOW_DATA^7;
-
- void refreshLight()
- {
- static u8 num = 0;
-
- if (num <= 7)
- {
- LED_ENABLE = 1;
- if (SEG_SHOW_DATA[num] == 11 || SEG_POS_ENABLE[num])
- {
- SEG_ENABLE = 0xFF;
- }
- else
- {
- SEG_ENABLE = SEG_POS_DATA[num];
- SEG_SHOW_CONTROL = SEG_NUM_MAP[SEG_SHOW_DATA[num]];
- }
- }
- else if (num <= 14)
- {
- SEG_ENABLE = 0xFF;
- LED_ENABLE = 0;
- LED_SHOW_CONTROL = LED_SHOW_DATA;
- }
- else
- {
- SEG_ENABLE = 0xFF;
- LED_ENABLE = 1;
- }
-
- num++;
- if (num > 15)
- {
- num = 0;
- }
- }
复制代码
key.h
- #ifndef __KEY_H_
- #define __KEY_H_
-
- #include "STC32G.H"
- #include "STC32_STC8_USB.H"
-
- extern u16 KEY_STATES[8];
-
- #define KEY1 2 // P32
- #define KEY2 3 // P33
- #define KEY3 4 // P34
- #define KEY4 5 // P35
-
- #define KEY_NORMAL 1 // 未点击
- #define KEY_CLICK 2 // 单击
- #define KEY_DOUBAL_CLICK 3 // 双击
- #define KEY_LONG_CLICK 4 // 长按
-
- #define KEY_SHAKE_TIMEOUT 30
-
- #define KEY_DOUBLE_CLICK_TIMEOUT 500 // 双击超时时间
- #define KEY_DOUBLE_CLICK_MASK 10000 // 双击检测掩码位
- #define KEY_DOUBLE_CLICK_THRESHOLD (KEY_DOUBLE_CLICK_TIMEOUT + KEY_DOUBLE_CLICK_MASK) // 双击检测阈值
-
- #define KEY_LONG_CLICK_TIMEOUT 3000
-
- void refreshKeyStatus();
- u8 readKeyStatus(u8 keyId);
-
- #endif
复制代码
key.c
- #include "key.h"
-
- #define KEY_GPIO P3
-
- u16 KEY_STATES[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-
- /**
- * 按键状态刷新
- * 每10ms执行一次
- */
- void refreshKeyStatus()
- {
- u8 pos = 0;
- for (pos = 0; pos < 8; pos++)
- {
- if (~KEY_GPIO & (1 << pos))
- {
- // 判断按键是否已经进入双击检测
- if (KEY_STATES[pos] > KEY_DOUBLE_CLICK_MASK)
- {
- // 标记为双击状态
- KEY_STATES[pos] = KEY_DOUBLE_CLICK_THRESHOLD + 1;
- }
- else
- {
- KEY_STATES[pos] += 10;
- if (KEY_STATES[pos] > KEY_LONG_CLICK_TIMEOUT)
- {
- // 标记为双击状态
- KEY_STATES[pos] = KEY_LONG_CLICK_TIMEOUT + 1;
- }
- }
- }
- else
- {
- // 30 < s < 3000 进入双击检测
- if (KEY_STATES[pos] > KEY_SHAKE_TIMEOUT && KEY_STATES[pos] < KEY_LONG_CLICK_TIMEOUT)
- {
- // 按键按下过,并且按键没有触发过长按事件
- // 进入双击超时检测
- // 11000
- KEY_STATES[pos] = KEY_DOUBLE_CLICK_THRESHOLD;
- KEY_STATES[pos] -= 10;
- }
- else if (KEY_STATES[pos] > KEY_DOUBLE_CLICK_MASK && KEY_STATES[pos] < KEY_DOUBLE_CLICK_THRESHOLD)
- {
- // 双击超时计数
- KEY_STATES[pos] -= 10;
- if (KEY_STATES[pos] <= KEY_DOUBLE_CLICK_MASK)
- {
- // 双击超时,重置计数
- KEY_STATES[pos] = 0;
- }
- }
- else
- {
- KEY_STATES[pos] = 0;
- }
- }
- }
- }
-
- u8 readKeyStatus(u8 keyId)
- {
- if (KEY_STATES[keyId] > KEY_DOUBLE_CLICK_THRESHOLD)
- {
- return KEY_DOUBAL_CLICK;
- }
- else if (KEY_STATES[keyId] > KEY_LONG_CLICK_TIMEOUT && KEY_STATES[keyId] < KEY_DOUBLE_CLICK_MASK)
- {
- return KEY_LONG_CLICK;
- }
- else if (KEY_STATES[keyId] > KEY_SHAKE_TIMEOUT && KEY_STATES[keyId] < KEY_DOUBLE_CLICK_MASK)
- {
- return KEY_CLICK;
- }
- return KEY_NORMAL;
- }
复制代码
main.c
复制代码
|