久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2268|回復: 38
收起左側

求個手電 斷電時長判斷的單片機代碼可以嗎?

  [復制鏈接]
ID:1130333 發表于 2024-8-11 00:33 | 顯示全部樓層 |閱讀模式
stc單片機.控制pwm占空比的代碼?
現在沒弄懂半按這個怎么判定!!!
半按.png
回復

使用道具 舉報

ID:879348 發表于 2024-8-12 08:09 | 顯示全部樓層
我做過電筒一段時間,這個需要硬件判斷關機時間,STC做這種功能不是很方便,需要的硬件比較多
回復

使用道具 舉報

ID:161164 發表于 2024-8-12 10:30 | 顯示全部樓層
如果要測關機時間就要加電容電阻來檢測掉電時間
上電時引腳輸入模式,檢測電容電平,
檢測完后引腳轉為輸出模式對電容充電
電容并聯一個電阻來讓電容在關電時放電
回復

使用道具 舉報

ID:1130333 發表于 2024-8-13 09:59 | 顯示全部樓層
wufa1986 發表于 2024-8-12 08:09
我做過電筒一段時間,這個需要硬件判斷關機時間,STC做這種功能不是很方便,需要的硬件比較多

用哪個比較方便呢?
我見很多手電用的都是九齊或者應廣
回復

使用道具 舉報

ID:1130333 發表于 2024-8-13 10:00 | 顯示全部樓層
wufa1986 發表于 2024-8-12 08:09
我做過電筒一段時間,這個需要硬件判斷關機時間,STC做這種功能不是很方便,需要的硬件比較多

可以提供一份代碼給我嗎?
謝謝
回復

使用道具 舉報

ID:1130333 發表于 2024-8-13 10:01 | 顯示全部樓層
lkc8210 發表于 2024-8-12 10:30
如果要測關機時間就要加電容電阻來檢測掉電時間
上電時引腳輸入模式,檢測電容電平,
檢測完后引腳轉為輸 ...

能否提供一份代碼?
我做的另一個手電是 要開機3秒才能判定是否eeprom保存
回復

使用道具 舉報

ID:161164 發表于 2024-8-13 11:30 | 顯示全部樓層
vb2002 發表于 2024-8-13 10:01
能否提供一份代碼?
我做的另一個手電是 要開機3秒才能判定是否eeprom保存
  1. sbit CAP = P3^2;
  2. u8 mode = 0;
  3. void main()
  4. {
  5.         mode = IapRead(EEPromAddr);
  6.         if(CAP)
  7.         {
  8.                 mode++;
  9.                 if(mode>=4)mode=0;
  10.                 IapProgram(EEPromAddr,mode);
  11.         }
  12.         P3M0 = 0x04; P3M1 = 0x00; //P32推挽輸出對電容充電

  13.         switch (mode)
  14.         {
  15.                 case 0:
  16.                         break;
  17.                 case 1:
  18.                         break;
  19.                 case 2:
  20.                         break;
  21.                 case 3:
  22.                         break;
  23.                 default:
  24.                         break;
  25.         }
  26.     while (1)
  27.     {
  28.         }
  29. }
復制代碼
回復

使用道具 舉報

ID:404160 發表于 2024-8-15 12:35 | 顯示全部樓層
根據提供的描述,我們需要編寫一段C51代碼來實現以下功能:

按下開關開機,再次按下關機,這個過程中PWM亮度保持不變,即只讀取EEPROM中的值。
如果在開機狀態下,半按(斷電時間小于500ms)則進入下一個狀態,切換PWM的占空比,實現4個檔位的循環切換。
如果關機時長大于3秒,則寫入當前的PWM占空比到EEPROM;如果小于3秒,則寫入新的EEPROM值。
如果關機后馬上開機,不進行任何操作。
下面是一段簡化的C51代碼示例,用于實現上述功能。請注意,這只是一個基礎示例,實際應用中可能需要根據具體的硬件和EEPROM庫進行調整。

#include <reg51.h>

#define PWM_PIN P1 // 假設PWM控制引腳連接到P1端口
#define BUTTON_PIN P3_2 // 假設按鈕連接到P3.2端口
#define EEPROM_ADDR 0x30 // 假設EEPROM寫入地址

unsigned char pwm_duty = 10; // PWM占空比
unsigned char pwm_level = 0; // 當前PWM級別
unsigned char eeprom_value = 0; // 從EEPROM讀取的值
bit is_power_on = 0; // 電源狀態標志

void DelayMs(unsigned int ms) {
    // 延時函數,需要根據實際的晶振頻率調整
    // 這里只是一個示例,具體實現需要根據硬件來編寫
}

void SetPWM(unsigned char duty) {
    // 設置PWM占空比的函數
    // 這里只是一個示例,具體實現需要根據硬件來編寫
}

void EEPROMWrite(unsigned char addr, unsigned char value) {
    // 寫入EEPROM的函數
    // 這里只是一個示例,具體實現需要根據EEPROM庫來編寫
    EERDB = value; // 設置EEPROM數據寄存器
    EEMPE = 1;    // 允許EEPROM編程
    EENH = 0;     // 選擇高8位地址
    EEL = 1;      // 選擇低8位地址
    EEAR = addr;  // 設置EEPROM地址寄存器
    EEWE = 1;     // 寫入使能
    EEWE = 0;     // 清除寫入使能
}

