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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

stc8g1k08a單片機掉電存儲問題

  [復制鏈接]
跳轉到指定樓層
樓主
感覺程序沒有問題但是掉電之后不能重新讀取上次保存到eeprom 不知道是沒有保存到內部還是讀取不行

//STC8G1K08A工作電壓范圍1.9~5.5V
//測試工作頻率為11.0592MHz
//S_ADC基準值由調試后確定
//此程序為基礎構架,需經調試完善
//#include "reg51.h"
#include "STC8.H"
#include "intrins.h"
#define ADCTIM  (*(unsigned char volatile xdata *)0xfea8)
#define WT_12M   0x83
typedef unsigned char uchar;
typedef unsigned int uint;
//端口定義
sbit LED=P3^2;
sbit OUT=P3^3;
sbit ADC=P5^4;
sbit KEY=P5^5;
//全局變量
uchar S_ADC,M_ADC;                                                                //ADC采樣值
/*----------------------------
        初始化定時器
----------------------------*/
void Timer0Init()                                                                //2毫秒@11.0592MHz
{
        AUXR |= 0x80;                                                                //定時器時鐘1T模式
        TMOD &= 0xF0;                                                                //設置定時器自動重裝模式
        TL0 = 0x9A;                                                                        //設置定時初值
        TH0 = 0xA9;                                                                        //設置定時初值
        TF0 = 0;                                                                        //清除TF0標志
        TR0 = 1;                                                                        //定時器0開始計時
}
/*----------------------------
        讀取ADC結果
----------------------------*/
uchar GetADCResult()
{        //ADC 控制器  電源  啟動  完成  --   15通道模擬選擇位
        //ADC_CONTR    B7    B6    B5   B4   B3   B2   B1   B0
        ADC_CONTR|= 0x44;                                       //啟動AD轉換,P5.4 ADC輸入
        _nop_();_nop_();                                                //延時2個時鐘
        while (!(ADC_CONTR & 0x20));                //查詢ADC完成標志
        ADC_CONTR &= ~0x20;                                                //清完成標志
        return ADC_RES;                                 //返回8位ADC結果
}

void IapIdle()
{
    IAP_CONTR = 0;                     //關閉IAP功能
    IAP_CMD = 0;                       //清除命令寄存器
    IAP_TRIG = 0;                      //清除觸發寄存器
    IAP_ADDRH = 0x80;                  //將地址設置到非IAP區域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = WT_12M;                //使能IAP
    IAP_CMD = 1;                       //設置IAP讀命令
    IAP_ADDRL = addr;                  //設置IAP低地址
    IAP_ADDRH = addr >> 8;             //設置IAP高地址
    IAP_TRIG = 0x5a;                   //寫觸發命令(0x5a)
    IAP_TRIG = 0xa5;                   //寫觸發命令(0xa5)
    _nop_();
    dat = IAP_DATA;                    //讀IAP數據
    IapIdle();                         //關閉IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = WT_12M;                //使能IAP
    IAP_CMD = 2;                       //設置IAP寫命令
    IAP_ADDRL = addr;                  //設置IAP低地址
    IAP_ADDRH = addr >> 8;             //設置IAP高地址
    IAP_DATA = dat;                    //寫IAP數據
    IAP_TRIG = 0x5a;                   //寫觸發命令(0x5a)
    IAP_TRIG = 0xa5;                   //寫觸發命令(0xa5)
    _nop_();
    IapIdle();                         //關閉IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = WT_12M;                //使能IAP
    IAP_CMD = 3;                       //設置IAP擦除命令
    IAP_ADDRL = addr;                  //設置IAP低地址
    IAP_ADDRH = addr >> 8;             //設置IAP高地址
    IAP_TRIG = 0x5a;                   //寫觸發命令(0x5a)
    IAP_TRIG = 0xa5;                   //寫觸發命令(0xa5)
    _nop_();                           //
    IapIdle();                         //關閉IAP功能
}

