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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

關于單片機EEPROM讀數據偶爾不正確的情況

[復制鏈接]
跳轉到指定樓層
樓主
ID:675145 發表于 2025-6-2 11:06 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
一:問題描述
之前用的單片機是stc15w408a都是正常的,因為FLASH太小又需要增加其他功能費不得不改成stc15f2k60s2,但是EEPROM代碼是差不多的。從原來保存在2,3扇區變成了0,1扇區(stc15f2k60s2只有0,1這兩個扇區)
換完芯片后EEPROM讀取大部分時候是正常的,隨機出現讀出來的數據是0xff,而且第0扇區和第1扇區隨機出現,讀取異常后無論如何重新上電都是異常的需要重新寫入

二:看代碼:
1.EEPROM.c
[code]#include "all.h"
void IapIdle()
{
        IAP_CONTR = 0;
        IAP_CMD = 0;
        IAP_TRIG = 0;
        IAP_ADDRH = 0x80;
        IAP_ADDRL = 0;
}
void EEPROM_Wipe512_Drive(u8 ADDRH)        //清空某個扇區
{
        
        IAP_CONTR|=0x82;
        IAP_CMD=0x03;
        IAP_ADDRH=ADDRH;
        IAP_TRIG=0x5A;
        IAP_TRIG=0xA5;
        _nop_();
        _nop_();
        _nop_();
        IapIdle();
}
u8 EEPROM_Read_Byte_Drive(u8 ADDRH,u8 ADDRL)        //讀某個扇區數據
{
        u8 idata DATA;
        
        IAP_CONTR|=0x82;
        IAP_CMD=0x01;
        IAP_ADDRH=ADDRH;
        IAP_ADDRL=ADDRL;
        IAP_TRIG=0x5A;
        IAP_TRIG=0xA5;
        _nop_();
        _nop_();
        _nop_();
        DATA=IAP_DATA;
        IapIdle();
        
        return  DATA;
}
void EEPROM_Write_Byte_Drive(u8 ADDRH,u8 ADDRL,u8 Byte)//往某個扇區寫數據
{
        IAP_CONTR|=0x82;
        IAP_CMD=0x02;
        IAP_ADDRH=ADDRH;
        IAP_ADDRL=ADDRL;
        IAP_DATA=Byte;
        IAP_TRIG=0x5A;
        IAP_TRIG=0xA5;
        _nop_();
        _nop_();
        _nop_();
        IapIdle();
}

void EEPROM_Write_Data(u8 ADDRH)
{
        EEPROM_Wipe512_Drive(ADDRH);
        
        if(ADDRH == EEPROM_ID)
        {
                EEPROM_Write_Byte_Drive(EEPROM_ID, EEPROM_Drive_ID0, Drive_ID[0]);
                EEPROM_Write_Byte_Drive(EEPROM_ID, EEPROM_Drive_ID1, Drive_ID[1]);
        }
        else if(ADDRH == EEPROM_SET)
        {
                EEPROM_Write_Byte_Drive(EEPROM_SET, EEPROM_Set_Num, Set_Num);
                EEPROM_Write_Byte_Drive(EEPROM_SET, EEPROM_Hall_Open, Hall_Open);
                EEPROM_Write_Byte_Drive(EEPROM_SET, EEPROM_Motor_Open, Motor_Open);
                EEPROM_Write_Byte_Drive(EEPROM_SET, EEPROM_Limit_Flag, Limit_Flag);
                EEPROM_Write_Byte_Drive(EEPROM_SET, EEPROM_Version, Version);
        }
}

2.EEPROM.h
#ifndef EEPROM
#define EEPROM

#define EEPROM_ID                                        0
#define EEPROM_SET                                        2

#define EEPROM_Drive_ID0                        0
#define EEPROM_Drive_ID1                        1

#define EEPROM_Set_Num                                0
#define EEPROM_Hall_Open                        1
#define EEPROM_Motor_Open                        2
#define EEPROM_Limit_Flag                        3
#define EEPROM_Version                                4

extern u8 EEPROM_Read_Byte_Drive(u8 ADDRH,u8 ADDRL);//讀某個扇區數據
extern void EEPROM_Write_Data(u8 ADDRH);
        
#endif