unsigned char EEPROMRead(unsigned char addr) {
    // 從EEPROM讀取的函數
    EEAR = addr; // 設置EEPROM地址寄存器
    EEN2 = 1;    // 啟用EEPROM
    EEN1 = 1;
    EEN0 = 1;
    unsigned char value = EERDB; // 讀取數據
    EEN2 = 0;
    EEN1 = 0;
    EEN0 = 0;
    return value;
}

void main() {
    SetPWM(eeprom_value); // 初始設置PWM為EEPROM中的值
    while(1) {
        if (!BUTTON_PIN) { // 檢測按鈕是否被按下
            DelayMs(20); // 消抖
            if (!BUTTON_PIN) {
                if (is_power_on) {
                    // 關機操作
                    unsigned int shutdown_time = 0;
                    while (!BUTTON_PIN) {
                        shutdown_time++;
                        if (shutdown_time > 3000) { // 大于3秒
                            EEPROMWrite(EEPROM_ADDR, pwm_duty);
                            break;
                        }
                    }
                    SetPWM(0); // 關閉PWM
                    is_power_on = 0;
                } else {
                    // 開機操作
                    is_power_on = 1;
                    SetPWM(pwm_duty); // 根據EEPROM設置PWM
                }
            }
        } else {
            if (is_power_on) {
                // 半按操作,切換PWM占空比
                DelayMs(500); // 等待500ms
                if (BUTTON_PIN) {
                    pwm_level++;
                    if (pwm_level > 3) {
                        pwm_level = 0;
                    }
                    pwm_duty = (pwm_duty + 20) % 101; // 增加20%,循環4個級別
                    SetPWM(pwm_duty);
                }
            }
        }
    }
}
回復

使用道具 舉報

ID:1130333 發表于 2024-8-16 13:06 | 顯示全部樓層
飛云居士 發表于 2024-8-15 12:35
根據提供的描述,我們需要編寫一段C51代碼來實現以下功能:

按下開關開機,再次按下關機,這個過程中PWM ...

感覺這個像是ai寫的.
而且里面提到的是3秒
回復

使用道具 舉報

ID:1110945 發表于 2024-8-16 16:41 | 顯示全部樓層
本帖最后由 明日之星8 于 2024-8-16 17:38 編輯

加二極管和電池(比如2032電池),檢測到無外接供電時單片機
就進入掉電模式,同時打開掉電喚醒定時器并計時。
比如STC8H1K08可以做到2微安,2032電池可以連續計時三到五年以上,
時間誤差不到10%

有RTC功能的單片機(比如STC8H1K08T),外接32k晶振可以做到相對精確的計時。
回復

使用道具 舉報

ID:1130333 發表于 2024-8-18 00:43 | 顯示全部樓層
明日之星8 發表于 2024-8-16 16:41
加二極管和電池(比如2032電池),檢測到無外接供電時單片機
就進入掉電模式,同時打開掉電喚醒定時器并計時 ...

這個不符合實際情況啊
實際情況就是一個18650電池, 加一個燈珠,中間有個驅動.
再要去弄其他電池麻煩哦.
回復

使用道具 舉報

ID:401564 發表于 2024-8-19 13:03 | 顯示全部樓層
首先,你要清楚你的要求是什么,在我的印象中,沒有什么手電是對關機斷電時長有要求的
按照正常的實際情況操作是這樣的:
1,先看你18650是怎么接在電路上的,如果是焊線的,那就不需要用到EEPROM,直接保存到一個全局變量就可以了,如果涉及充電,這個變量就得有三個工作模式:1點燈,2充電,3關機
STC進入掉電模式,喚醒后全局變量的值是不會變的
2,如果電池是可以拿出來的那種,那就是每次按下按鍵,點燈模式切換后就把點燈模式保存到EEPROM,下次開機時,先讀取EEPROM的模式,再進行點燈
但有一點要記得,STC的是"EEPROM"是FLASH,不是像24C01那種的,百度一下就知道了
回復

使用道具 舉報

ID:1130333 發表于 2024-8-20 10:42 | 顯示全部樓層
Y_G_G 發表于 2024-8-19 13:03
首先,你要清楚你的要求是什么,在我的印象中,沒有什么手電是對關機斷電時長有要求的
按照正常的實際情況操 ...

手電開關有兩種.
你說的那種是電子開關的.可以長期不斷電.不設計eeprom也可以保存檔位
我說的這個是機械開關,就是開關裝在尾部,依靠斷電通電來開關手電的
市面銷售的開關邏輯是, 123檔,現在我調到2檔,關機,下次開機也是2檔. 如果想換擋,就開機關機(時間低于500ms就換擋到3檔) 如果超過500ms就還是2檔

現在我能實現的就是,開機 2檔,超過3秒就eeprom保存當前2檔,,如果開機3秒內在關機開機.那就進行換擋.
雖然都能達到目的, 但是我這個有點麻煩,如果開機超過3秒后,需要換擋,必須重新關機開機,再關機開機換擋.

如果您感興趣,發視頻給您看看?

回復

使用道具 舉報

ID:401564 發表于 2024-8-20 12:01 | 顯示全部樓層
vb2002 發表于 2024-8-20 10:42
手電開關有兩種.
你說的那種是電子開關的.可以長期不斷電.不設計eeprom也可以保存檔位
我說的這個是機 ...

斷電了,單片機就沒有用了,就沒有"斷電時間"這個概念了
如果要有記憶功能,就只能是重新關機開機,再關機開機換擋
沒有別的選擇了,除非換開關種類
回復

