DeepSeek官方更新日志描述:
时间: 2026-07-31DeepSeek-V4-Flash 更新DeepSeek-V4-Flash 正式版 API 上线公测,API 调用方式不变,模型名设置为 deepseek-v4-flash 即可使用最新版本。 Agent 能力大幅增强,基准测试远超 V4-Pro-Preview
现在来测试一下STC-【AI助手】的写代码能力是否有明显提升
测试的问题是:
“
帮忙用STC32G12K128写一个程序。功能是检测P32外部按键(按键按下时会被接地)短按,长按,双击。然后在串口1(P30,P31)使用115200波特率发送识别到的按键信息。同时在P2口上完成一个流水灯,短按切换流水方向,长按切换流水速度(三档循环切换),双击切换所有的led同时闪烁,再次双击切换回led的流水状态。按下按键的时候不能影响led动作,可以参考例程
”
这个主要考察了模型本身对于状态机和多种冲突的处理能力(按键按下和流水灯需要互相不冲突,主要考验逻辑能力)
经过了较长的思考时间后,STC-AI助手给出了最终程序
复制对应的程序到Keil中
一次编译直接通过
按照注释设置24Mhz主频后,串口成功在上电接收到了启动信息
进行点击测试,成功出现了三种识别,且按下按键的过程中并未被堵塞
以下是实际测试视频:
这里分析一下其输出内容:
会进行自我反思,然后逐步更新模块内容
开头部分会进行分析需求来梳理
以及输出的程序部分:
- /*****************************************************************************
- * 文件名: main.c
- * 芯片 : STC32G12K128
- * 系统时钟: 24MHz 内部IRC
- * 编译环境: Keil C251 (选择 STC32G 型号)
- *
- * 功能说明:
- * 1. 检测 P32 外部按键(按键按下接地)的 短按 / 长按 / 双击 操作
- * 2. 串口1(P3.0/P3.1) 以 115200,8,N,1 发送按键识别信息
- * 3. P2口完成流水灯:
- * - 短按: 切换流水方向(正/反)
- * - 长按: 切换流水速度(慢/中/快 三档循环)
- * - 双击: 所有LED同时闪烁, 再次双击切回流水状态
- * 4. 按键检测基于定时器0的1ms中断, 与LED动作相互独立
- * (按下/识别按键不影响LED流水动作)
- *
- * 硬件连接:
- * P2.0~P2.7 -> 8个LED(建议高电平点亮,LED负极接GND)
- * P3.2(P32) -> 按键, 另一端接GND (按下接地)
- * P3.0/P3.1 -> 串口1 RXD/TXD(接USB转串口)
- *
- * 使用步骤:
- * 1. 用 AiCube-ISP 下载时选择"内部IRC时钟", 频率选 24MHz
- * 2. 编译后用 ISP 工具下载到 STC32G12K128
- * 3. 打开串口助手, 波特率 115200, 即可看到按键信息
- *****************************************************************************/
- #include "stc32g.h" // STC32G 头文件(见下载软件)
- #include "intrins.h"
-
- #define FOSC 24000000UL // 系统时钟 24MHz
-
- // 定时器2做串口1波特率发生器: 重载值计算(加2为四舍五入)
- #define BRT (65536 - (FOSC/115200 + 2)/4)
-
- // ------------------- LED 模式与事件定义 -------------------
- #define LED_MODE_FLOW 0 // 流水灯模式
- #define LED_MODE_BLINK 1 // 全部闪烁模式
-
- #define KEY_NONE 0 // 无按键事件
- #define KEY_SINGLE 1 // 短按
- #define KEY_LONG 2 // 长按
- #define KEY_DOUBLE 3 // 双击
-
- // 按键状态机状态
- #define KEY_ST_IDLE 0 // 空闲
- #define KEY_ST_PRESS 1 // 第一次按下(判断长按/短按)
- #define KEY_ST_RELEASE 2 // 第一次释放(等待是否双击)
- #define KEY_ST_SECOND 3 // 第二次按下(双击确认中)
- #define KEY_ST_LONGED 4 // 长按已触发(等待释放)
-
- // 时间阈值(单位: 1ms)
- #define LONG_PRESS_MS 900 // 长按判定阈值
- #define DOUBLE_WINDOW_MS 300 // 双击间隔窗口
-
- // ------------------- 全局变量 -------------------
- unsigned char led_mode = LED_MODE_FLOW; // LED工作模式
- unsigned char led_dir = 0; // 流水方向 0正向 1反向
- unsigned char led_speed = 0; // 流水速度 0慢 1中 2快
- unsigned char led_pos = 0; // 当前点亮LED位置
-
- unsigned char key_event = KEY_NONE; // 按键事件标志
-
- volatile unsigned int sys_tick = 0; // 1ms时基(定时器0产生)
-
- // ------------------- 函数声明 -------------------
- void UartInit(void);
- void Timer0_Init(void);
- void UartSend(char dat);
- void UartSendStr(char *p);
- void UpdateLed(void);
- void Key_Task(void); // 按键状态机, 每1ms调用
-
- // =================== 串口1相关函数 ===================
- // 串口1初始化: 使用定时器2做波特率发生器, 115200
- void UartInit(void)
- {
- SCON = 0x50; // 串口1模式1: 8位数据, 可变波特率(由T2产生)
- T2L = BRT; // 定时器2波特率重载低字节
- T2H = BRT >> 8; // 定时器2波特率重载高字节
- S1BRT = 1; // 串口1使用定时器2做波特率发生器
- T2x12 = 1; // 定时器2工作在1T模式
- T2R = 1; // 启动定时器2
- }
-
- // 发送一个字节(轮询方式)
- void UartSend(char dat)
- {
- SBUF = dat;
- while(!TI); // 等待发送完成
- TI = 0;
- }
-
- // 发送字符串
- void UartSendStr(char *p)
- {
- while(*p)
- {
- UartSend(*p++);
- }
- }
-
- // =================== 定时器0 1ms时基 ===================
- // 定时器0初始化: 12T模式, 16位自动重载, 1ms中断
- void Timer0_Init(void)
- {
- TMOD &= 0xF0; // 清零T0相关位, 设为16位自动重载模式(模式0)
- // 重载值 = 65536 - FOSC/12/1000 = 65536 - 24000000/12000 = 63536 = 0xF830
- TL0 = 0x30;
- TH0 = 0xF8;
- TR0 = 1; // 启动定时器0
- ET0 = 1; // 使能定时器0中断
- }
-
- // 定时器0中断服务函数: 1ms一次
- void TM0_Isr() interrupt 1
- {
- sys_tick++; // 1ms时基计数
- Key_Task(); // 执行按键状态机扫描
- }
-
- // =================== 按键识别状态机 ===================
- // 每1ms调用一次, 识别短按/长按/双击, 结果存入 key_event
- void Key_Task(void)
- {
- static unsigned char key_state = KEY_ST_IDLE;
- static unsigned int press_cnt = 0; // 按下持续计数
- static unsigned int wait_cnt = 0; // 双击窗口等待计数
- unsigned char pin_level;
-
- pin_level = P32; // 读取按键电平, 按下为0(接地)
-
- switch(key_state)
- {
- case KEY_ST_IDLE: // 空闲, 等待按下
- if(pin_level == 0)
- {
- press_cnt = 0;
- key_state = KEY_ST_PRESS;
- }
- break;
-
- case KEY_ST_PRESS: // 第一次按下中
- if(pin_level == 0)
- {
- press_cnt++;
- if(press_cnt >= LONG_PRESS_MS) // 达到长按阈值
- {
- key_event = KEY_LONG; // 判定为长按
- key_state = KEY_ST_LONGED; // 进入长按已触发状态
- }
- }
- else // 释放
- {
- wait_cnt = 0;
- key_state = KEY_ST_RELEASE; // 进入等待双击窗口
- }
- break;
-
- case KEY_ST_RELEASE: // 等待双击窗口内是否再次按下
- if(pin_level == 0) // 窗口内再次按下
- {
- key_state = KEY_ST_SECOND; // 进入第二次按下
- }
- else
- {
- wait_cnt++;
- if(wait_cnt >= DOUBLE_WINDOW_MS) // 窗口超时
- {
- key_event = KEY_SINGLE; // 判定为短按
- key_state = KEY_ST_IDLE; // 回到空闲
- }
- }
- break;
-
- case KEY_ST_SECOND: // 第二次按下(等待释放确认双击)
- if(pin_level == 1) // 第二次释放
- {
- key_event = KEY_DOUBLE; // 判定为双击
- key_state = KEY_ST_IDLE;
- }
- break;
-
- case KEY_ST_LONGED: // 长按已触发, 等待释放
- if(pin_level == 1)
- {
- key_state = KEY_ST_IDLE;
- }
- break;
- }
- }
-
- // =================== LED 流水灯控制 ===================
- // 基于 sys_tick 时基更新LED, 与按键检测相互独立
- void UpdateLed(void)
- {
- static unsigned int last_tick = 0;
- unsigned int cur = sys_tick;
- unsigned int diff = cur - last_tick;
- unsigned int interval;
-
- if(led_mode == LED_MODE_FLOW)
- {
- // 根据速度档位选择更新间隔
- switch(led_speed)
- {
- case 0: interval = 500; break; // 慢: 500ms
- case 1: interval = 200; break; // 中: 200ms
- default: interval = 80; break; // 快: 80ms
- }
-
- if(diff >= interval)
- {
- last_tick = cur;
- if(led_dir == 0) // 正向流水
- led_pos = (led_pos + 1) & 0x07;
- else // 反向流水
- led_pos = (led_pos + 7) & 0x07;
-
- P2 = (unsigned char)(1 << led_pos); // 单灯点亮
- }
- }
- else // LED_MODE_BLINK: 全部LED同时闪烁
- {
- if(diff >= 200) // 200ms翻转一次
- {
- last_tick = cur;
- P2 = ~P2; // 取反闪烁
- }
- }
- }
-
- // =================== 主函数 ===================
- void main(void)
- {
- EAXFR = 1; // 使能访问XFR(需访问扩展寄存器)
- CKCON = 0x00; // 设置外部数据总线速度为最快
- WTST = 0x00; // 设置程序代码等待参数, 执行速度最快
-
- // P2口配置为推挽输出(驱动LED)
- P2M0 = 0xFF;
- P2M1 = 0x00;
-
- // P3口配置为准双向口(弱上拉)
- // P3.0/P3.1 -> 串口1
- // P3.2 -> 按键输入(准双向内部上拉,按键接地时为0)
- P3M0 = 0x00;
- P3M1 = 0x00;
-
- P32 = 1; // P32作为输入, 准双向口读外部状态前需锁存为1
-
- UartInit(); // 串口1初始化(115200)
- Timer0_Init(); // 定时器0初始化(1ms中断)
-
- EA = 1; // 打开总中断
-
- UartSendStr("STC32G12K128 Key Test Start!\r\n");
-
- while(1)
- {
- // ---------- 处理按键事件(中断中置位,主循环消费) ----------
- if(key_event != KEY_NONE)
- {
- switch(key_event)
- {
- case KEY_SINGLE: // 短按: 切换流水方向
- led_dir = !led_dir;
- UartSendStr("Key: Single Press\r\n");
- break;
-
- case KEY_LONG: // 长按: 三档速度循环
- led_speed++;
- if(led_speed > 2)
- led_speed = 0;
- UartSendStr("Key: Long Press\r\n");
- break;
-
- case KEY_DOUBLE: // 双击: 切换LED模式
- if(led_mode == LED_MODE_FLOW)
- {
- led_mode = LED_MODE_BLINK;
- P2 = 0xFF; // 进入闪烁模式先全亮
- }
- else
- {
- led_mode = LED_MODE_FLOW;
- P2 = 1; // 回到流水, 从第一个LED开始
- }
- UartSendStr("Key: Double Press\r\n");
- break;
- }
- key_event = KEY_NONE; // 清除事件
- }
-
- // ---------- 更新LED(按键检测不影响LED) ----------
- UpdateLed();
- }
- }
复制代码
还有可以测试的程序:
test stc32g led.zip
(154.67 KB, 下载次数: 50)
|