亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 624|回復: 4
打印 上一主題 下一主題
收起左側

EEPROM存儲的數據,斷電后再上電,數據發生變化

[復制鏈接]
跳轉到指定樓層
樓主
ID:74143 發表于 2026-4-11 09:27 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
請教,EEPROM存儲的數據,斷電后再上電,數據發生變化的原因。

#include"STC8G.H"
#include"intrins.H"
#include"ADC.h"
#include"NTC.h"
#include"GPIO.h"
#include"TIMER.h"
#include"HC595_DISPLAY.h"

//==================== 引腳定義 ====================
sbit KEY_ADD  = P3^2;   // 加鍵
sbit KEY_SUB  = P1^4;   // 減鍵
sbit KEY_OK   = P1^7;   // 確認鍵

sbit BEEP     = P1^5;   // 蜂鳴器

sbit ADC_TEMP = P1^1;   

unsigned int temp_real;    // 實際溫度值
unsigned int temp_high;     // 高溫閾值
unsigned int temp_low;      // 低溫閾值
unsigned char set_mode = 0;        // 設置模式標志:0=正常模式,1=設置高溫,2=設置低溫

// EEPROM 地址定義
#define EEPROM_ADDR_H 0x0000  
#define EEPROM_ADDR_L 0x0001  
#define EEPROM_ADDR   0x0000

void IAP_IDLE(void);
unsigned char IAP_Read(unsigned int addr);
void IAP_Write(unsigned int addr,unsigned char dat);
void IAP_Erase(unsigned int addr);

// 延時函數
void Delay_ms(unsigned int ms)
{
        unsigned int i,j;
                for(i=0;i<ms;i++)
                        for(j=0;j<24*85;j++);
}


void IAP_IDLE(void)
{
        IAP_CONTR = 0;   
        IAP_CMD = 0;      
        IAP_TRIG = 0;     
        IAP_ADDRH = 0x80;
        IAP_ADDRL = 0;   
}

// 單字節讀
unsigned char IAP_Read(unsigned int addr)
{
        char dat;
        IAP_CONTR = 0x80;   
        IAP_TPS = 24;
        IAP_CMD = 0x01;   
        IAP_ADDRL = addr;   
        IAP_ADDRH = addr >> 8;
        IAP_TRIG = 0x5a;     
        IAP_TRIG = 0xa5;   
        _nop_();            
        dat = IAP_DATA;             
        IAP_IDLE();         
        return dat;
}

// 單字節寫
void IAP_Write(unsigned int addr,unsigned char dat)
{
        IAP_CONTR = 0x80;      
        IAP_TPS = 24;
        IAP_CMD = 0x02;     
        IAP_ADDRL = addr;   
        IAP_ADDRH = addr >> 8;
        IAP_DATA = dat;             
        IAP_TRIG = 0x5a;     
        IAP_TRIG = 0xa5;      
        _nop_();           
        IAP_IDLE();
}

void IAP_Erase(unsigned int addr)
{
        IAP_CONTR = 0x80;   
        IAP_TPS = 24;
        IAP_CMD   = 0x03;   
        IAP_ADDRL = addr;
        IAP_ADDRH = addr >> 8;
        IAP_TRIG  = 0x5A;
        IAP_TRIG  = 0xA5;
        _nop_();              
        IAP_IDLE();
}