使用道具 舉報

ID:384109 發表于 2024-8-20 13:05 | 顯示全部樓層
感覺你這個想復雜了吧,跟普通手電操作一樣,只不過增加一個標志而已
回復

使用道具 舉報

ID:161164 發表于 2024-8-20 14:22 | 顯示全部樓層
vb2002 發表于 2024-8-20 10:42
手電開關有兩種.
你說的那種是電子開關的.可以長期不斷電.不設計eeprom也可以保存檔位
我說的這個是機 ...

試了我的代碼了嗎?
回復

使用道具 舉報

ID:23640 發表于 2024-8-20 15:55 | 顯示全部樓層
樓主可以在MCU供電腳串一個二極管,MCU供電加個幾微法的大電容,加二極管的目的就是防止開關斷開后電容給后級供電,只要滿足電容只給MCU供電,即使外部電源斷了,幾微法的電容也可以維持幾秒鐘時間,這時候你就可以做些判斷保存數據的動作
回復

使用道具 舉報

ID:1130333 發表于 2024-8-20 16:42 | 顯示全部樓層
lkc8210 發表于 2024-8-20 14:22
試了我的代碼了嗎?

試了,試出來就是普通的eeprom讀寫switch里面的循環.
沒有加電容實現不了那個半按..
回復

使用道具 舉報

ID:69038 發表于 2024-8-20 16:43 | 顯示全部樓層
咋看都象是一個按鍵實現開機、關機、調亮度的功能。。。
回復

使用道具 舉報

ID:1130333 發表于 2024-8-20 16:45 | 顯示全部樓層
人中狼 發表于 2024-8-20 13:05
感覺你這個想復雜了吧,跟普通手電操作一樣,只不過增加一個標志而已

我能想通,但是代碼搞不定.
標志位就是斷電那個狀態怎么讀取出來.
之前有人發了一個帖子,,當時我還不懂啥意思,都已經斷電了.為啥還要在斷電的時候開啟睡眠模式.
現在懂了.是讓電容繼續給單片機供電
回復

使用道具 舉報

ID:69038 發表于 2024-8-20 16:46 | 顯示全部樓層
倒不如關機后短按開機、開機后短按切換亮度、長按關機。。。
回復

使用道具 舉報

ID:1130333 發表于 2024-8-20 16:51 | 顯示全部樓層
yaosongjin 發表于 2024-8-20 15:55
樓主可以在MCU供電腳串一個二極管,MCU供電加個幾微法的大電容,加二極管的目的就是防止開關斷開后電容給后 ...

如果設置睡眠模式,是不是10uf可以堅持很久很久?
甚至都不用eeprom都行了?
就是這個斷電判斷不會弄
回復

使用道具 舉報

ID:161164 發表于 2024-8-20 17:13 | 顯示全部樓層
vb2002 發表于 2024-8-20 16:42
試了,試出來就是普通的eeprom讀寫switch里面的循環.
沒有加電容實現不了那個半按..

為啥不加電容?
回復

使用道具 舉報

ID:23640 發表于 2024-8-20 17:39 | 顯示全部樓層
vb2002 發表于 2024-8-20 16:51
如果設置睡眠模式,是不是10uf可以堅持很久很久?
甚至都不用eeprom都行了?
就是這個斷電判斷不會弄

MCU第4腳用于判斷開關狀態。
5fee380a84e8dab4c9fc65f1daf0e8ca.png
回復

使用道具 舉報

ID:23640 發表于 2024-8-20 17:42 | 顯示全部樓層
5fee380a84e8dab4c9fc65f1daf0e8ca.png 圖中MCU第4腳用于判斷開關狀態,開關斷開4腳是低電平,開關接通4腳是高電平。
回復

使用道具 舉報

ID:1130333 發表于 2024-8-20 18:47 | 顯示全部樓層
lkc8210 發表于 2024-8-20 17:13
為啥不加電容?


這個是我的代碼, 現在可以變相換擋和保存的 ..電路圖是這個,電容直接替換那個0.1uf嗎?