void keys_can()                                                                //按鍵掃描
{
        static uint count=0;                                        //長按計數變量
        static bit sign=0;                                                //狀態標志
        if(!KEY)                                                                   //按鍵按下
        {  
                if(++count>=500)                                        //長按計數1s
                {
                        sign=1;                                                        //狀態標志置1
                        S_ADC=GetADCResult();                        //讀取ADC
                        IapErase(0x0000);                                //擦除第0扇區
                        IapProgram(0x0000,S_ADC);                //寫入數據
                        LED=0;                                                        //保存成功指示
                }
        }  
        else                                                                        //按鍵抬起
        {  
                if(sign)                                                        //判斷狀態標志
                {
                        LED=1;                                                        //指示燈復位
                        sign=0;                                                        //狀態標志清0
                }
                count=0;                                                        //長按計數變量清0
        }   
}

void main()
{
//配置端口模式寄存器
        P3M0 = 0x00;                                                        //設置P3準雙向口
        P3M1 = 0x00;                                                        //設置P3準雙向口
        P5M0 = 0x00;                                                        //設置P5.4為ADC口
        P5M1 = 0x10;                                                        //設置P5.4為ADC口
        OUT  = 0;                                                                //輸出口低電平
//配置ADC寄存器 --  -- 格式控制位 --   速度控制位
//   ADCCFG     B7  B6     B5     B4   B3 B2 B1 B0
        P_SW2 |= 0x80;                                                        //打開外設寄存器
        ADCTIM = 0x3f;                                                        //設置 ADC 內部時序
        P_SW2 &= 0x7f;                                                        //關閉外設寄存器
        ADCCFG = 0x0f;                                                        //設置 ADC 時鐘為系統時鐘/2/16
        ADC_CONTR = 0x80;                                                //使能 ADC 模塊
//EEPROM初始操作
        S_ADC=IapRead(0x0000);                                        //讀取EEPROM保存的數據
        //if(S_ADC<50||S_ADC>150)                                        //判斷超出合適范圍,初次使用EEPROM全為0xff
                //S_ADC=100;                                                        //預設基準值

        Timer0Init();                                                        //初始化定時器

        while (1)
        {
                if(TF0)                                                                //中斷請求周期2ms
                {
                        TF0=0;                                                        //中斷請求標志清0
                        keys_can();                                                //按鍵掃描
                        M_ADC=GetADCResult();                        //讀取ADC
                        if(M_ADC < S_ADC)                                //比較
                        {
                                OUT = 1;                                        //輸出高電平
                                LED = 1;                                        //輸出指示亮
                        }
                        else         
                        {
                                OUT = 0;                                        //輸出低電平
                                LED = 0;                                        //輸出指示熄
                        }
                }
        }
}

51黑論壇_急停測試程序.zip

19.82 KB, 下載次數: 15

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏7 分享淘帖 頂2 踩
回復

使用道具 舉報

沙發
ID:94031 發表于 2021-9-9 14:38 | 只看該作者
可以先把 IapProgram(int addr, char dat)(寫),char IapRead(int addr)(讀) 單獨測試一下,看正常嗎。
回復

使用道具 舉報

板凳
ID:123289 發表于 2021-9-9 16:05 | 只看該作者
先證明一下,是否寫進去了。
當然,當掉電發重在寫數據期間,會發生寫失敗的,不過這是個概率問題。
回復

使用道具 舉報

地板
ID:792404 發表于 2021-9-9 18:10 | 只看該作者
IapErase(0);                    //擦除第0扇區
IapProgram(1,S_ADC);     //寫入數據
S_ADC=IapRead(1);        //讀取EEPROM保存的數據
這樣改一下就可以了,我之前有個程序也是按照官網提供的代碼寫的不行,這樣改一下就沒問題了,你試一下
回復

使用道具 舉報

