实在是没办法了,弄了一晚上了还是弄不好 AI 帮人写的代码
这段代码用 AI 编程写的.试了很多遍,现在只能实现按键换挡,一直这样循环.
我的代码想要 按键换挡,但是如果3秒内没有换挡,
再次按下按键,就关闭LED.最好是加上 记忆上次关闭时的档位.
下次开机直接进入上次关闭时的档位.
感觉是定时器中断没有 参与进来.
麻烦大神们帮看看把.苦恼死我了
#include <STC8G.H>
#include "intrins.h"
sbit LED1=P3^3;
sbit KEY1=P3^2;
#define MAIN_Fosc 11059200UL
#define ON 0
#define OFF 1
typedef unsigned char u8;
typedef unsigned int u16;
static u8 ld = 0;
static u8 gear = 0;
static u16 noShiftTime = 0; // 自上次换挡以来的时间
void pwm_init(void);
void delayms(u16 ms);
void timer0_init();
void process_key_press();
void update_led_brightness(u8 gear);
void main() {
// I/O口配置
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P_SW2=0x80;
while(1) {
pwm_init();
timer0_init();
process_key_press();
update_led_brightness(gear);
delayms(10);
}
}
void process_key_press() {
if (KEY1 == 0) {
delayms(10); // 去抖动延时
if (KEY1 == 0) {
if (noShiftTime >= 300) {
ld = 0; // 关闭LED
noShiftTime = 0;
} else {
gear = (gear + 1) % 4; // 切换档位
while (!KEY1); // 等待按钮释放
noShiftTime = 0;
}
}
}
}
void update_led_brightness(u8 gear) {
switch (gear) {
case 0:
ld = 0;
break;
case 1:
ld = 15;
break;
case 2:
ld = 135;
break;
case 3:
ld = 255;
break;
}
}
void pwm_init(void)
{
CCON = 0x00;
CMOD = 0x08;
CL = 0x00;
CH = 0x00;
CCAPM1 = 0x42;
PCA_PWM1 = 0x00;
CCAP1L = ld;
CCAP1H = ld;
CR=1;
// while(1);
}
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0_ISR() interrupt 1 {
noShiftTime++;
if (noShiftTime >= 300) {
noShiftTime = 0;
}
}
void delayms(u16 ms)
{
u16 i;
do{
i = MAIN_Fosc /10000;
while(--i);
}while(--ms);
}
你首先是你的定时器,不可以一直开着,这样就没有计时3s的意义了。
这里有一种方式,就是采用自减操作。中断先判断变量是否为0,不为零就自减一次,为零就不操作。
需要定时的地方(按键按下后)赋予延时值3s,然后再判断3s是否归零就可以了。档位需要从1开始记,这样初始化为0,方便判断第一次按下,防止直接进入关闭 王昱顺 发表于 2024-6-30 01:42
你首先是你的定时器,不可以一直开着,这样就没有计时3s的意义了。
这里有一种方式,就是采用自减操作。中 ...
我也怀疑是定时器的问题,
我按照你的方案再试试.看看怎么样
王昱顺 发表于 2024-6-30 01:42
你首先是你的定时器,不可以一直开着,这样就没有计时3s的意义了。
这里有一种方式,就是采用自减操作。中 ...
这是修改后的代码,还是不行.#include <STC8G.H>
#include "intrins.h"
sbit LED1=P3^3;
sbit KEY1=P3^2;
#define MAIN_Fosc 11059200UL
#define ON 0
#define OFF 1
typedef unsigned char u8;
typedef unsigned int u16;
static u8 ld = 0;
static u8 gear = 0;
static u16 noShiftTime = 0; // 自上次换挡以来的时间
static u8 timerStarted = OFF; // 标记定时器是否已启动
void sysini();
void pwm_init(void);
void delayms(u16 ms);
void Timer0_Init();
void process_key_press();
void update_led_brightness(u8 gear);
void main() {
sysini();
// Timer0_Init();
EA = 1; // 开启全局中断
P_SW2=0x80;
while(1) {
pwm_init();
process_key_press();
update_led_brightness(gear);
delayms(10);
}
}
void sysini() {
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
}
void process_key_press() {
static u8 firstPress = ON; // 标记第一次按键按下
if (KEY1 == 0) {
delayms(10); // 去抖动延时
if (KEY1 == 0) {
if (firstPress) {
Timer0_Init(); // 第一次按键按下时启动定时器
firstPress = OFF;
}
if (noShiftTime >= 3000) {
ld = 0; // 关闭LED
noShiftTime = 0;
} else {
gear = (gear + 1) % 4; // 切换档位
while (!KEY1); // 等待按钮释放
noShiftTime = 0;
}
}
}
}
void update_led_brightness(u8 gear) {
switch (gear) {
case 0:
ld = 0;
break;
case 1:
ld = 15;
break;
case 2:
ld = 135;
break;
case 3:
ld = 255;
break;
}
}
void pwm_init(void) {
CCON = 0x00;
CMOD = 0x08;
CL = 0x00;
CH = 0x00;
CCAPM1 = 0x42;
PCA_PWM1 = 0x00;
CCAP1L = ld;
CCAP1H = ld;
CR=1;
}
void Timer0_ISR() interrupt 1 {
if (timerStarted) { // 只有当定时器已启动时才递增计数器
TL0 = 0xCD; // 设置定时初始值
TH0 = 0xD4; // 设置定时初始值
noShiftTime++;
if (noShiftTime >= 3000) {
noShiftTime = 0;
}
}
}
void Timer0_Init(void) { // 1毫秒@11.0592MHz
AUXR |= 0x80; // 定时器时钟1T模式
TMOD &= 0xF0; // 设置定时器模式
TMOD |= 0x01; // 设置定时器模式
TL0 = 0xCD; // 设置定时初始值
TH0 = 0xD4; // 设置定时初始值
TF0 = 0; // 清除TF0标志
TR0 = 1; // 定时器0开始计时
ET0 = 1;
timerStarted = ON; // 标记定时器已启动
}
void delayms(u16 ms) {
u16 i;
do{
i = MAIN_Fosc /10000;
while(--i);
}while(--ms);
} 代码简化一下,按下按键就
判断 noShiftTime 是不是超过3s,
如果超过,关闭,
没有超过 noShiftTime = 1,
定时器中断里面这样写:
if(noShiftTime) {
noShiftTime ++;
}
if(noShiftTime >=3000){
noShiftTime = 0;
} xiangzichen 发表于 2024-6-30 12:10
代码简化一下,按下按键就
判断 noShiftTime 是不是超过3s,
如果超过,关闭,
按照您给的代码写了.
还是不行,和之前一样,不能三秒后按键关闭led
#include <STC8G.H>
#include "intrins.h"
sbit LED1=P3^3;
sbit KEY1=P3^2;
#define MAIN_Fosc 11059200UL
#define ON 0
#define OFF 1
typedef unsigned char u8;
typedef unsigned int u16;
static u8 ld = 0;
static u8 gear = 0;
static u16 noShiftTime = 0; // 自上次换挡以来的时间
void pwm_init(void);
void delayms(u16 ms);
void Timer0_Init(void);
void process_key_press();
void update_led_brightness(u8 gear);
void main() {
// I/O口配置
Timer0_Init();
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P_SW2=0x80;
EA=1;
while(1) {
pwm_init();
process_key_press();
update_led_brightness(gear);
delayms(10);
}
}
void process_key_press() {
if (KEY1 == 0) {
delayms(10); // 去抖动延时
if (KEY1 == 0) {
if (noShiftTime >= 3000) {
ld = 0; // 关闭LED
noShiftTime = 0;
} else {
gear = (gear + 1) % 4; // 切换档位
while (!KEY1); // 等待按钮释放
noShiftTime = 0;
}
}
}
}
void update_led_brightness(u8 gear) {
switch (gear) {
case 0:
ld = 0;
break;
case 1:
ld = 15;
break;
case 2:
ld = 135;
break;
case 3:
ld = 255;
break;
}
}
void pwm_init(void)
{
CCON = 0x00;
CMOD = 0x08;
CL = 0x00;
CH = 0x00;
CCAPM1 = 0x42;
PCA_PWM1 = 0x00;
CCAP1L = ld;
CCAP1H = ld;
CR=1;
// while(1);
}
void Timer0_Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xCD; //设置定时初始值
TH0 = 0xD4; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0_ISR() interrupt 1 {
if(noShiftTime) {
noShiftTime ++;
}
if(noShiftTime >=3000){
noShiftTime = 0;
}
}
void delayms(u16 ms)
{
u16 i;
do{
i = MAIN_Fosc /10000;
while(--i);
}while(--ms);
}
本帖最后由 xiangzichen 于 2024-6-30 16:31 编辑
这里是不是应该 是 =1
还有这里,貌似应该是3000
noShiftTime 要加限制而不是清零
即
if(noShiftTime <3000)noShiftTime ++;
这样noShiftTime 就不会超过3000也不会溢出 本帖最后由 网老四 于 2024-6-30 15:15 编辑
//以下是程序控制框架,细节需要根据实际情况修改添加
void main(void)
{
u16 count; //延时计数器
while(1)
{
if(key_ON)
{
if(count<3000)//若3s内再次按键
{
(LED_gear<3)?(LED_gear++):(LED_gear=0); //循环调亮度档位
LED_ON; //开灯
}
else //若3s后再按键
{
if(LED_ON)//若原来开灯状态
{
LED_gear=0; //微亮档位
LED_OFF; //关灯
}
else LED_ON; //若原来关灯状态,以原来亮度档位开灯
}
count=0;//清计数器
while(key_ON); //等按键释放,防止重复响应
}
这里插入根据档位设置LED驱动PWM值的代码或函数
delay_ms(1);//1ms延时
(count<3000)?(count++):(count=3000); //计数器累加并限幅
}
} 本帖最后由 晓飛飛 于 2024-7-1 00:12 编辑
目前AI对问题的理解能力还是差了点,我按你的要求手搓了一点代码,可以实现5档PWM调节,实测可以的,你参考一下。
大概花了我二十分钟搞这个,还是有点不熟练。
160
/*
本例程基于STC8H8K64U-QFN32核心板编写
使用PWM4_2对应的P2.6和P2.7驱动板载LED指示灯
*/
#include "stc8h.h"
#include "intrins.h"
#define MAIN_Fosc 24000000L
unsigned char PWM_SAVE;
sbit key = P3^2;
bit key_flag;
unsigned char PWM_MODE;
unsigned char time_out;
void PWM_init(void)
{
PWMA_CCER2 = 0x00; //写CCMRx前必须先清零CCERx关闭通道
PWMA_CCMR4 = 0x60; //设置CC1为PWMA输出模式
PWMA_PS = 0x40;
//PWMA_CCER1 = 0x01; //使能CC1通道正极
//PWMA_CCER1 = 0x05; //使能CC1通道双极
PWMA_CCER2 = 0x50; //使能CC4通道双极
//PWMA_CCR1 = (MAIN_Fosc / fq / 2) - 1; //设置占空比时间1~65535
PWMA_CCR4 = 0;
PWMA_ARR = 12000; //设置周期时间 1~65535
//PWMA_ENO = 0x01; //使能PWM1P端口输出
//PWMA_ENO = 0x03; //使能PWM1P+N端口输出
PWMA_ENO = 0xC0; //使能PWM4P+N端口输出
PWMA_PSCR = 0; //PWM时钟预分频寄存器 0~65535
PWMA_BKR = 0x80; //使能主输出
PWMA_CR1 = 0x01; //开始计时
}
void PWM_updata(unsigned char duty) //duty取值0~100,duty = 0时,关闭输出,PWM端口释放为普通IO
{
if(duty > 0) //
{
PWMA_CCR4 = duty * 120;
PWMA_ENO = 0xC0;
PWMA_BKR = 0x80; //使能主输出
PWMA_CR1 = 0x01; //开始计时
}
else
{
PWMA_BKR = 0x00; //关主输出
PWMA_CR1 = 0x00; //停止计时
PWMA_ENO &= ~0xC0; //关闭PWM端口
P26 = 1;P27 = 1;
}
}
void Timer4_Isr(void) interrupt 20
{
static unsigned char key_sta;
switch(key_sta) //按键检测状态机
{
case 0:
if (key == 0) key_sta++;//如果有按键 跳下一个模式
break;
case 1:
if (key == 0) key_sta++;//如果持续按键 跳下一个模式
else key_sta = 0;
break;
case 2:
if (key == 1) key_sta++;//如果按键释放 跳下一个模式
break;
case 3:
key_flag = 1;
key_sta = 0;
break;
default:
key_sta = 0;
break;
}
if (time_out < 60) time_out++; //50ms x 60 = 3000ms = 3秒,这里是超时计数器
}
void Timer4_Init(void) //50毫秒@24.000MHz
{
TM4PS = 0x01; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
T4T3M &= 0xDF; //定时器时钟12T模式
T4L = 0xB0; //设置定时初始值
T4H = 0x3C; //设置定时初始值
T4T3M |= 0x80; //定时器4开始计时
IE2 |= 0x40; //使能定时器4中断
}
void main()
{
EAXSFR(); //
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
PWM_init();
Timer4_Init();
EA = 1;
while(1)
{
if(key_flag) //如果有按键事件
{
key_flag = 0;//清按键标记
if (time_out < 60)//按键还没超时
{
PWM_MODE++;
if(PWM_MODE > 5) PWM_MODE = 1;
PWM_updata(PWM_MODE*20);
time_out = 0;
}
else //按键超时了
{
if(PWM_MODE) //有输出状态时关闭输出
{
PWM_SAVE = PWM_MODE;//保存当前状态 //可以移植代码保存到EEPROM
PWM_MODE = 0;
PWM_updata(0);
}
else //关闭状态时恢复之前的PWM
{
if(PWM_SAVE == 0) PWM_SAVE = 1;//首次按键启动最低亮度
PWM_MODE = PWM_SAVE; //恢复之前的PWM //可以移植代码从EEPROM读取
time_out = 0;
PWM_updata(PWM_MODE*20);
}
}
}
}
}
页:
[1]
2