void Key_Scan(void)
{
  if(KEY_OK == 0)  // 確認鍵按下
  {
    Delay_ms(20);
    if(KEY_OK == 0)
    {
      set_mode++;
      if(set_mode > 2) set_mode = 0;
      
      // 退出設置模式時,保存參數到EEPROM
      if(set_mode == 0)
      {
        IAP_Erase(EEPROM_ADDR);  // 先擦除片區
                                IAP_Write(EEPROM_ADDR_H, temp_high);   // 保存高溫
                                IAP_Write(EEPROM_ADDR_L, temp_low);  // 保存低溫      }
      
      while(KEY_OK == 0); // 等待松開
    }
  }
  
  if(set_mode != 0) // 設置模式下才響應加減鍵
  {
    if(KEY_ADD == 0)
    {
      Delay_ms(20);
      if(KEY_ADD == 0)
      {
        if(set_mode == 1) temp_high++;  // 設置高溫
        if(set_mode == 2) temp_low++;   // 設置低溫
        while(KEY_ADD == 0);
      }                                                 
    }
   
    if(KEY_SUB == 0)
    {
      Delay_ms(20);
      if(KEY_SUB == 0)
      {
        if(set_mode == 1 && temp_high > 0) temp_high--;
        if(set_mode == 2 && temp_low > 0) temp_low--;
        while(KEY_SUB == 0);
      }
    }
  }
}

// 報警判斷函數
void Alarm_Check(void)
{
  if(set_mode == 0) // 正常模式才報警
  {
    if(temp_real > temp_high || temp_real < temp_low)
                        BEEP = 0;  // 超閾值,蜂鳴器響
    else
                        BEEP = 1;  // 正常,蜂鳴器關
  }
  else
  {
                BEEP = 1; // 設置模式關閉報警
  }
}

// 主函數
void main(void)
{
  unsigned char        i;
        unsigned int        j;
       
        // 初始化
  GPIO_Init();         
  ADC_Init();// ADC初始化
        Timer0_Init();

        BEEP = 1;

        for(i=0; i<8; i++)        DisplayBuff [i] = 0xff;        //上電消隱        1111 1111
  

  temp_high = IAP_Read(EEPROM_ADDR_H);
        temp_low  = IAP_Read(EEPROM_ADDR_L);

  
  // 上電默認值(防止首次使用EEPROM無數據)
  if(temp_high == 0xFF || temp_high == 0) temp_high = 300;
  if(temp_low  == 0xFF || temp_low  == 0) temp_low  = 50;

  while(1)
  {
    if(!AUTO_ISP) IAP_CONTR = 0x60;

                Key_Scan();        // 按鍵掃描

                while(!g_bSystemTime1Ms)        ;        //等待1ms到
                g_bSystemTime1Ms = 0;
               
                if(++j >= 40)                //40ms到
                {
                        j = 0;

                        temp_real = Get_temperature(ADC_Read_Oversample(1)); // 采集實際溫度

                        if(temp_real >= 0)
                        {
                                F0 = 0;       
        temp_real = temp_real;      
            }
                        else               
            {
        F0 = 1;       
        temp_real = -temp_real;   
            }
                       
                        DisplayBuff[7] = (temp_real / 1000);     //顯示數值
      DisplayBuff[6] = (temp_real / 100) % 10;
      DisplayBuff[5] = (temp_real / 10) % 10 + DIS_DOT;        //十位 + 小數點(帶小數點顯示)
      DisplayBuff[4] = temp_real % 10;                                       

                        // 千位為 0 時不顯示(消零),顯示黑位(不亮)
            if(DisplayBuff[7] == 0)   
      DisplayBuff[7] = DIS_BLACK;

           
            if(F0 == 1)  
      DisplayBuff[7] = DIS_;

                        if((temp_real > 1200) && (temp_real < TEMP_MIN*10))
                        {
                                for(i=0; i<4; i++)        DisplayBuff[i] = DIS_;
                        }


                        if(temp_high >= 0)
                        {
                                F0 = 0;       
        temp_high = temp_high;      
            }
                        else               
            {
        F0 = 1;       
        temp_high = -temp_high;   
            }
                        DisplayBuff[3] = (temp_high / 1000);     //顯示數值
      DisplayBuff[2] = (temp_high / 100) % 10;
      DisplayBuff[1] = (temp_high / 10) % 10 + DIS_DOT;        //十位 + 小數點(帶小數點顯示)
      DisplayBuff[0] = temp_high % 10;                                               

                       
            if(DisplayBuff[3] == 0)   
      DisplayBuff[3] = DIS_BLACK;

           
            if(F0 == 1)  
      DisplayBuff[3] = DIS_;

                        if((temp_high > 1200) && (temp_high < TEMP_MIN*10))
                        {
                                for(i=0; i<4; i++)        DisplayBuff[i] = DIS_;
                        }   
                }
    Alarm_Check();        // 報警判斷
  }
}
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:76027 發表于 2026-4-11 19:46 | 只看該作者
重新上電后,你的數據是這個: // 上電默認值(防止首次使用EEPROM無數據)
  if(temp_high == 0xFF || temp_high == 0) temp_high = 300;
  if(temp_low  == 0xFF || temp_low  == 0) temp_low  = 50;
回復

使用道具 舉報

板凳
ID:76027 發表于 2026-4-11 19:49 | 只看該作者
unsigned int temp_high = 300;     // 高溫閾值
unsigned int temp_low = 50;      // 低溫閾值 再注釋點這個試試 // 上電默認值(防止首次使用EEPROM無數據)
  //if(temp_high == 0xFF || temp_high == 0) temp_high = 300;
// if(temp_low  == 0xFF || temp_low  == 0) temp_low  = 50;
回復

使用道具 舉報

地板
ID:1167595 發表于 2026-4-12 18:50 | 只看該作者
花了點時間,給樓主的源碼加上適合初學者學習使用的全注釋源碼

代碼功能概述:這是一個基于STC8G單片機的溫度監控系統,具有以下功能:
1)通過NTC測溫并顯示實際溫度
2)可通過按鍵設置高溫/低溫報警閾值
3)閾值參數存儲于EEPROM
4)溫度超限時蜂鳴器報警
5)使用74HC595驅動數碼管顯示溫度值


  1. #include"STC8G.H"          // 包含STC8G系列單片機頭文件
  2. #include"intrins.H"        // 包含內聯函數頭文件(如_nop_延時)
  3. #include"ADC.h"            // 包含ADC模塊頭文件
  4. #include"NTC.h"            // 包含NTC溫度傳感器頭文件
  5. #include"GPIO.h"           // 包含GPIO初始化頭文件
  6. #include"TIMER.h"          // 包含定時器頭文件
  7. #include"HC595_DISPLAY.h"  // 包含74HC595顯示驅動頭文件

  8. //==================== 引腳定義 ====================
  9. sbit KEY_ADD  = P3 ^ 2; // 定義加鍵連接到P3.2引腳
  10. sbit KEY_SUB  = P1 ^ 4; // 定義減鍵連接到P1.4引腳
  11. sbit KEY_OK   = P1 ^ 7; // 定義確認鍵連接到P1.7引腳

  12. sbit BEEP     = P1 ^ 5; // 定義蜂鳴器連接到P1.5引腳
  13. sbit ADC_TEMP = P1 ^ 1; // 定義溫度ADC輸入引腳P1.1

  14. unsigned int temp_real;    // 存儲實際溫度值
  15. unsigned int temp_high;    // 存儲高溫報警閾值
  16. unsigned int temp_low;     // 存儲低溫報警閾值
  17. unsigned char set_mode = 0;  // 設置模式標志:0=正常模式,1=設置高溫,2=設置低溫

  18. // EEPROM 地址定義
  19. #define EEPROM_ADDR_H 0x0000  // 高溫閾值存儲地址
  20. #define EEPROM_ADDR_L 0x0001  // 低溫閾值存儲地址
  21. #define EEPROM_ADDR   0x0000  // EEPROM起始地址(備用)

  22. void IAP_IDLE(void);                       // 聲明IAP空閑函數
  23. unsigned char IAP_Read(unsigned int addr); // 聲明IAP讀函數
  24. void IAP_Write(unsigned int addr, unsigned char dat); // 聲明IAP寫函數
  25. void IAP_Erase(unsigned int addr);         // 聲明IAP擦除函數

  26. // 延時函數(毫秒級)
  27. void Delay_ms(unsigned int ms)
  28. {
  29.     unsigned int i, j;
  30.     for(i = 0; i < ms; i++)     // 外層循環控制毫秒數
  31.         for(j = 0; j < 24 * 85; j++); // 內層循環實現約1ms延時
  32. }

  33. // IAP空閑函數(關閉IAP功能)
  34. void IAP_IDLE(void)
  35. {
  36.     IAP_CONTR = 0;   // 關閉IAP功能
  37.     IAP_CMD = 0;     // 清除命令寄存器
  38.     IAP_TRIG = 0;    // 清除觸發寄存器
  39.     IAP_ADDRH = 0x80; // 設置地址高字節
  40.     IAP_ADDRL = 0;   // 設置地址低字節
  41. }

  42. // 單字節讀函數
  43. unsigned char IAP_Read(unsigned int addr)
  44. {
  45.     char dat;                          // 定義數據存儲變量
  46.     IAP_CONTR = 0x80;   // 使能IAP,設置等待時間
  47.     IAP_TPS = 24;       // 設置IAP時鐘分頻
  48.     IAP_CMD = 0x01;   // 設置讀命令
  49.     IAP_ADDRL = addr;   // 設置地址低字節
  50.     IAP_ADDRH = addr >> 8; // 設置地址高字節
  51.     IAP_TRIG = 0x5a;   // 觸發訪問(先寫0x5A)
  52.     IAP_TRIG = 0xa5;   // 觸發訪問(再寫0xA5)
  53.     _nop_();           // 空操作延時
  54.     dat = IAP_DATA;    // 讀取數據
  55.     IAP_IDLE();        // 進入IAP空閑模式
  56.     return dat;        // 返回讀取的數據
  57. }

  58. // 單字節寫函數
  59. void IAP_Write(unsigned int addr, unsigned char dat)
  60. {
  61.     IAP_CONTR = 0x80;   // 使能IAP,設置等待時間
  62.     IAP_TPS = 24;       // 設置IAP時鐘分頻
  63.     IAP_CMD = 0x02;   // 設置寫命令
  64.     IAP_ADDRL = addr;   // 設置地址低字節
  65.     IAP_ADDRH = addr >> 8; // 設置地址高字節
  66.     IAP_DATA = dat;    // 寫入數據
  67.     IAP_TRIG = 0x5a;   // 觸發訪問(先寫0x5A)
  68.     IAP_TRIG = 0xa5;   // 觸發訪問(再寫0xA5)
  69.     _nop_();           // 空操作延時
  70.     IAP_IDLE();        // 進入IAP空閑模式
  71. }

  72. // 扇區擦除函數
  73. void IAP_Erase(unsigned int addr)
  74. {
  75.     IAP_CONTR = 0x80;   // 使能IAP,設置等待時間
  76.     IAP_TPS = 24;       // 設置IAP時鐘分頻
  77.     IAP_CMD   = 0x03;   // 設置擦除命令
  78.     IAP_ADDRL = addr;   // 設置地址低字節
  79.     IAP_ADDRH = addr >> 8; // 設置地址高字節
  80.     IAP_TRIG  = 0x5A;   // 觸發訪問(先寫0x5A)
  81.     IAP_TRIG  = 0xA5;   // 觸發訪問(再寫0xA5)
  82.     _nop_();            // 空操作延時
  83.     IAP_IDLE();         // 進入IAP空閑模式
  84. }

  85. // 按鍵掃描函數
  86. void Key_Scan(void)
  87. {
  88.     if(KEY_OK == 0)  // 檢測確認鍵是否按下(低電平有效)
  89.     {
  90.         Delay_ms(20);  // 延時消抖
  91.         if(KEY_OK == 0) // 再次確認按鍵按下
  92.         {
  93.             set_mode++;   // 模式切換
  94.             if(set_mode > 2) set_mode = 0; // 模式循環:0->1->2->0

  95.             // 退出設置模式時,保存參數到EEPROM
  96.             if(set_mode == 0)
  97.             {
  98.                 IAP_Erase(EEPROM_ADDR);  // 先擦除扇區
  99.                 IAP_Write(EEPROM_ADDR_H, temp_high);   // 保存高溫閾值
  100.                 IAP_Write(EEPROM_ADDR_L, temp_low);  // 保存低溫閾值
  101.             } // 注意:原代碼這里缺少右花括號,已補全

  102.             while(KEY_OK == 0); // 等待按鍵釋放
  103.         }
  104.     }

  105.     if(set_mode != 0) // 僅在設置模式下響應加減鍵
  106.     {
  107.         if(KEY_ADD == 0) // 檢測加鍵
  108.         {
  109.             Delay_ms(20);
  110.             if(KEY_ADD == 0)
  111.             {
  112.                 if(set_mode == 1) temp_high++;  // 增加高溫閾值
  113.                 if(set_mode == 2) temp_low++;   // 增加低溫閾值
  114.                 while(KEY_ADD == 0); // 等待按鍵釋放
  115.             }
  116.         }

  117.         if(KEY_SUB == 0) // 檢測減鍵
  118.         {
  119.             Delay_ms(20);
  120.             if(KEY_SUB == 0)
  121.             {
  122.                 if(set_mode == 1 && temp_high > 0) temp_high--; // 減少高溫閾值(不低于0)
  123.                 if(set_mode == 2 && temp_low > 0) temp_low--;  // 減少低溫閾值(不低于0)
  124.                 while(KEY_SUB == 0); // 等待按鍵釋放
  125.             }
  126.         }
  127.     }
  128. }

  129. // 報警判斷函數
  130. void Alarm_Check(void)
  131. {
  132.     if(set_mode == 0) // 僅在正常模式進行報警判斷
  133.     {
  134.         if(temp_real > temp_high || temp_real < temp_low)
  135.             BEEP = 0;  // 溫度超限,蜂鳴器響(低電平驅動)
  136.         else
  137.             BEEP = 1;  // 溫度正常,關閉蜂鳴器
  138.     }
  139.     else
  140.     {
  141.         BEEP = 1; // 設置模式下關閉蜂鳴器
  142.     }
  143. }

  144. // 主函數
  145. void main(void)
  146. {
  147.     unsigned char        i;        // 循環變量
  148.     unsigned int        j;       // 時間計數變量

  149.     // 初始化
  150.     GPIO_Init();         // GPIO初始化
  151.     ADC_Init();          // ADC初始化
  152.     Timer0_Init();       // 定時器0初始化

  153.     BEEP = 1;             // 初始化關閉蜂鳴器

  154.     for(i = 0; i < 8; i++)        DisplayBuff [i] = 0xff; // 顯示緩沖區初始化(全滅)


  155.     temp_high = IAP_Read(EEPROM_ADDR_H); // 從EEPROM讀取高溫閾值
  156.     temp_low  = IAP_Read(EEPROM_ADDR_L);  // 從EEPROM讀取低溫閾值


  157.     // 上電默認值(防止首次使用EEPROM無數據)
  158.     if(temp_high == 0xFF || temp_high == 0) temp_high = 300; // 默認高溫閾值300
  159.     if(temp_low  == 0xFF || temp_low  == 0) temp_low  = 50;  // 默認低溫閾值50

  160.     while(1)  // 主循環
  161.     {
  162.         if(!AUTO_ISP) IAP_CONTR = 0x60;  // 如果不在ISP模式,設置IAP等待時間

  163.         Key_Scan();        // 調用按鍵掃描函數

  164.         while(!g_bSystemTime1Ms)        ;        // 等待1ms定時標志
  165.         g_bSystemTime1Ms = 0;                    // 清除1ms標志

  166.         if(++j >= 40)                // 40ms定時到達
  167.         {
  168.             j = 0;  // 重置計時

  169.             temp_real = Get_temperature(ADC_Read_Oversample(1)); // 采集實際溫度值

  170.             // 處理實際溫度顯示
  171.             if(temp_real >= 0)  // 溫度為正
  172.             {
  173.                 F0 = 0;       // 正數標志
  174.                 temp_real = temp_real;      // 保持原值
  175.             }
  176.             else                // 溫度為負
  177.             {
  178.                 F0 = 1;       // 負數標志
  179.                 temp_real = -temp_real;   // 取絕對值
  180.             }

  181.             DisplayBuff[7] = (temp_real / 1000);     // 千位顯示
  182.             DisplayBuff[6] = (temp_real / 100) % 10;  // 百位顯示
  183.             DisplayBuff[5] = (temp_real / 10) % 10 + DIS_DOT;  // 十位顯示(帶小數點)
  184.             DisplayBuff[4] = temp_real % 10;         // 個位顯示

  185.             // 千位消零處理
  186.             if(DisplayBuff[7] == 0)
  187.                 DisplayBuff[7] = DIS_BLACK;  // 千位為0則不顯示

  188.             // 負號顯示處理
  189.             if(F0 == 1)
  190.                 DisplayBuff[7] = DIS_MINUS;  // 顯示負號(注意:原代碼為DIS_,應為DIS_MINUS)

  191.             // 溫度異常處理(超出量程)
  192.             if((temp_real > 1200) && (temp_real < TEMP_MIN * 10))
  193.             {
  194.                 for(i = 0; i < 4; i++)        DisplayBuff[i] = DIS_MINUS; // 顯示----
  195.             }

  196.             // 處理高溫閾值顯示(類似實際溫度處理流程)
  197.             if(temp_high >= 0)
  198.             {
  199.                 F0 = 0;
  200.                 temp_high = temp_high;
  201.             }
  202.             else
  203.             {
  204.                 F0 = 1;
  205.                 temp_high = -temp_high;
  206.             }
  207.             DisplayBuff[3] = (temp_high / 1000);     // 千位顯示
  208.             DisplayBuff[2] = (temp_high / 100) % 10;  // 百位顯示
  209.             DisplayBuff[1] = (temp_high / 10) % 10 + DIS_DOT;  // 十位顯示(帶小數點)
  210.             DisplayBuff[0] = temp_high % 10;         // 個位顯示

  211.             // 千位消零處理
  212.             if(DisplayBuff[3] == 0)
  213.                 DisplayBuff[3] = DIS_BLACK;

  214.             // 負號顯示處理
  215.             if(F0 == 1)
  216.                 DisplayBuff[3] = DIS_MINUS;

  217.             // 閾值異常處理
  218.             if((temp_high > 1200) && (temp_high < TEMP_MIN * 10))
  219.             {
  220.                 for(i = 0; i < 4; i++)        DisplayBuff[i] = DIS_MINUS; // 顯示----
  221.             }
  222.         }
  223.         Alarm_Check();        // 報警檢測
  224.     }
  225. }
復制代碼

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

5#
ID:57657 發表于 2026-4-12 19:31 | 只看該作者
關于EEPROM數據不正確的問題,99%的新手沒有了解EEPROM的扇區存儲結構:
STC單片機的EEPROM不是真正的EEPROM,而是flash閃存。
讀:unsigned char code 指針或匯編MOVC指令讀取,不需要初始化EEPROM (STC89/STC90等老版本除外,具體見數據手冊)
寫: 二進制1可以寫為0:0xFF→Q,0不可寫為1 以下是無法完成的操作:Q→0xFF或Q→R  Q=0x00~0xFE R=0x00~0xFE 且Q與R的值不同
擦除:只有扇區擦除,沒有字節擦除,一次擦512字節,擦除后全部為:0xFF
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表