vb2002 发表于 2024-6-29 23:35:15

实在是没办法了,弄了一晚上了还是弄不好 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);
}




王昱顺 发表于 2024-6-30 01:42:46

你首先是你的定时器,不可以一直开着,这样就没有计时3s的意义了。
这里有一种方式,就是采用自减操作。中断先判断变量是否为0,不为零就自减一次,为零就不操作。
需要定时的地方(按键按下后)赋予延时值3s,然后再判断3s是否归零就可以了。档位需要从1开始记,这样初始化为0,方便判断第一次按下,防止直接进入关闭

vb2002 发表于 2024-6-30 08:02:26

王昱顺 发表于 2024-6-30 01:42
你首先是你的定时器,不可以一直开着,这样就没有计时3s的意义了。
这里有一种方式,就是采用自减操作。中 ...

我也怀疑是定时器的问题,
我按照你的方案再试试.看看怎么样

vb2002 发表于 2024-6-30 08:19:55

王昱顺 发表于 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);
}

xiangzichen 发表于 2024-6-30 12:10:13

代码简化一下,按下按键就
判断 noShiftTime 是不是超过3s,
如果超过,关闭,
没有超过 noShiftTime = 1,

定时器中断里面这样写:

if(noShiftTime) {
    noShiftTime ++;
}

if(noShiftTime >=3000){
    noShiftTime = 0;
}

vb2002 发表于 2024-6-30 13:01:19

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 13:47:39

本帖最后由 xiangzichen 于 2024-6-30 16:31 编辑


这里是不是应该 是 =1



还有这里,貌似应该是3000

Lkck8210 发表于 2024-6-30 14:06:03

noShiftTime 要加限制而不是清零

if(noShiftTime <3000)noShiftTime ++;
这样noShiftTime 就不会超过3000也不会溢出

网老四 发表于 2024-6-30 14:25:45

本帖最后由 网老四 于 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-6-30 22:47:49

本帖最后由 晓飛飛 于 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
查看完整版本: 实在是没办法了,弄了一晚上了还是弄不好 AI 帮人写的代码