3.EEPROM寫應用:設備通過RS485進行參數設置時才會用到寫EEPROM,一般情況不會隨意修改
void RS485_RX_Drive()        //RS485接收底層函數
{
        u8 i;
        
        send_cnt++;    //只要有數據接收,send_cnt每次都被串口中斷清零
        if(send_cnt>200)   //延時一段時間,確認緩沖區沒有繼續接收數據
        {
                send_cnt=0;
                RS485_Busy=0;
                RxLen=0;
                for(i=0;i<7;i++)
                {
                        //檢驗數據頭(D6  F7)
                        if(RS485_Up_Num_Buffer==0xD6 && RS485_Up_Num_Buffer[i+1]==0xF7)
                        {                                
                                switch(RS485_Up_Num_Buffer[i+4])
                                {
                                        case Cmd_Hall:
                                                {
                                                        if(RS485_Up_Num_Buffer[i+3]==Drive_ID[1] || RS485_Up_Num_Buffer[i+3]==0)
                                                        {
                                                                Hall_Open = RS485_Up_Num_Buffer[i+2];                //是否打開霍爾電流開關        
                                                                EEPROM_Write_Data(EEPROM_SET);
                                                        }
                                                }
                                                break;
                                        case Cmd_Motor:
                                                {
                                                        if(RS485_Up_Num_Buffer[i+3]==Drive_ID[1] || RS485_Up_Num_Buffer[i+3]==0)
                                                        {
                                                                Motor_Open = RS485_Up_Num_Buffer[i+2];                //是否打開電機電流開關
                                                                EEPROM_Write_Data(EEPROM_SET);
                                                        }
                                                }
                                                break;
                                        case Cmd_Limit:
                                                {
                                                        if(RS485_Up_Num_Buffer[i+3]==Drive_ID[1] || RS485_Up_Num_Buffer[i+3]==0)
                                                        {
                                                                Limit_Flag = RS485_Up_Num_Buffer[i+2];        //是否打開限位開關
                                                                EEPROM_Write_Data(EEPROM_SET);
                                                        }
                                                }
                                                break;
                                        case Cmd_Run_Num:
                                                        {
                                                                if(Run_Flag==0)        //停止狀態才能更改運行次數
                                                                {
                                                                        Set_Num=RS485_Up_Num_Buffer[i+2];
                                                                        EEPROM_Write_Data(EEPROM_SET);
                                                                }
                                                        }
                                                        break;
                                        case Cmd_Version:
                                                        {
                                                                if(Run_Flag==0)        //停止狀態才能更改產品版本
                                                                {
                                                                        Version = RS485_Up_Num_Buffer[i+2];                                                                        
                                                                        EEPROM_Write_Data(EEPROM_SET);
                                                                        
                                                                        if(Version==2)
                                                                                Stable_Motor_Current=550;        //電機穩定電流
                                                                        else if(Version==3)
                                                                                Stable_Motor_Current=800;        //電機穩定電流
                                                                }
                                                        }
                                                        break;
                                        case Cmd_EXIT:
                                                        {
                                                                if(Run_Flag==0)        
                                                                {
                                                                        Run_Flag = 3;
                                                                }
                                                        }
                                                        break;
                                }        
                        }
                }
        }
}

4.EEPROM讀應用:在初始化時用Get_SET_Parameter函數讀取數據,防止上電不充分在讀取數據前加了500MS延時,后來沒辦法在EEPROM讀取的數據錯誤時直接對變量進行賦值

void Get_SET_Parameter(void)
{
        Drive_ID[0] = EEPROM_Read_Byte_Drive(EEPROM_ID,        EEPROM_Drive_ID0);
        Drive_ID[1] = EEPROM_Read_Byte_Drive(EEPROM_ID,        EEPROM_Drive_ID1);
        
        Set_Num = EEPROM_Read_Byte_Drive(EEPROM_SET,        EEPROM_Set_Num);                //初始化運行次數        
        Hall_Open = EEPROM_Read_Byte_Drive(EEPROM_SET,        EEPROM_Hall_Open);                //是否打開霍爾電流開關        
        Motor_Open = EEPROM_Read_Byte_Drive(EEPROM_SET,        EEPROM_Motor_Open);                //是否打開霍爾電流開關        
        Limit_Flag = EEPROM_Read_Byte_Drive(EEPROM_SET,        EEPROM_Limit_Flag);                //是否打開霍爾電流開關
        
        Version = EEPROM_Read_Byte_Drive(EEPROM_SET,EEPROM_Version);
        if(Version==2)
        {
                Stable_Motor_Current=550;        //電機穩定電流
        }
        else if(Version==3)
        {
                Stable_Motor_Current=800;        //電機穩定電流
                Hall_Open = Close;
        }
        
        //        //設置設備編號
        Drive_ID[0] = 'G';
        Drive_ID[1] = 1;
        EEPROM_Write_Data(EEPROM_ID);
        
        //如果出現EEPROM錯誤,直接賦值
        if(Set_Num == 0xFF)
        {
                Set_Num = 100;                //初始化運行次數        
                Hall_Open = Open;                //是否打開霍爾電流開關        
                Motor_Open = Open;                //是否打開霍爾電流開關        
                Limit_Flag = Open;                //是否打開霍爾電流開關
                Version = 2;
                Stable_Motor_Current=550;        //電機穩定電流
        }
}
void main()
{
        P0M1=0;P0M0=0;
        P1M1=0;P1M0=0;
        P2M1=0;P2M0=0;
        P3M1=0;P3M0=0;
        P4M1=0;P4M0=0;        
        P5M1=0;P5M0=0;

        ADC_Init();
        Cylinder_Init();
        RS485_Init();
        IIC_Init();
        OLED_Init();
        KEY_Init();        
        WS2812B_Init();
        Lock_Init();

        Delay500ms();                                                        //延時500ms,等待系統穩定
        ADC_Reference = ADC_Filter_Result();        //獲取ADC偏置值
        Get_SET_Parameter();                                        //獲取EEPROM中的系統參數
        
        P2M1=0;P2M0=0x0E;        //P2.1/P2.2/P2.3推挽輸出                //氣缸輸出
        P1M1=0;P1M0=0x30;        //P1.4/P1.5推挽輸出                        //電機輸出
        while(1)
        {
                RS485_Data_Drive();        //RS485數據處理
                OLED_Allot();                //OLED屏幕顯示
                Mach_Run_Scan();        //電機運行掃描        
                KEY_Allot();                //按鍵掃描服務
                ADC_Allot();                //電流檢測服務
                WS2812B_Allot();        //燈
        }
}
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:675145 發表于 2025-6-2 14:06 | 只看該作者
stc15f2k60s2的工作頻率范圍在0-28M,而我的晶振是30M,大概率是這個問題了,先運行一段時間看看還會不會出現問題
回復