手電.PNG

  1. #include "stc8h.h"
  2. #include "intrins.h"
  3. #include "eeprom.h"
  4. #include <stdio.h>



  5. #define MAIN_Fosc 11059200UL
  6. #define BRT         (65536 - MAIN_Fosc / 115200 / 4)
  7. //#define EEPROMId           0x0E00

  8. typedef unsigned char u8;
  9. typedef unsigned int u16;


  10. u8 PWMData[] = {1,5,33,};//添加數組,設置需要的檔位
  11. u16 delayTime = 3000;//這里修改需要的工作時間,單位(ms)


  12. u8 dat;
  13. u16 EEPROMId = 0020;
  14. u16 time;

  15. bit key_flag;

  16. void delayms(u16 ms);   
  17. void sys_init();
  18. void PWM_init(void);
  19. void Timer0_Init(void);


  20. void UartInit()
  21. {
  22.     SCON = 0x5a;
  23.     T2L = BRT;
  24.     T2H = BRT >> 8;
  25.     AUXR = 0x15;
  26. }

  27. u8 LEDControl()
  28. {       
  29.         u8 i;
  30.         u8 length = (sizeof(PWMData)/sizeof(PWMData[0]));
  31.                 delayms(20);
  32. //        u16 EEPROMId = 0XE00;                                //將指針指向第8扇區的第一個字節
  33. //        SetMode(CMD_READ);                                //設置為讀取數據
  34.        
  35.         while(1)
  36.         {       
  37.                 dat = IapRead(EEPROMId + 1);                        //讀取下一字節數據255
  38. //                printf("dat=%bu\r\n",dat);
  39. //                printf("id=%u\r\n",EEPROMId);               
  40.                 if(dat == 0XFF)                                        //下一字節字節未寫入數據255
  41.                 {
  42.                         dat = IapRead(EEPROMId);                //讀取當前字節數據
  43. //                        SetMode(CMD_PROGRAM);                        //寫入數據
  44.                        
  45.                         for(i = 0; i < length-1; i++)
  46.                         {        if(dat == i)
  47.                                 {        IapProgram(EEPROMId+1,i+1);
  48.                                         return dat;
  49.                                 }
  50.                         }
  51. //                        dat=0;
  52.                         IapProgram(EEPROMId+1,0);
  53.                          
  54.                         return dat;                                        //返回當前字節數據
  55.                 }
  56.         else                                                        //下一字節不為空,指針加一,繼續判斷下一個字節
  57.                 {        EEPROMId++;
  58.                 }


  59.                 if(EEPROMId >= 0XFFD)                                //如果當前字節到達EEPROM末尾,擦除扇區所有數據
  60.                 {       
  61. //                        SetMode(CMD_ERASE);                        //扇區擦除
  62.                         IapErase(0x0000);                                //擦除扇區
  63.                         IapErase(0x0200);                                //擦除扇區       
  64.                         IapErase(0x0400);                                //擦除扇區       
  65.                         IapErase(0x0600);                                //擦除扇區       
  66.                         IapErase(0x0800);                                //擦除扇區       
  67.                         IapErase(0x0A00);                                //擦除扇區       
  68.                         IapErase(0x0C00);                                //擦除扇區       
  69.                         IapErase(0x0E00);                                //擦除扇區                               
  70.                         return 1;
  71.                 }
  72.         }
  73. }


  74. void main()
  75. {               

  76.         sys_init();  

  77.       UartInit();
  78.        
  79.     LEDControl();
  80.                      PWM_init();
  81.        
  82.                 PWMA_CCR1 = PWMData[dat] ;  

  83.           while(1)
  84.         {



  85.         }       
  86. }



  87. void sys_init(void)
  88. {
  89.         P_SW2=0x80;

  90.     P3M0 = 0x00; P3M1 = 0x00;       P1M0 = 0x00; P1M1 = 0x00;
  91.        
  92.   
  93.          Timer0_Init();
  94.        
  95.         IT0=1;EX0=1;
  96.         INTCLKO|=0x40;   //EX4=1; 允許INT4外部中斷
  97. //        IP2H=0x00;               
  98.         IP2=0x10;

  99.        
  100.         EA=1;                        //打開總中斷

  101. }


  102. //// 初始化PWM功能
  103. void PWM_init(void) {
  104.     PWMA_CCER1 = 0x00;                          // 寫CCMRx前必須先清零CCERx關閉通道
  105.     PWMA_CCMR1 = 0x60;                          // 設置CC1為PWMA輸出模式
  106.     PWMA_PS        = 0x00;                      //  
  107.     PWMA_CCER1 = 0x0c;                          // 使能CC4通道雙極
  108.     PWMA_CCR1 = 0;                              // 初始化CCR4計數值為0
  109.     PWMA_ARR = 256;                           // 設置周期時間為12000個計數周期
  110.     PWMA_ENO = 0x02;                            // 使能PWM4P+N端口輸出
  111.     PWMA_PSCR = 0;                              // PWM時鐘預分頻寄存器設置為0
  112.     PWMA_BKR = 0x80;                            // 使能主輸出
  113.     PWMA_CR1 = 0x01;                            // 開始計時
  114.        
  115. }


  116. u8 TimeNum = 1;//這里是定時器中斷時間,單位(ms)

  117. void Timer0_Isr(void) interrupt 1
  118. {        u8 Num = delayTime/TimeNum;//中斷執行多少次到達工作時間
  119.         if(time < Num)
  120.         {        time++;
  121.         }else if(time == Num)        //到達要求的時間
  122.         {       
  123.                 IapProgram(EEPROMId+2,dat);
  124.                 time++;
  125.         }
  126. }

  127. void Timer0_Init(void)                //1毫秒@11.0592MHz
  128. {
  129.         AUXR |= 0x80;                        //定時器時鐘1T模式
  130.         TMOD &= 0xF0;                        //設置定時器模式
  131.         TL0 = 0xCD;                                //設置定時初始值
  132.         TH0 = 0xD4;                                //設置定時初始值
  133.         TF0 = 0;                                //清除TF0標志
  134.         TR0 = 1;                                //定時器0開始計時
  135.         ET0 = 1;                                //使能定時器0中斷
  136. }


  137. void INT4_Isr(void) interrupt 16
  138. {
  139. IAP_CONTR=0x60;                       
  140. }


  141. void INT0_Isr(void) interrupt 0
  142. {
  143.                   printf("dat=%bu\n",dat);
  144.                 printf("id=%u\n",EEPROMId);               
  145. }

  146. void delayms(u16 ms)
  147.         {u16 i;
  148.         do{
  149.                 i = MAIN_Fosc /10000;
  150.                 while(--i);
  151.         }                while(--ms);
  152. }
  153.        
復制代碼