5#
ID:716660 發表于 2021-9-9 18:28 | 只看該作者
YUANYUXING 發表于 2021-9-9 18:10
IapErase(0);                    //擦除第0扇區
IapProgram(1,S_ADC);     //寫入數據
S_ADC=IapRead( ...

還是不行呀
回復

使用道具 舉報

6#
ID:94031 發表于 2021-9-9 19:48 | 只看該作者
不知你是如何得到 “掉電之后不能重新讀取” 結論的。
回復

使用道具 舉報

7#
ID:716660 發表于 2021-9-9 20:07 | 只看該作者
xuyaqi 發表于 2021-9-9 19:48
不知你是如何得到 “掉電之后不能重新讀取” 結論的。

重新上電,之前保存到eeprom的adc值沒了
回復

使用道具 舉報

8#
ID:814525 發表于 2021-9-9 22:46 | 只看該作者
是不是IAP_CONTR = WT_12M;       //使能IAP  這句有問題。以下是驗證沒問題的
sfr IAP_TPS = 0xF5;
#define  IAP_EN     (1<<7)
#define  IAP_ENABLE()        IAP_CONTR = IAP_EN; IAP_TPS = MAIN_Fosc / 1000000
回復

使用道具 舉報

9#
ID:624769 發表于 2021-9-9 23:00 | 只看該作者
你把:
                        S_ADC=GetADCResult();                        //讀取ADC
                         IapErase(0x0000);                                //擦除第0扇區
                        IapProgram(0x0000,S_ADC);                //寫入數據
                        LED=0;                                                        //保存成功指示
這里的 LED = 0;  改成:
if((IAP_CONTR & 0x10) == 0x00)    LED=0;                                                        //保存成功指示
來確定, 是不是真的保存成功了, 比較好。
回復

使用道具 舉報

10#
ID:401564 發表于 2021-9-10 08:30 | 只看該作者
這不是很簡單的東西嗎?
1,開發板上連接一個能顯示數據的,數碼管,OLED都行
2,寫一段開機就讀取指定EEPROM地址的程序,再寫一段按下按鍵就寫入指定地址EEPROM的,不要ADC,也不要什么串口,直接就是向一個地址寫入數據:123,代碼越少越好
3,寫完之后,拔下電,然后上電,只要顯示的是123,就說明讀寫程序是對的

像你這個,又是ADC,又是比較的,總之就是結果不如意,但并不能確定問題出現在哪一步
回復

使用道具 舉報

11#
ID:716660 發表于 2021-9-10 09:27 | 只看該作者
確實保存了,但是重新上電 數據就變成11111111沒有之前的數了咋回事
回復

使用道具 舉報

12#
ID:716660 發表于 2021-9-10 15:26 | 只看該作者
Y_G_G 發表于 2021-9-10 08:30
這不是很簡單的東西嗎?
1,開發板上連接一個能顯示數據的,數碼管,OLED都行
2,寫一段開機就讀取指定EEPROM ...

試了 ,只能讀不能寫
回復

使用道具 舉報

13#
ID:170318 發表于 2021-9-10 16:18 | 只看該作者
讀寫程序有問題,STC8與STC15的EEPROM有點不一樣,詳細看手冊
回復

使用道具 舉報

14#
ID:401564 發表于 2021-9-10 18:25 | 只看該作者
呦呦奧利給 發表于 2021-9-10 15:26
試了 ,只能讀不能寫

晚上有空我幫你寫一個看一下
回復

使用道具 舉報

15#
ID:716660 發表于 2021-9-10 19:01 | 只看該作者
Y_G_G 發表于 2021-9-10 18:25
晚上有空我幫你寫一個看一下

好的謝謝哥
回復

使用道具 舉報

16#
ID:401564 發表于 2021-9-11 06:59 | 只看該作者
Stc8g1k17_GPS時鐘.rar (143.73 KB, 下載次數: 50)
我這個是在自己以前的一個工程中測試的,運行的結果是可以寫入和讀取的,掉電之后兩次讀取的結果是正確的
在EEPROM.c中,你可以
我手頭上沒有08a的,所以,我用的是STC8G1k17的,其實也是一樣的,STC8g系列是一樣的
要注意幾個點:
1,這個型號的EEPROM只能把"1"寫成"0"!!!!!!!!!!這個很重要,也很扯,所以,每次寫入你要保存的數據之前,一定要先進行"擦除"操作,而每次擦除卻是以扇區進行的,這一點一定要理解!!!!!數據手冊中有說明,要認真看
比如,你要保存5個地址的數據,但你盲區還有這5個數據以外的其它數據,那么,你就要先把這整個扇區數據先讀取出來,保存好,然后改動你要保存的5個地址的數據,進行整個扇區的擦除(全部寫入1),然后,再把之前改動過的一起寫入
2,下載器有一個"本次下載程序時擦除用戶EEPROM區"選項,不要打鉤!
回復

使用道具 舉報

17#
ID:716660 發表于 2021-9-11 22:41 | 只看該作者
Y_G_G 發表于 2021-9-11 06:59
我這個是在自己以前的一個工程中測試的,運行的結果是可以寫入和讀取的,掉電之后兩次讀取的結果是正確的
...

,好了
回復

使用道具 舉報

18#
ID:65956 發表于 2022-11-9 08:47 | 只看該作者
看你這程序要寫入內部EEPROM數據要滿足按鍵按下一秒才會寫入,這樣掉電1秒才寫入是來不及寫入的,如果要確保掉電時寫入數據,就要用到掉電中斷,可以在中斷里直接寫入,但字節要越少越好,不然要用一個AD功能讀電源輸入,當電源低于一定值后就把數據寫入,否則按你這程序是不行的。僅供參考
回復

使用道具 舉報

19#
ID:483092 發表于 2025-1-4 11:32 | 只看該作者
Y_G_G 發表于 2021-9-11 06:59
我這個是在自己以前的一個工程中測試的,運行的結果是可以寫入和讀取的,掉電之后兩次讀取的結果是正確的
...

厲害,太詳細了。
回復

使用道具 舉報

20#
ID:1006638 發表于 2025-1-22 20:38 | 只看該作者
我用這個小東西做了好多小玩意很好用,帶掉電保存數據功能也都很可靠。我是這樣做的:1,用較大的電源濾波電容680UF到1000UF(掉電后提供較多的能量)。2,上電后先擦除好EEPROM,斷電后光寫就行了,節省擦除時間,這對數據量較大情況尤為重要。3,我不用掉電中斷寫數據,因為觸發它已經是電壓低了,低壓寫EEPROM不可靠(它數據手冊里說的)。我用穩壓器前的電壓低于7v觸發外部中斷來寫的(不用ADC讀取,直接硬件比較器實現)。針對你我建議先如樓上所言做一個極簡程序,上電先讀取EEPROM一個字節用LED顯示,再按下按鍵改變顯示值并寫進EEPROM(注意先擦后寫),再斷電上電驗證程序的基本功能是否正常(第一次不準全是1,看第二次以后斷、上電LED狀態).正常后按我所做,應該差不離。
回復

使用道具 舉報

21#
ID:1109793 發表于 2025-1-23 09:08 | 只看該作者
大IGBT 發表于 2025-1-22 20:38
我用這個小東西做了好多小玩意很好用,帶掉電保存數據功能也都很可靠。我是這樣做的:1,用較大的電源濾波 ...

一個1000UF的在12V端的電容,可以提供很長時間了。別說擦除一個扇區了,兩個三個也不在華夏吧。
回復

使用道具 舉報

22#
ID:161164 發表于 2025-1-26 23:18 | 只看該作者
大IGBT 發表于 2025-1-22 20:38
我用這個小東西做了好多小玩意很好用,帶掉電保存數據功能也都很可靠。我是這樣做的:1,用較大的電源濾波 ...

我用這種接法


回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 毛片高清 | 久久久久亚洲视频 | 亚洲在线| 91久久久久久久久久久久久 | 久久久久91 | 精品欧美一区二区三区久久久 | 国产精品电影网 | 一区二区在线免费观看 | 久久久久久成人 | 免费国产一区二区视频 | 黄色免费在线观看 | 日本精品视频一区二区 | 欧美八区| 亚洲 成人 av | 精品久久久久久亚洲精品 | 九一视频在线观看 | 亚洲女人天堂成人av在线 | jⅰzz亚洲| 欧美极品在线视频 | 欧美二三区 | 午夜在线小视频 | 美女视频.| 成人h动漫亚洲一区二区 | 欧美a在线 | 人人99 | 另类在线 | 日韩成人性视频 | 国产成人精品免费视频 | 先锋资源吧 | 精品一区国产 | 欧美一级免费黄色片 | 日韩成人精品在线 | 国产成人综合一区二区三区 | 精品亚洲一区二区三区四区五区高 | 国产在线观看不卡一区二区三区 | 久热电影 | 久久国产精品99久久久久久丝袜 | 羞羞视频在线观看免费观看 | 亚洲欧洲成人在线 | 久久国产精品无码网站 | 国产视频福利一区 |