使用道具 舉報

板凳
ID:1109793 發表于 2025-6-2 15:37 | 只看該作者
會不會是頻率設置不對
IAP_CONTR|=0x82;
11.0592用0X83比較好吧。
另外,為啥是|=?
IAP_CONTR=0x83;可以不
回復

使用道具 舉報

地板
ID:1109793 發表于 2025-6-2 15:41 | 只看該作者
張小不懂 發表于 2025-6-2 14:06
stc15f2k60s2的工作頻率范圍在0-28M,而我的晶振是30M,大概率是這個問題了,先運行一段時間看看還會不會出 ...

30M是0x80吧
不過用到22.1184就比較穩定,用到30M你比較大膽
回復

使用道具 舉報

5#
ID:1121801 發表于 2025-6-2 16:22 | 只看該作者
IAP我算小白,我不明白IAP_CONTL|=0X82,為什么用"|=",直接賦值用"="不好嗎?還是有什么玄機?
回復

使用道具 舉報

6#
ID:57657 發表于 2025-6-2 21:49 | 只看該作者
EEPROM二進制1可以寫為0,反過來就不能。
只有扇區擦除,沒有字節擦除,必須擦除后才可以恢復為1,一次擦1扇區(512字節),扇區擦除的地址必須是512的倍數:0,512,1024,1536等。
另外此型號可以使用unsigned char code *指針(匯編MOVC指令)讀取EEPROM數據。
回復

使用道具 舉報

7#
ID:675145 發表于 2025-6-4 15:52 | 只看該作者
xiaobendan001 發表于 2025-6-2 15:41
30M是0x80吧
不過用到22.1184就比較穩定,用到30M你比較大膽

之前是STC15F408AS用的30M的晶振,改了單片機但是沒注意晶振,現在改用內部晶振24M,暫時沒問題
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 特级丰满少妇一级aaaa爱毛片 | 91久久精品国产 | 免费一级片 | 国产一区三区在线 | 免费精品 | www.日韩| 欧美中文一区 | 亚洲一区二区三区 | 精品视频成人 | 久久久这里只有17精品 | 色婷婷综合网 | 成年免费大片黄在线观看岛国 | 777777777亚洲妇女 | www久久久| 一区二区三区国产 | wwwsihu| 成人国产精品久久 | 黄色免费av | 蜜桃视频在线观看www社区 | 中文字幕成人免费视频 | 亚洲视频在线看 | 欧美福利久久 | 欧美激情综合色综合啪啪五月 | 91pao对白在线播放 | 91久久国产综合久久 | 成人性生交大免费 | 欧美日韩一区二区视频在线观看 | 欧美成年人视频在线观看 | 亚洲乱码国产乱码精品精的特点 | 午夜爽爽爽男女免费观看影院 | 日韩欧美一区在线 | 亚洲精品一区二三区不卡 | 免费a网 | 久久久久久久久久久久久九 | 99国产视频| 九九精品在线 | 日韩av免费在线观看 | 久久国产视频网 | 精品视频久久久久久 | 久久国产亚洲 | 欧美精品一区二区三 |