回復

使用道具 舉報

ID:1130333 發表于 2024-8-20 18:49 | 顯示全部樓層
yaosongjin 發表于 2024-8-20 17:39
MCU第4腳用于判斷開關狀態。

主要是代碼方面弄不好.
  1. #include "stc8h.h"
  2. #include "intrins.h"
  3. #include "eeprom.h"
  4. #include <stdio.h>



  5. #define MAIN_Fosc 11059200UL
  6. #define BRT         (65536 - MAIN_Fosc / 115200 / 4)
  7. //#define EEPROMId           0x0E00

  8. typedef unsigned char u8;
  9. typedef unsigned int u16;


  10. u8 PWMData[] = {1,5,33,};//添加數組,設置需要的檔位
  11. u16 delayTime = 3000;//這里修改需要的工作時間,單位(ms)


  12. u8 dat;
  13. u16 EEPROMId = 0020;
  14. u16 time;

  15. bit key_flag;

  16. void delayms(u16 ms);   
  17. void sys_init();
  18. void PWM_init(void);
  19. void Timer0_Init(void);


  20. void UartInit()
  21. {
  22.     SCON = 0x5a;
  23.     T2L = BRT;
  24.     T2H = BRT >> 8;
  25.     AUXR = 0x15;
  26. }

  27. u8 LEDControl()
  28. {       
  29.         u8 i;
  30.         u8 length = (sizeof(PWMData)/sizeof(PWMData[0]));
  31.                 delayms(20);
  32. //        u16 EEPROMId = 0XE00;                                //將指針指向第8扇區的第一個字節
  33. //        SetMode(CMD_READ);                                //設置為讀取數據
  34.        
  35.         while(1)
  36.         {       
  37.                 dat = IapRead(EEPROMId + 1);                        //讀取下一字節數據255
  38. //                printf("dat=%bu\r\n",dat);
  39. //                printf("id=%u\r\n",EEPROMId);               
  40.                 if(dat == 0XFF)                                        //下一字節字節未寫入數據255
  41.                 {
  42.                         dat = IapRead(EEPROMId);                //讀取當前字節數據
  43. //                        SetMode(CMD_PROGRAM);                        //寫入數據
  44.                        
  45.                         for(i = 0; i < length-1; i++)
  46.                         {        if(dat == i)
  47.                                 {        IapProgram(EEPROMId+1,i+1);
  48.                                         return dat;
  49.                                 }
  50.                         }
  51. //                        dat=0;
  52.                         IapProgram(EEPROMId+1,0);
  53.                          
  54.                         return dat;                                        //返回當前字節數據
  55.                 }
  56.         else                                                        //下一字節不為空,指針加一,繼續判斷下一個字節
  57.                 {        EEPROMId++;
  58.                 }


  59.                 if(EEPROMId >= 0XFFD)                                //如果當前字節到達EEPROM末尾,擦除扇區所有數據
  60.                 {       
  61. //                        SetMode(CMD_ERASE);                        //扇區擦除
  62.                         IapErase(0x0000);                                //擦除扇區
  63.                         IapErase(0x0200);                                //擦除扇區       
  64.                         IapErase(0x0400);                                //擦除扇區       
  65.                         IapErase(0x0600);                                //擦除扇區       
  66.                         IapErase(0x0800);                                //擦除扇區       
  67.                         IapErase(0x0A00);                                //擦除扇區       
  68.                         IapErase(0x0C00);                                //擦除扇區       
  69.                         IapErase(0x0E00);                                //擦除扇區                               
  70.                         return 1;
  71.                 }
  72.         }
  73. }


  74. void main()
  75. {               

  76.         sys_init();  

  77.       UartInit();
  78.        
  79.     LEDControl();
  80.                      PWM_init();
  81.        
  82.                 PWMA_CCR1 = PWMData[dat] ;  

  83.           while(1)
  84.         {



  85.         }       
  86. }



  87. void sys_init(void)
  88. {
  89.         P_SW2=0x80;

  90.     P3M0 = 0x00; P3M1 = 0x00;       P1M0 = 0x00; P1M1 = 0x00;
  91.        
  92.   
  93.          Timer0_Init();
  94.        
  95.         IT0=1;EX0=1;
  96.         INTCLKO|=0x40;   //EX4=1; 允許INT4外部中斷
  97. //        IP2H=0x00;               
  98.         IP2=0x10;

  99.        
  100.         EA=1;                        //打開總中斷

  101. }


  102. //// 初始化PWM功能
  103. void PWM_init(void) {
  104.     PWMA_CCER1 = 0x00;                          // 寫CCMRx前必須先清零CCERx關閉通道
  105.     PWMA_CCMR1 = 0x60;                          // 設置CC1為PWMA輸出模式
  106.     PWMA_PS        = 0x00;                      //  
  107.     PWMA_CCER1 = 0x0c;                          // 使能CC4通道雙極
  108.     PWMA_CCR1 = 0;                              // 初始化CCR4計數值為0
  109.     PWMA_ARR = 256;                           // 設置周期時間為12000個計數周期
  110.     PWMA_ENO = 0x02;                            // 使能PWM4P+N端口輸出
  111.     PWMA_PSCR = 0;                              // PWM時鐘預分頻寄存器設置為0
  112.     PWMA_BKR = 0x80;                            // 使能主輸出
  113.     PWMA_CR1 = 0x01;                            // 開始計時
  114.        
  115. }


  116. u8 TimeNum = 1;//這里是定時器中斷時間,單位(ms)

  117. void Timer0_Isr(void) interrupt 1
  118. {        u8 Num = delayTime/TimeNum;//中斷執行多少次到達工作時間
  119.         if(time < Num)
  120.         {        time++;
  121.         }else if(time == Num)        //到達要求的時間
  122.         {       
  123.                 IapProgram(EEPROMId+2,dat);
  124.                 time++;
  125.         }
  126. }

  127. void Timer0_Init(void)                //1毫秒@11.0592MHz
  128. {
  129.         AUXR |= 0x80;                        //定時器時鐘1T模式
  130.         TMOD &= 0xF0;                        //設置定時器模式
  131.         TL0 = 0xCD;                                //設置定時初始值
  132.         TH0 = 0xD4;                                //設置定時初始值
  133.         TF0 = 0;                                //清除TF0標志
  134.         TR0 = 1;                                //定時器0開始計時
  135.         ET0 = 1;                                //使能定時器0中斷
  136. }


  137. void INT4_Isr(void) interrupt 16
  138. {
  139. IAP_CONTR=0x60;                       
  140. }


  141. void INT0_Isr(void) interrupt 0
  142. {
  143.                   printf("dat=%bu\n",dat);
  144.                 printf("id=%u\n",EEPROMId);               
  145. }

  146. void delayms(u16 ms)
  147.         {u16 i;
  148.         do{
  149.                 i = MAIN_Fosc /10000;
  150.                 while(--i);
  151.         }                while(--ms);
  152. }
  153.        
