本帖最后由 CListery 于 2024-8-2 16:22 编辑
记一个在 STC32G12K128 大学计划实验箱 V9.62 上遇到的问题:
在同时对 P32、P33、P34、P35 和 矩阵按键扫描时,P34会出现意外拉低的情况,设置了上拉电阻也无效,导致按键扫描程序一直扫描到 P34 为低电平
引发该问题的具体原因暂时未知,有可能是在拉低P0口时其他的电路影响到了P3口
解决方案,在扫描 P3 口的按键时将 P0 口拉高,扫描 P0 口矩阵按键时将 P3 拉高(最好排除 P30、P31 口)
第二十九集:
做一个带闹钟、时间设置、30秒提醒功能的时钟
#include <stc32g.h>
#define PRINTF_HID
#include <stc32_stc8_usb.h>
#include "adc.h"
#include "extint.h"
#include "key.h"
#include "led.h"
#include "timer.h"
#define FOSC 24000000UL // ISP 下载时需将工作频率设置为 24MHz
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; // 设置自动复位到ISP区的用户接口命令
bit FLAG_100ms = 1, FLAG_500ms = 0;
// 秒,分,时
u8 time = {0, 0, 0};
#define T_HOUR time
#define T_MINUTE time
#define T_SECOUND time
u8 preSetTime = {255, 255, 255};
#define PRE_T_HOUR preSetTime
#define PRE_T_MINUTE preSetTime
#define PRE_T_SECOUND preSetTime
bit pauseRefreshLight = 0;
u8 twinkle = 0;
bit TIME_SETTING = 0;
bit PRE_TIME_SETTING = 0;
u8 twinklePos = 0;
bit PRE_TIMEUP = 0;
void sys_init();
void refreshTIME();
void setTime(u8 tVal);
void preTimeup();
void Delay1ms(void) //@24.000MHz
{
unsigned char data i, j;
i = 24;
j = 85;
do
{
while (--j)
;
} while (--i);
}
void Delay100ms()
{
u8 i = 100;
while (--i)
{
Delay1ms();
}
}
void main()
{
char key;
// u8 keyStatus;
u8 tVal;
sys_init();
// initTimer0(0x30, 0xF8);
initTimer1(0x40, 0xA2);
initADC(0);
EA = 1;
P0M0 = 0;
P0M1 = 0;
// P3M0 = 0;
// P3M1 = 0;
P4M0 = 0;
P4M1 = 0;
P6M0 = 0;
P6M1 = 0;
P7M0 = 0;
P7M1 = 0;
// SSD0 = 0;
// SSD1 = 1;
// SSD2 = 2;
// SSD3 = 3;
// SSD4 = 4;
// SSD5 = 5;
// SSD6 = 6;
// SSD7 = 7;
// 等待 USB 完成配置
while (DeviceState != DEVSTATE_CONFIGURED)
;
while (1)
{
if (bUsbOutReady) // 当硬件接收完成上位机通过串口助手发送数据后
// 会自动将 bUsbOutReady 置 1
// 接收的数据字节保存在 OutNumber 变量总
// 接收的数据保存在 UsbOutBuffer 缓冲区
{
USB_SendData(UsbOutBuffer, OutNumber); // 使用 Usb_SendData 库函数可向上位机发送数据
// 这里的测试代码为将接收数据原样返回
usb_OUT_done(); // 处理完成接收的数据后
// 调用 usb_OUT_done 准备接收下一笔数据
}
if (FLAG_100ms)
{
FLAG_100ms = 0;
key = adcKeyRead(0);
if (key != -1)
{
tVal = -1;
printf("%d\r\n", key);
switch (key)
{
case ADC_K_0_CLICK:
case ADC_K_1_CLICK:
case ADC_K_2_CLICK:
case ADC_K_3_CLICK:
case ADC_K_4_CLICK:
case ADC_K_5_CLICK:
case ADC_K_6_CLICK:
case ADC_K_7_CLICK:
case ADC_K_8_CLICK:
case ADC_K_9_CLICK:
if (TIME_SETTING || PRE_TIME_SETTING)
{
while (queryADC(0))
{
Delay100ms();
}
tVal = key - 1;
}
break;
case ADC_K_B_CLICK:
case ADC_K_B_LONG_CLICK:
if (TIME_SETTING)
{
T_SECOUND++;
pauseRefreshLight = 0;
}
break;
case ADC_K_D_CLICK:
if (TIME_SETTING)
{
// 退出设置时间
TIME_SETTING = 0;
pauseRefreshLight = 0;
}
else if (PRE_TIME_SETTING)
{
// 退出设置闹钟
PRE_TIME_SETTING = 0;
pauseRefreshLight = 0;
}
break;
case ADC_K_A_LONG_CLICK:
// 设置时间
if (!TIME_SETTING)
{
twinklePos = 0;
TIME_SETTING = 1;
}
break;
case ADC_K_F_LONG_CLICK:
// 设置闹钟
if (!PRE_TIME_SETTING)
{
twinklePos = 0;
PRE_TIME_SETTING = 1;
}
break;
}
if (tVal != -1)
{
setTime(tVal);
}
}
// key = queryUnNormalKey();
// if (key != -1)
// {
// keyStatus = readKeyStatus(key);
// printf("%d -> %d\r\n", key, keyStatus);
// switch (key)
// {
// case KEY1:
// // A 键
// if (keyStatus == KEY_LONG_CLICK)
// {
// if (!TIME_SETTING)
// {
// twinklePos = 0;
// TIME_SETTING = 1;
// }
// }
// break;
// case KEY4:
// // D键
// if (keyStatus == KEY_CLICK)
// {
// TIME_SETTING = 0;
// pauseRefreshLight = 0;
// }
// break;
// }
// }
refreshTIME();
}
}
}
void setTime(u8 tVal)
{
if (TIME_SETTING)
{
switch (twinklePos)
{
case 0:
T_SECOUND = (T_SECOUND / 10 * 10) + tVal;
break;
case 1:
T_SECOUND = tVal * 10 + T_SECOUND % 10;
break;
case 3:
T_MINUTE = (T_MINUTE / 10 * 10) + tVal;
break;
case 4:
T_MINUTE = tVal * 10 + T_MINUTE % 10;
break;
case 6:
T_HOUR = (T_HOUR / 10 * 10) + tVal;
break;
case 7:
T_HOUR = tVal * 10 + T_HOUR % 10;
break;
}
twinklePos++;
if (twinklePos == 2 || twinklePos == 5)
{
twinklePos++;
}
else if (twinklePos == 8)
{
twinklePos = 0;
}
}
else if (PRE_TIME_SETTING)
{
switch (twinklePos)
{
case 0:
PRE_T_SECOUND = (PRE_T_SECOUND / 10 * 10) + tVal;
break;
case 1:
PRE_T_SECOUND = tVal * 10 + PRE_T_SECOUND % 10;
break;
case 3:
PRE_T_MINUTE = (PRE_T_MINUTE / 10 * 10) + tVal;
break;
case 4:
PRE_T_MINUTE = tVal * 10 + PRE_T_MINUTE % 10;
break;
case 6:
PRE_T_HOUR = (PRE_T_HOUR / 10 * 10) + tVal;
break;
case 7:
PRE_T_HOUR = tVal * 10 + PRE_T_HOUR % 10;
break;
}
twinklePos++;
if (twinklePos == 2 || twinklePos == 5)
{
twinklePos++;
}
else if (twinklePos == 8)
{
twinklePos = 0;
}
}
}
void refreshTIME()
{
if (PRE_TIME_SETTING)
{
if (PRE_T_SECOUND >= 60)
{
PRE_T_SECOUND = 0;
PRE_T_MINUTE++;
}
if (PRE_T_MINUTE >= 60)
{
PRE_T_MINUTE = 0;
PRE_T_HOUR++;
}
if (PRE_T_HOUR >= 24)
{
PRE_T_HOUR = 0;
}
// if (!pauseRefreshLight)
// {
// printf("%d - %d - %d \r\n", T_HOUR, T_MINUTE, T_SECOUND);
// }
// else
// {
// printf(" - -\r\n");
// }
SSD0 = PRE_T_SECOUND > 0 ? PRE_T_SECOUND % 10 : 0;
SSD1 = PRE_T_SECOUND > 0 ? PRE_T_SECOUND / 10 : 0;
SSD2 = SEG_DISPLAY_STAFF;
SSD3 = PRE_T_MINUTE > 0 ? PRE_T_MINUTE % 10 : 0;
SSD4 = PRE_T_MINUTE > 0 ? PRE_T_MINUTE / 10 : 0;
SSD5 = SEG_DISPLAY_STAFF;
SSD6 = PRE_T_HOUR > 0 ? PRE_T_HOUR % 10 : 0;
SSD7 = PRE_T_HOUR > 0 ? PRE_T_HOUR / 10 : 0;
}
else
{
if (T_SECOUND >= 60)
{
T_SECOUND = 0;
T_MINUTE++;
}
if (T_MINUTE >= 60)
{
T_MINUTE = 0;
T_HOUR++;
}
if (T_HOUR >= 24)
{
T_HOUR = 0;
}
// if (!pauseRefreshLight)
// {
// printf("%d - %d - %d \r\n", T_HOUR, T_MINUTE, T_SECOUND);
// }
// else
// {
// printf(" - -\r\n");
// }
SSD0 = T_SECOUND > 0 ? T_SECOUND % 10 : 0;
SSD1 = T_SECOUND > 0 ? T_SECOUND / 10 : 0;
SSD2 = SEG_DISPLAY_STAFF;
SSD3 = T_MINUTE > 0 ? T_MINUTE % 10 : 0;
SSD4 = T_MINUTE > 0 ? T_MINUTE / 10 : 0;
SSD5 = SEG_DISPLAY_STAFF;
SSD6 = T_HOUR > 0 ? T_HOUR % 10 : 0;
SSD7 = T_HOUR > 0 ? T_HOUR / 10 : 0;
if (T_SECOUND == PRE_T_SECOUND && T_MINUTE == PRE_T_MINUTE && T_HOUR == PRE_T_HOUR)
{
preTimeup();
}
}
}
void preTimeup()
{
u8 key;
PRE_TIMEUP = 1;
twinklePos = 0;
while (1)
{
if (FLAG_100ms)
{
FLAG_100ms = 0;
key = adcKeyRead(0);
if (key != -1)
{
printf("%d\r\n", key);
if (key == ADC_K_0_CLICK)
{
PRE_TIMEUP = 0;
break;
}
}
}
}
}
void t1_run(void) interrupt 3
// void t0_run() interrupt 1
{
static u8 n = 0, n100 = 0, n500 = 0;
if (TIME_SETTING || PRE_TIME_SETTING || PRE_TIMEUP)
{
refreshLight(pauseRefreshLight ? twinklePos : -1);
}
else
{
if (pauseRefreshLight)
{
SEG_ENABLE = 0xFF;
}
else
{
refreshLight(-1);
}
}
n++;
if (n % 10 == 0)
{
refreshKeyStatus();
}
if (n == 100)
{
FLAG_100ms = 1;
n100++;
n500++;
n = 0;
}
if (n100 > 0)
{
if (n100 % 10 == 0)
{
if (!TIME_SETTING)
{
T_SECOUND++;
if (T_SECOUND == 30)
{
twinkle = 6;
}
}
n100 = 0;
}
if (n500 == 5)
{
n500 = 0;
}
}
if (n500)
{
n500 = 0;
if (TIME_SETTING || PRE_TIME_SETTING)
{
pauseRefreshLight = !pauseRefreshLight;
}
else if (PRE_TIMEUP)
{
pauseRefreshLight = 1;
twinklePos++;
if (twinklePos == 8)
{
twinklePos = 0;
}
}
else
{
if (twinkle > 0)
{
pauseRefreshLight = !pauseRefreshLight;
twinkle--;
}
else
{
pauseRefreshLight = 0;
}
}
}
}
void sys_init()
{
WTST = 0;
CKCON = 0;
EAXFR = 1;
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
P3M1 |= 0x03;// 需要将 P30,P31 设置为高阻输入模式
IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
while (!(IRC48MCR & 0x01))
; // 等待震荡源稳定
USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
USBCON = 0x09; // 使能 USB 功能
usb_init(); // 调用 USB CDC 初始化库函数
EUSB = 1; // 使能 USB 中断
}
进来看看
本帖最后由 CListery 于 2024-8-7 15:58 编辑
第三十集:
ADC采集NTC温度并显示
#include <stc32g.h>
#define PRINTF_HID
#include <stc32_stc8_usb.h>
#include "adc.h"
#include "extint.h"
#include "key.h"
#include "led.h"
#include "timer.h"
#define FOSC 24000000UL // ISP 下载时需将工作频率设置为 24MHz
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; // 设置自动复位到ISP区的用户接口命令
bit FLAG_100ms = 1, FLAG_500ms = 0;
u16 NTC_ADC_DATA = {
3980, // -40 0
3972, // -39 1
3964, // -38 2
3955, // -37 3
3946, // -36 4
3936, // -35 5
3926, // -34 6
3915, // -33 7
3904, // -32 8
3892, // -31 9
3880, // -30 10
3867, // -29 11
3853, // -28 12
3838, // -27 13
3823, // -26 14
3807, // -25 15
3791, // -24 16
3774, // -23 17
3756, // -22 18
3737, // -21 19
3717, // -20 20
3697, // -19 21
3675, // -18 22
3653, // -17 23
3630, // -16 24
3606, // -15 25
3581, // -14 26
3556, // -13 27
3529, // -12 28
3501, // -11 29
3473, // -10 30
3444, // -9 31
3413, // -8 32
3382, // -7 33
3350, // -6 34
3317, // -5 35
3283, // -4 36
3249, // -3 37
3213, // -2 38
3177, // -1 39
3139, // 0 40
3101, // 1 41
3063, // 2 42
3023, // 3 43
2983, // 4 44
2942, // 5 45
2901, // 6 46
2858, // 7 47
2816, // 8 48
2773, // 9 49
2729, // 10 50
2685, // 11 51
2640, // 12 52
2595, // 13 53
2550, // 14 54
2505, // 15 55
2459, // 16 56
2414, // 17 57
2368, // 18 58
2322, // 19 59
2276, // 20 60
2230, // 21 61
2184, // 22 62
2139, // 23 63
2093, // 24 64
2048, // 25 65
2003, // 26 66
1958, // 27 67
1914, // 28 68
1870, // 29 69
1827, // 30 70
1784, // 31 71
1741, // 32 72
1699, // 33 73
1657, // 34 74
1617, // 35 75
1576, // 36 76
1536, // 37 77
1497, // 38 78
1459, // 39 79
1421, // 40 80
1384, // 41 81
1348, // 42 82
1312, // 43 83
1277, // 44 84
1242, // 45 85
1209, // 46 86
1176, // 47 87
1144, // 48 88
1112, // 49 89
1082, // 50 90
1052, // 51 91
1022, // 52 92
994,// 53 93
966,// 54 94
939,// 55 95
912,// 56 96
886,// 57 97
861,// 58 98
837,// 59 99
813,// 60 100
790,// 61 101
767,// 62 102
745,// 63 103
724,// 64 104
703,// 65 105
683,// 66 106
663,// 67 107
644,// 68 108
626,// 69 109
608,// 70 110
590,// 71 111
573,// 72 112
557,// 73 113
541,// 74 114
525,// 75 115
510,// 76 116
496,// 77 117
481,// 78 118
468,// 79 119
454,// 80 120
441,// 81 121
429,// 82 122
417,// 83 123
405,// 84 124
394,// 85 125
382,// 86 126
372,// 87 127
361,// 88 128
351,// 89 129
341,// 90 130
332,// 91 131
323,// 92 132
314,// 93 133
305,// 94 134
297,// 95 135
289,// 96 136
281,// 97 137
273,// 98 138
265,// 99 139
258,// 100 140
251,// 101 141
245,// 102 142
238,// 103 143
232,// 104 144
225,// 105 145
219,// 106 146
214,// 107 147
208,// 108 148
202,// 109 149
197,// 110 150
192,// 111 151
187,// 112 152
182,// 113 153
177,// 114 154
173,// 115 155
168,// 116 156
164,// 117 157
160,// 118 158
156,// 119 159
152,// 120 160
148,// 121 161
144,// 122 162
141,// 123 163
137,// 124 164
134,// 125 165
130,// 126 166
127,// 127 167
124,// 128 168
121,// 129 169
118,// 130 170
115,// 131 171
112,// 132 172
110,// 133 173
107,// 134 174
104,// 135 175
102,// 136 176
100,// 137 177
97, // 138 178
95, // 139 179
93, // 140 180
91, // 141 181
88, // 142 182
86, // 143 183
84, // 144 184
82, // 145 185
81, // 146 186
79, // 147 187
77, // 148 188
75, // 149 189
73, // 150 190
};
void sys_init();
void Delay1ms(void) //@24.000MHz
{
unsigned char data i, j;
i = 24;
j = 85;
do
{
while (--j)
;
} while (--i);
}
void Delay100ms()
{
u8 i = 100;
while (--i)
{
Delay1ms();
}
}
u16 cal_temperature(u16 adcVal);
void main()
{
u16 ntcVal;
u16 temp;
sys_init();
// initTimer0(0x30, 0xF8);
initTimer1(0x40, 0xA2);
initADC(0);
EA = 1;
P0M0 = 0;
P0M1 = 0;
P4M0 = 0;
P4M1 = 0;
P6M0 = 0;
P6M1 = 0;
P7M0 = 0;
P7M1 = 0;
P1M1 = 0x38;
P1M0 = 0x30; // 设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.3 为 ADC 高阻输入口
// SSD0 = 0;
// SSD1 = 1;
// SSD2 = 2;
// SSD3 = 3;
// SSD4 = 4;
// SSD5 = 5;
// SSD6 = 6;
// SSD7 = 7;
// 等待 USB 完成配置
while (DeviceState != DEVSTATE_CONFIGURED)
;
while (1)
{
if (bUsbOutReady) // 当硬件接收完成上位机通过串口助手发送数据后
// 会自动将 bUsbOutReady 置 1
// 接收的数据字节保存在 OutNumber 变量总
// 接收的数据保存在 UsbOutBuffer 缓冲区
{
USB_SendData(UsbOutBuffer, OutNumber); // 使用 Usb_SendData 库函数可向上位机发送数据
// 这里的测试代码为将接收数据原样返回
usb_OUT_done(); // 处理完成接收的数据后
// 调用 usb_OUT_done 准备接收下一笔数据
}
if (FLAG_100ms)
{
FLAG_100ms = 0;
ntcVal = queryADC(3);
if (ntcVal < 4096)
{
temp = cal_temperature(ntcVal);
SSD0 = temp % 10;
SSD1 = temp / 10 % 10 + 11;
SSD2 = temp / 100;
}
printf("ntc: %d -> %d\r\n", ntcVal, temp);
}
}
}
u16 cal_temperature(u16 adcVal)
{
u8 i;
float temp;
if (adcVal < NTC_ADC_DATA)
{
i = 191 / 2;
}
else
{
i = 0;
}
for (; i < 191; i++)
{
if (NTC_ADC_DATA == adcVal)
{
temp = (i - 40) * 10;
break;
}
else if (NTC_ADC_DATA < adcVal)
{
temp = ((float)(NTC_ADC_DATA - adcVal) / (float)(NTC_ADC_DATA - NTC_ADC_DATA) + (i - 40)) * 10;
break;
}
}
return (u16)temp;
}
void t1_run(void) interrupt 3
// void t0_run() interrupt 1
{
static u8 n = 0, n100 = 0, n500 = 0;
refreshLight(-1);
n++;
if (n % 10 == 0)
{
refreshKeyStatus();
}
if (n == 100)
{
FLAG_100ms = 1;
n100++;
n500++;
n = 0;
}
if (n100 > 0)
{
if (n500 == 5)
{
n500 = 0;
}
if (n100 % 10 == 0)
{
n100 = 0;
}
}
if (n500)
{
n500 = 0;
}
}
void sys_init()
{
WTST = 0;
CKCON = 0;
EAXFR = 1;
P3M0 = 0x00;
P3M1 = 0x00;
P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
P3M1 |= 0x03;// 需要将 P30,P31 设置为高阻输入模式
IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
while (!(IRC48MCR & 0x01))
; // 等待震荡源稳定
USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
USBCON = 0x09; // 使能 USB 功能
usb_init(); // 调用 USB CDC 初始化库函数
EUSB = 1; // 使能 USB 中断
}
第32集
课后训练
#include "pref.h"
#include "digital_display.h"
#include "timer.h"
#include "uart.h"
#include "ntc.h"
#include "bee.h"
#include <STDIO.H>
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; // 设置自动复位到ISP区的用户接口命令
bit B_1ms; // 1ms标志
void sys_init();
void init_usb();
void main()
{
// u8 cnt = 0;
u32 number;
u16 tmp_u16;
u8 tmp_u8, i;
u8 *str;
sys_init();
init_time0();
UART2_config(2);
init_adc();
init_bee();
init_usb();
EA = 1; // 打开总中断
// 等待 USB 完成配置
while (DeviceState != DEVSTATE_CONFIGURED)
;
digital_display_init();
digital_led_set(4);
digital_display_set(123456781);
bee_open_with_time(100);
uart2_send_string("uart test!\r\n");
while (1)
{
if (B_1ms) // 1ms到
{
B_1ms = 0;
// digital_display_1ms_on_main();
if (uart_is_rec_done())
{
uart_reset_rec_flag();
// digital_display_set(++cnt);
switch (uart2_read_byte(0))
{
case 'A':
uart2_send_byte('A');
tmp_u8 = uart2_read_byte(1);
uart2_send_byte((u8)tmp_u8);
if (tmp_u8 >= '0' && tmp_u8 <= '9')
{
digital_led_set((u8)(tmp_u8 - '0'));
}
break;
case 'B':
uart2_send_byte('B');
number = 0;
for (i = 1; i <= 8; i++)
{
tmp_u8 = uart2_read_byte(i);
if (tmp_u8 == '\r' || tmp_u8 == '\n' || tmp_u8 == '\0')
{
break;
}
if (tmp_u8 >= '0' && tmp_u8 <= '9')
{
number = number * 10 + (tmp_u8 - '0');
}
else
{
break;
}
}
// uart2_send_u16(number);
digital_display_set(number);
break;
case 'Z':
uart2_send_byte('Z');
uart2_send_string("HELLO CLISTERY!");
break;
case 'C':
uart2_send_byte('C');
if (uart2_read_byte(1) == '1')
{
bee_on();
}
else
{
bee_off();
}
break;
case 'D':
uart2_send_byte('D');
uart2_send_newline();
tmp_u16 = Get_ADC12bitResult(3); // 参数0~15,查询方式做一次ADC, 返回值就是结果, == 4096 为错误
if (tmp_u16 < 4096)
{
tmp_u16 = get_temperature(tmp_u16);
if (tmp_u16 >= 400)
F0 = 0, tmp_u16 -= 400; // 温度 >= 0度
else
F0 = 1, tmp_u16 = 400 - tmp_u16; // 温度 <0度
i = tmp_u16 / 1000;
sprintf(str, "温度: %5.1f\r\n", ((float)tmp_u16) / 10);
uart2_send_string(str);
digital_display_set_pos((u8)(DIS_BLACK),
(u8)(DIS_BLACK),
(u8)(DIS_BLACK),
(u8)(DIS_BLACK),
(u8)(i == 0 ? DIS_BLACK : (F0 ? DIS_ : i)),
(u8)(tmp_u16 % 1000 / 100),
(u8)(tmp_u16 % 100 / 10 + DIS_DOT),
(u8)(tmp_u16 % 10));
}
break;
}
}
}
}
}
void sys_init()
{
WTST = 0;// 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; // 扩展寄存器(XFR)访问使能
CKCON = 0; // 提高访问XRAM速度
{
P0M1 = 0x30;
P0M0 = 0x30; // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x30;
P1M0 = 0x30; // 设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V)
P2M1 = 0x3c;
P2M0 = 0x3c; // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
P3M1 = 0x50;
P3M0 = 0x50; // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c;
P4M0 = 0x3c; // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c;
P5M0 = 0x0c; // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff;
P6M0 = 0xff; // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00;
P7M0 = 0x00; // 设置为准双向口
}
}
void init_usb()
{
P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
P3M1 |= 0x03;// 需要将 P30,P31 设置为高阻输入模式
IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
while (!(IRC48MCR & 0x01))
; // 等待震荡源稳定
USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
USBCON = 0x09; // 使能 USB 功能
usb_init(); // 调用 USB CDC 初始化库函数
EUSB = 1; // 使能 USB 中断
}
/********************** Timer0 1ms中断函数 ************************/
void timer0(void) interrupt 1
{
B_1ms = 1; // 1ms标志
DisplayScan(); // 1ms扫描显示一位
bee_on_1ms();
}
推荐优先看的 printf_usb("Hello World !\r\n")及usb不停电下载, 演示视频链接
https://v.stcai.com/sv/e49742d-1978afcb431/e49742d-1978afcb431.mp4
上面是 小李 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
https://v.stcai.com/sv/61d1aa5-1978c2a6adb/61d1aa5-1978c2a6adb.mp4
上面是 小赵 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
使用 CDC 串口重写普通串口通讯代码
#include "pref.h"
#include "digital_display.h"
#include "timer.h"
#include "ntc.h"
#include "bee.h"
#include <STDIO.H>
bit B_1ms; // 1ms标志
void sys_init();
void init_usb();
void main()
{
u32 number;
u16 tmp_u16;
u8 tmp_u8, i;
sys_init();
init_time0();
init_adc();
init_bee();
init_usb();
EA = 1; // 打开总中断
digital_display_set(0);
digital_led_set(0);
while (1)
{
if (bUsbOutReady)
{
switch (UsbOutBuffer)
{
case 'A':
tmp_u8 = UsbOutBuffer;
printf_usb("A %c", tmp_u8);
if (tmp_u8 >= '0' && tmp_u8 <= '9')
{
digital_led_set((u8)(tmp_u8 - '0'));
}
break;
case 'B':
number = 0;
for (i = 1; i <= 8; i++)
{
tmp_u8 = UsbOutBuffer;
if (tmp_u8 == '\r' || tmp_u8 == '\n' || tmp_u8 == '\0')
{
break;
}
if (tmp_u8 >= '0' && tmp_u8 <= '9')
{
number = number * 10 + (tmp_u8 - '0');
}
else
{
break;
}
}
printf_usb("B %d", number);
digital_display_set(number);
break;
case 'Z':
printf_usb("Z HELLO CLISTERY!");
break;
case 'C':
if (UsbOutBuffer == '1')
{
printf_usb("C on");
bee_on();
}
else
{
printf_usb("C off");
bee_off();
}
break;
case 'D':
tmp_u16 = Get_ADC12bitResult(3); // 参数0~15,查询方式做一次ADC, 返回值就是结果, == 4096 为错误
if (tmp_u16 < 4096)
{
tmp_u16 = get_temperature(tmp_u16);
if (tmp_u16 >= 400)
F0 = 0, tmp_u16 -= 400; // 温度 >= 0度
else
F0 = 1, tmp_u16 = 400 - tmp_u16; // 温度 <0度
i = tmp_u16 / 1000;
printf_usb("D 温度: %5.1f", ((float)tmp_u16) / 10);
digital_display_set_pos((u8)(DIS_BLACK),
(u8)(DIS_BLACK),
(u8)(DIS_BLACK),
(u8)(DIS_BLACK),
(u8)(i == 0 ? DIS_BLACK : (F0 ? DIS_ : i)),
(u8)(tmp_u16 % 1000 / 100),
(u8)(tmp_u16 % 100 / 10 + DIS_DOT),
(u8)(tmp_u16 % 10));
}
break;
}
usb_OUT_done();
}
}
}
void sys_init()
{
WTST = 0;// 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; // 扩展寄存器(XFR)访问使能
CKCON = 0; // 提高访问XRAM速度
{
P0M1 = 0x30;
P0M0 = 0x30; // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x30;
P1M0 = 0x30; // 设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V)
P2M1 = 0x3c;
P2M0 = 0x3c; // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
P3M1 = 0x50;
P3M0 = 0x50; // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c;
P4M0 = 0x3c; // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c;
P5M0 = 0x0c; // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff;
P6M0 = 0xff; // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00;
P7M0 = 0x00; // 设置为准双向口
}
}
void init_usb()
{
P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
P3M1 |= 0x03;// 需要将 P30,P31 设置为高阻输入模式
IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
while (!(IRC48MCR & 0x01))
; // 等待震荡源稳定
USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
USBCON = 0x09; // 使能 USB 功能
usb_init(); // 调用 USB CDC 初始化库函数
EUSB = 1; // 使能 USB 中断
}
/********************** Timer0 1ms中断函数 ************************/
void timer0(void) interrupt 1
{
B_1ms = 1; // 1ms标志
DisplayScan(); // 1ms扫描显示一位
bee_on_1ms();
}
36. 看门狗
#include "pref.h"
#include "digital_display.h"
#include "timer.h"
#include "ntc.h"
#include "bee.h"
#include <STDIO.H>
bit B_1ms; // 1ms标志
void sys_init();
void init_usb();
void main()
{
sys_init();
init_time0();
// (12*32768*WDT_PS) / MAIN_Fosc
// WDT_PS = 128
// 24M 系统时钟,看门狗计数器溢出时间大概为 2秒
WDT_CONTR = 0x26;
init_usb();
EA = 1; // 打开总中断
digital_display_set(0);
digital_led_set(0);
while (1)
{
WDT_CONTR = 0x36;
if (!P34)
{
// 2秒左右显示会被复位
digital_led_set(7);
digital_display_set(11111111);
// 模拟程序跑飞
while(1);
}
}
}
void sys_init()
{
WTST = 0;// 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; // 扩展寄存器(XFR)访问使能
CKCON = 0; // 提高访问XRAM速度
{
P0M1 = 0x30;
P0M0 = 0x30; // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x30;
P1M0 = 0x30; // 设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V)
P2M1 = 0x3c;
P2M0 = 0x3c; // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
P3M1 = 0x50;
P3M0 = 0x50; // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c;
P4M0 = 0x3c; // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c;
P5M0 = 0x0c; // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff;
P6M0 = 0xff; // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00;
P7M0 = 0x00; // 设置为准双向口
}
}
void init_usb()
{
P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
P3M1 |= 0x03;// 需要将 P30,P31 设置为高阻输入模式
IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
while (!(IRC48MCR & 0x01))
; // 等待震荡源稳定
USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
USBCON = 0x09; // 使能 USB 功能
usb_init(); // 调用 USB CDC 初始化库函数
EUSB = 1; // 使能 USB 中断
}
/********************** Timer0 1ms中断函数 ************************/
void timer0(void) interrupt 1
{
B_1ms = 1; // 1ms标志
DisplayScan(); // 1ms扫描显示一位
bee_on_1ms();
}
37. 比较器
采用adc采集ntc电压,并与内部1.9V比较,由于测试时室温高,所以直接用镊子短接ntc两端,瞬间触发P47的led点亮~
课后练习只需将 ADC_CONTR 值改为 0x80 选择 P1.0 ADC 通道即可
#include "cmp.h"
void init_cmp()
{
ADC_CONTR = 0x83; // 打开 ADC_POWER 和 P1.3 ADC 通道
CMPEXCFG = 0x00;
//CMPEXCFG |= 0x40; //比较器DC迟滞输入选择,0:0mV; 0x40:10mV; 0x80:20mV; 0xc0:30mV
//CMPEXCFG &= ~0x04; //P3.6为CMP-输入脚
CMPEXCFG |= 0x04; // 内部1.19V参考电压为CMP-输入脚
// CMPEXCFG &= ~0x03; //P3.7为CMP+输入脚
//CMPEXCFG |= 0x01; //P5.0为CMP+输入脚
//CMPEXCFG |= 0x02; //P5.1为CMP+输入脚
CMPEXCFG |= 0x03; // ADC输入脚为CMP+输入脚
CMPCR2 = 0x00;
INVCMPO = 0; // 比较器正向输出
//INVCMPO = 1; //比较器反向输出
DISFLT = 0; // 使能0.1us滤波
//DISFLT = 1; //禁止0.1us滤波
//CMPCR2 &= ~0x3f; //比较器结果直接输出
CMPCR2 |= 0x10; // 比较器结果经过16个去抖时钟后输出
CMPCR1 = 0x00;
//PIE = 0; //禁止比较器上升沿中断
PIE = 1; // 使能比较器上升沿中断
//NIE = 0; //禁止比较器下降沿中断
NIE = 1; // 使能比较器下降沿中断
//CMPOE = 0; //禁止比较器输出
CMPOE = 1; // 使能比较器输出
CMPO_S = 0; // 选择P3.4作为比较器输出脚
//CMPO_S = 1; //选择P4.1作为比较器输出脚
CMPEN = 1; // 使能比较器模块
}
void CMP_Isr() interrupt 21
{
CMPIF = 0; // 清中断标志
P47 = CMPRES; // 中断方式读取比较器比较结果
}
38. 内部EEPROM
在 EEPROM 中存储断电次数,EEPROM 设置为1K
#include "pref.h"
#include "digital_display.h"
#include "timer.h"
#include "ntc.h"
#include "bee.h"
#include <STDIO.H>
#include "cmp.h"
#include "internal_eeprom.h"
bit B_1ms; // 1ms标志
void sys_init();
void init_usb();
#define FLAG_ADDR 512 // 标记位起始地址
#define DATA_ADDR 0 // 数据位起始地址
void main()
{
u8 i;
sys_init();
init_cmp();
init_adc();
init_time0();
digital_display_init();
init_usb();
EA = 1; // 打开总中断
digital_display_black();
internal_eeprom_idle();
if (internal_eeprom_read(FLAG_ADDR) != 0x2A)
{
internal_eeprom_erasure(FLAG_ADDR);
internal_eeprom_erasure(DATA_ADDR);
internal_eeprom_write(FLAG_ADDR, 0x2A);
internal_eeprom_write(DATA_ADDR, 1);
}
i = internal_eeprom_read(DATA_ADDR);
digital_display_set(i++);
internal_eeprom_erasure(DATA_ADDR);
internal_eeprom_write(DATA_ADDR, i);
// (12*32768*WDT_PS) / MAIN_Fosc
// WDT_PS = 128
// 24M 系统时钟,看门狗计数器溢出时间大概为 2秒
WDT_CONTR = 0x26;
while (1)
{
WDT_CONTR = 0x36;
}
}
void sys_init()
{
WTST = 0;// 设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; // 扩展寄存器(XFR)访问使能
CKCON = 0; // 提高访问XRAM速度
{
P0M1 = 0x30;
P0M0 = 0x30; // 设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x30;
P1M0 = 0x30; // 设置P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V)
P2M1 = 0x3c;
P2M0 = 0x3c; // 设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
P3M1 = 0x50;
P3M0 = 0x50; // 设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c;
P4M0 = 0x3c; // 设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c;
P5M0 = 0x0c; // 设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff;
P6M0 = 0xff; // 设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00;
P7M0 = 0x00; // 设置为准双向口
}
}
void init_usb()
{
P3M0 &= ~0x03; // P30,P31 和 USB 的 D-,D+ 共用 PIN 脚
P3M1 |= 0x03;// 需要将 P30,P31 设置为高阻输入模式
IRC48MCR = 0x80; // 使能内部 48M 的 USB 专用 IRC
while (!(IRC48MCR & 0x01))
; // 等待震荡源稳定
USBCLK = 0x00; // 设置 USB 时钟源为内部 48M 的 USB 专用 IRC
USBCON = 0x09; // 使能 USB 功能
usb_init(); // 调用 USB CDC 初始化库函数
EUSB = 1; // 使能 USB 中断
}
/********************** Timer0 1ms中断函数 ************************/
void timer0(void) interrupt 1
{
B_1ms = 1; // 1ms标志
DisplayScan(); // 1ms扫描显示一位
bee_on_1ms();
}