復制代碼
回復

使用道具 舉報

ID:23640 發表于 2024-8-21 08:38 | 顯示全部樓層
vb2002 發表于 2024-8-20 18:49
主要是代碼方面弄不好.

你可能沒搞清楚程序運行的邏輯,按照這個電路來操作的話:
1.上電后MCU復位進入工作狀態
2.當按下電源開關后MCU開始記錄4腳電平保持的時間
3.假如維持的低電平為500MS又變高了,就切換模式或者亮度之類的功能并且寫入內存
4.假如維持的電平超過500MS說明是手電要關機,就不再做任何處理
5.如果要做雙擊的話,同樣在按鍵處理這一塊想辦法
回復

使用道具 舉報

ID:161164 發表于 2024-8-21 11:11 | 顯示全部樓層
vb2002 發表于 2024-8-20 18:47
這個是我的代碼, 現在可以變相換擋和保存的 ..電路圖是這個,電容直接替換那個0.1uf嗎?

我的代碼是檢測P32腳電容的電平來判斷掉電時間的
回復

使用道具 舉報

ID:1130333 發表于 2024-8-21 22:01 | 顯示全部樓層
lkc8210 發表于 2024-8-21 11:11
我的代碼是檢測P32腳電容的電平來判斷掉電時間的

按您的代碼現在一直是亮度5,可以點亮
但是不能換擋. 能幫看看嗎?  是我沒有上真機實驗嗎? 我用的開發板弄的
  1. #include "stc8h.h"
  2. #include "intrins.h"
  3. #include "eeprom.h"
  4. #include <stdio.h>



  5. #define MAIN_Fosc 11059200UL
  6. #define BRT         (65536 - MAIN_Fosc / 115200 / 4)
  7. //#define EEPROMId           0x0E00

  8. typedef unsigned char u8;
  9. typedef unsigned int u16;


  10. //u8 PWMData[] = {1,5,33,};//添加數組,設置需要的檔位
  11. //u16 delayTime = 1000;//這里修改需要的工作時間,單位(ms)


  12. u8 dat;
  13. //u16 EEPROMId = 0020;
  14. u16 EEPromAddr;
  15. u16 time;
  16. u8 mode = 0;
  17. sbit CAP = P3^2;
  18. // bit key_flag;


  19. void delayms(u16 ms);   
  20. void sys_init();
  21. void PWM_init(void);
  22. void Timer0_Init(void);


  23. void UartInit()
  24. {
  25.     SCON = 0x5a;
  26.     T2L = BRT;
  27.     T2H = BRT >> 8;
  28.     AUXR = 0x15;
  29. }

  30. //u8 LEDControl()
  31. //{       
  32. //        u8 i;
  33. //        u8 length = (sizeof(PWMData)/sizeof(PWMData[0]));
  34. //                delayms(20);
  35. ////        u16 EEPROMId = 0XE00;                                //將指針指向第8扇區的第一個字節
  36. ////        SetMode(CMD_READ);                                //設置為讀取數據
  37. //       
  38. //        while(1)
  39. //        {       
  40. //                dat = IapRead(EEPROMId + 1);                        //讀取下一字節數據255
  41. ////                printf("dat=%bu\r\n",dat);
  42. ////                printf("id=%u\r\n",EEPROMId);               
  43. //                if(dat == 0XFF)                                        //下一字節字節未寫入數據255
  44. //                {
  45. //                        dat = IapRead(EEPROMId);                //讀取當前字節數據
  46. ////                        SetMode(CMD_PROGRAM);                        //寫入數據
  47. //                       
  48. //                        for(i = 0; i < length-1; i++)
  49. //                        {        if(dat == i)
  50. //                                {       
  51. //                                        IapProgram(EEPROMId+1,i+1);
  52. ////                                        IapRead(EEPROMId );
  53. //                                        return dat;
  54. //                                }
  55. //                        }
  56. ////                        dat=0;
  57. //                        IapProgram(EEPROMId+1,0);
  58. //                         
  59. //                        return dat;                                        //返回當前字節數據
  60. //                }
  61. //        else                                                        //下一字節不為空,指針加一,繼續判斷下一個字節
  62. //                {        EEPROMId++;
  63. //                }


  64. //                if(EEPROMId >= 0XFFD)                                //如果當前字節到達EEPROM末尾,擦除扇區所有數據
  65. //                {       
  66. ////                        SetMode(CMD_ERASE);                        //扇區擦除
  67. //                        IapErase(0x0000);                                //擦除扇區
  68. //                        IapErase(0x0200);                                //擦除扇區       
  69. //                        IapErase(0x0400);                                //擦除扇區       
  70. //                        IapErase(0x0600);                                //擦除扇區       
  71. //                        IapErase(0x0800);                                //擦除扇區       
  72. //                        IapErase(0x0A00);                                //擦除扇區       
  73. //                        IapErase(0x0C00);                                //擦除扇區       
  74. //                        IapErase(0x0E00);                                //擦除扇區                               
  75. //                        return 1;
  76. //                }
  77. //        }
  78. //}


  79. void main()
  80. {               

  81.         sys_init();  

  82.       UartInit();
  83.        
  84. //     LEDControl();
  85.                      PWM_init();
  86.        
  87. //                PWMA_CCR1 = PWMData[dat] ;  

  88.           mode = IapRead(EEPromAddr);
  89.         if(CAP)
  90.         {
  91.                 mode++;
  92.                 if(mode>=4)mode=0;
  93.                 IapProgram(EEPromAddr,mode);
  94.         }
  95.         P3M0 = 0x04; P3M1 = 0x00; //P32推挽輸出對電容充電

  96.         switch (mode)
  97.         {
  98.                 case 0: PWMA_CCR1 = 2 ;  
  99.                         break;
  100.                 case 1: PWMA_CCR1 = 5 ;  
  101.                         break;
  102.                 case 2: PWMA_CCR1 = 12 ;  
  103.                         break;
  104.                 case 3: PWMA_CCR1 = 32 ;  
  105.                         break;
  106.                 default: PWMA_CCR1 = 112 ;  
  107.                         break;
  108.           }

  109.           while(1)
  110.         {
  111. //           PWMA_CCR1 = mode ;  


  112.         }       
  113. }



  114. void sys_init(void)
  115. {
  116.         P_SW2=0x80;

  117.     P3M0 = 0x00; P3M1 = 0x00;     
  118.         P1M0 = 0x00; P1M1 = 0x00;
  119.        
  120.   
  121.          Timer0_Init();
  122.        
  123.         IT0=1;EX0=1;
  124.         INTCLKO|=0x40;   //EX4=1; 允許INT4外部中斷
  125. //        IP2H=0x00;               
  126.         IP2=0x10;

  127.        
  128.         EA=1;                        //打開總中斷

  129. }


  130. //// 初始化PWM功能
  131. void PWM_init(void) {
  132.     PWMA_CCER1 = 0x00;                          // 寫CCMRx前必須先清零CCERx關閉通道
  133.     PWMA_CCMR1 = 0x60;                          // 設置CC1為PWMA輸出模式
  134.     PWMA_PS        = 0x00;                      //  
  135.     PWMA_CCER1 = 0x0c;                          // 使能CC4通道雙極
  136.     PWMA_CCR1 = 0;                              // 初始化CCR4計數值為0
  137.     PWMA_ARR = 256;                           // 設置周期時間為12000個計數周期
  138.     PWMA_ENO = 0x02;                            // 使能PWM4P+N端口輸出
  139.     PWMA_PSCR = 0;                              // PWM時鐘預分頻寄存器設置為0
  140.     PWMA_BKR = 0x80;                            // 使能主輸出
  141.     PWMA_CR1 = 0x01;                            // 開始計時
  142.        
  143. }


  144. //u8 TimeNum = 1;//這里是定時器中斷時間,單位(ms)

  145. //void Timer0_Isr(void) interrupt 1
  146. //{        u8 Num = delayTime/TimeNum;//中斷執行多少次到達工作時間
  147. //        if(time < Num)
  148. //        {        time++;
  149. //        }else if(time == Num)        //到達要求的時間
  150. //        {       
  151. //                IapProgram(EEPROMId+2,dat);
  152. ////                IapRead(EEPROMId);
  153. //                time++;
  154. //        }
  155. //}

  156. void Timer0_Init(void)                //1毫秒@11.0592MHz
  157. {
  158.         AUXR |= 0x80;                        //定時器時鐘1T模式
  159.         TMOD &= 0xF0;                        //設置定時器模式
  160.         TL0 = 0xCD;                                //設置定時初始值
  161.         TH0 = 0xD4;                                //設置定時初始值
  162.         TF0 = 0;                                //清除TF0標志
  163.         TR0 = 1;                                //定時器0開始計時
  164.         ET0 = 1;                                //使能定時器0中斷
  165. }


  166. void INT4_Isr(void) interrupt 16
  167. {
  168. IAP_CONTR=0x60;                       
  169. }


  170. //void INT0_Isr(void) interrupt 0
  171. //{
  172. //                  printf("dat=%bu\n",mode);
  173. //                printf("id=%u\n",EEPromAddr);               
  174. //}

  175. void delayms(u16 ms)
  176.         {u16 i;
  177.         do{
  178.                 i = MAIN_Fosc /10000;
  179.                 while(--i);
  180.         }                while(--ms);
  181. }
  182.        
復制代碼
回復

使用道具 舉報

ID:1130333 發表于 2024-8-21 22:51 | 顯示全部樓層
yaosongjin 發表于 2024-8-21 08:38
你可能沒搞清楚程序運行的邏輯,按照這個電路來操作的話:
1.上電后MCU復位進入工作狀態
2.當按下電源 ...

就是代碼不會弄呢
可以給個代碼嗎?
實現半按換擋
我這個麻煩死了
回復

使用道具 舉報

ID:23640 發表于 2024-8-22 08:42 | 顯示全部樓層
vb2002 發表于 2024-8-21 22:51
就是代碼不會弄呢
可以給個代碼嗎?
實現半按換擋

我沒寫過這種代碼,但是有了具體思路不是很簡單的事情嗎?按鍵判斷的代碼本站也有很多的
回復

使用道具 舉報

ID:161164 發表于 2024-8-22 09:20 | 顯示全部樓層
vb2002 發表于 2024-8-21 22:01
按您的代碼現在一直是亮度5,可以點亮
但是不能換擋. 能幫看看嗎?  是我沒有上真機實驗嗎? 我用的開發板 ...

我那個只是示范,你還要加上之前的EEPRom循環讀寫的代碼
回復

使用道具 舉報

ID:1130333 發表于 2024-8-22 23:12 | 顯示全部樓層
lkc8210 發表于 2024-8-22 09:20
我那個只是示范,你還要加上之前的EEPRom循環讀寫的代碼

哥,我好像有一點點懂了.
我一直糾結程序上的問題.
剛剛我試了一個很垃圾的手電.好像不是代碼上的問題.
就是那個電容的問題.  我那個垃圾手電,我把電容用鉛筆涂黑了(就是短路了)
現在不能換擋,一直是那個檔位.
好像換擋取決于那個電容.. 電容的大小決定關機再開機多久時間換擋.
回復

使用道具 舉報

ID:1130333 發表于 2024-8-24 23:37 | 顯示全部樓層
lkc8210 發表于 2024-8-21 11:11
我的代碼是檢測P32腳電容的電平來判斷掉電時間的

您這個是不是電路上還有要求啊?
P32 我原本接的按鍵
回復

使用道具 舉報

ID:1130333 發表于 2024-8-24 23:41 | 顯示全部樓層
lkc8210 發表于 2024-8-22 09:20
我那個只是示范,你還要加上之前的EEPRom循環讀寫的代碼

您的代碼我之前不能換擋是因為沒有加 eeprom擦除
現在在寫前面加一句                  IapErase(EEPROMId);
就好了
但是就一直換擋,關開一次就換一次檔.不能保存當前檔位
還有哪里需要糾正嗎
回復

使用道具 舉報

ID:1130333 發表于 2024-8-25 10:20 | 顯示全部樓層
lkc8210 發表于 2024-8-22 09:20
我那個只是示范,你還要加上之前的EEPRom循環讀寫的代碼

弄好了.我在P32加了個電容到負極.
現在可以實現我說的那個功能了
超強
回復

使用道具 舉報

ID:1130333 發表于 2024-11-15 14:03 | 顯示全部樓層
lkc8210 發表于 2024-8-22 09:20
我那個只是示范,你還要加上之前的EEPRom循環讀寫的代碼

您好,代碼已經實現了.
想問下您, P32引腳那個電容需要怎么處理嗎?
P32 - 22uf電容- gnd
中間是否需要并聯電阻? 減速掉電?
或者二極管之類的處理
回復

使用道具 舉報

ID:146878 發表于 2024-11-16 13:27 | 顯示全部樓層
這種斷電換檔的手電筒爛大街了,給你個思路,單片機的RAM數據可以在極低的電壓下保持數據不變。斷電后單片機不工作了,但是RAM數據還是能保存一會的。起不到精準控制,但是實現簡單的手電筒換擋功能還行。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人精品国产一区二区4080 | 91av视频| 一区二区三区小视频 | 蜜桃视频在线观看免费视频网站www | 国产一区二区美女 | 国产精品视频 | 2018国产精品| 精品一区国产 | 精品一区二区三区免费毛片 | 男女在线免费观看 | 毛片高清| 成人国产一区二区三区精品麻豆 | 欧美精品一区在线 | 国产一区二区在线免费观看 | 中文字幕1区2区3区 亚洲国产成人精品女人久久久 | 天天艹天天干天天 | 日韩欧美在线不卡 | 在线观看中文字幕 | 国产综合精品 | 国产精品揄拍一区二区久久国内亚洲精 | 精品自拍视频在线观看 | 青青草社区 | 国产人成精品一区二区三 | 91影院| 91p在线观看 | 成人午夜视频在线观看 | 天天干夜夜操视频 | 夜夜爽99久久国产综合精品女不卡 | 福利二区 | 欧美一级欧美三级在线观看 | 欧美精品一区二区在线观看 | 天天操天天拍 | 中文字幕 亚洲一区 | 久久国产成人精品国产成人亚洲 | 亚洲精品一区二区三区 | 91.com视频| 一区二区三区国产 | 亚洲一区二区三区四区五区中文 | 精品久久久久久久久久久 | 水蜜桃久久夜色精品一区 | 亚洲久久一区 |