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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

用C語言結構體寫EEPROM數據保存的問題

[復制鏈接]
跳轉到指定樓層
樓主
ID:997026 發(fā)表于 2022-5-12 00:30 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

請教下各位,如下的結構體和結構體數組用法正確嗎?
就是需要保存數據到EEPROM,數據每改動一次,就往EEPROM寫一次,現(xiàn)在功能是沒問題的,可以正常寫入數據,但是數碼管顯示出問題了,每次設置min_change時,數碼管會變暗。

整個程序有一萬行,非常長,其他沒有貼出來,只貼了結構體這部分,因為這部分以前不是用結構體寫的,沒問題,現(xiàn)在突發(fā)奇想,用結構體寫了下,功能是實現(xiàn)了,但數碼管變暗了,不知道為啥,看了好久也不知道為啥。

但我個人估計是結構體用法的問題,麻煩大家?guī)臀铱纯矗缦碌慕Y構體數組的用法是否正確,謝謝了

C語言源程序如下:
  1. unsigned char   min_change0=0,  //要保存的變量值第一組,每一次改變都會保存
  2. unsigned char   min_change_backup0=0; //該變量為中間變量,用于與min_change做對比,下同

  3. unsigned char   min_change1=0,  //要保存的變量值第二組,每一次改變都會保存
  4. unsigned char   min_change_backup1=0;

  5. unsigned char   min_change2=0,  //要保存的變量值第三組,每一次改變都會保存  
  6. unsigned char   min_change_backup2=0;

  7. void EEPROM_Write(timeset*, unsigned char, unsigned char) ; //數據保存并寫入EEPROM
  8. EEPROM_write(unsigned char,  unsigned char, );  //內部EEPROM寫入函數


  9. typedef struct  EEPROM_Save
  10. {
  11.         unsigned char* min_set;
  12.         unsigned char* min_set_backup;
  13. } timeset;


  14. timeset  EEPROM_SAVE[3] ={      //定義并初始化一個結構體數組,數組元素是指針,數組元素為三組需要保存的數據
  15. {&min_change0, &min_change_backup0},
  16. {&min_change1, &min_change_backup1},
  17. {&min_change2, &min_change_backup2}

  18. };

  19. int main(void)
  20. {
  21.    while(1)
  22.    {
  23.       for(int j=0; j <3; j++)
  24.       {
  25.          EEPROM_Write(EEPROM_SAVE,  j,  (j+1)) ;
  26.       }
  27.    }
  28. }


  29. void EEPROM_Write(timeset* table, unsigned char i, unsigned char addr)
  30. {
  31.         if (*(table[i].min_set)  != *(table[i].min_set_backup)) //如果min_change和min_change_backup不相等,則開始保存
  32.         {
  33.               *(table[i].min_set_backup) = *(table[i].min_set) ; //保存數據
  34.                   EEPROM_write(addr,  *(table[i].min_set_backup));  //寫入EEPROM

  35.          }
  36. }
復制代碼


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

使用道具 舉報

沙發(fā)
ID:879348 發(fā)表于 2022-5-12 08:21 | 只看該作者
如果你是用單片機的內部flash做EEPROM,那就無解,刷寫過程需要比較長時間,而且要關閉中斷
回復

使用道具 舉報

板凳
ID:401564 發(fā)表于 2022-5-12 11:41 | 只看該作者
跟結構體是沒有關系的
寫入EEPROM的時候,不知道是不是先擦除再寫入?
如果是的話,擦除和寫入之后,不要一直在那等待完稿完成,FLASH擦除的時間是比較久的,一般都是以頁面為單位的
寫入和擦除應該是寫入之后就去顯示數碼管,或者是數碼管用中斷的方式顯示
回復

使用道具 舉報

地板
ID:997026 發(fā)表于 2022-5-12 12:17 來自觸屏版 | 只看該作者
wufa1986 發(fā)表于 2022-5-12 08:21
如果你是用單片機的內部flash做EEPROM,那就無解,刷寫過程需要比較長時間,而且要關閉中斷

我是用單片機內部的EEPROM,不是flash,EEPROM讀寫很簡單,不需要擦除,不存在邏輯上的問題。感覺就是結構體用法沒搞清楚,我這里面用了好多指針,不知道對不對
回復

使用道具 舉報

5#
ID:997026 發(fā)表于 2022-5-12 12:21 來自觸屏版 | 只看該作者
Y_G_G 發(fā)表于 2022-5-12 11:41
跟結構體是沒有關系的
寫入EEPROM的時候,不知道是不是先擦除再寫入?
如果是的話,擦除和寫入之后,不要一直 ...

我這個是單片機內部的eeprom,不是flash。eeprom的讀寫非常的簡單,我用過很多次了,比較熟,至少不是這種寫法。沒問題,這次換成結構體數組和指針方式就出了問題,我懷疑是結構體用法問題,因為這里面涉及到了數組傳遞參數和指針的問題,不知道用的對不對。另外你提到的寫入延時問題,eeprom寫入確實需要延時,這個程序里我沒加進去,我改天加上試試
回復

使用道具 舉報

6#
ID:123289 發(fā)表于 2022-5-12 14:12 | 只看該作者
建議先仔細研讀一下EEPROM的寫入方式。
大多EEPROM是只能寫0,不能寫1的,即寫之前,要將寫入的位置的數據擦成FFH,而擦除是以頁為單位的,即不能單字節(jié)擦。
程序中指向的地址中,原來數字是不是FFH,這里看不出。如果不是FFH,則平臺編譯此步寫入是很復雜的。涉及:保存存整頁全體到緩沖區(qū),擦除本頁面,在緩沖區(qū)中改寫數據,再將緩沖區(qū)中的整頁數據寫入。這就需要較長的作業(yè)時間。在這段時間里,很可能照顧不到顯示。
想知道正解也簡單:打開編譯生成的匯編程序,看看你在寫入時,CPU干了什么?
如果你懂匯編,而且讀透了EEPROM的性能及操作,是很容易想到問題之所在的。
回復

使用道具 舉報

7#
ID:401564 發(fā)表于 2022-5-12 14:29 | 只看該作者
hxdby 發(fā)表于 2022-5-12 12:21
我這個是單片機內部的eeprom,不是flash。eeprom的讀寫非常的簡單,我用過很多次了,比較熟,至少不是這 ...

EEPROM_write寫入函數是用了遞歸嗎?還是代碼沒復制完
如果是遞歸就沒有必要了,就寫入一個字節(jié)而已,單片機最好不要用遞歸
回復

使用道具 舉報

8#
ID:844772 發(fā)表于 2022-5-12 14:31 | 只看該作者
我不習慣你這種寫法,但覺得你指針用的沒啥問題,難道指針的使用導致執(zhí)行效率下降了,使得數碼刷新率下降引起顯示變暗嗎?
回復

使用道具 舉報

9#
ID:997026 發(fā)表于 2022-5-12 14:46 | 只看該作者
Y_G_G 發(fā)表于 2022-5-12 14:29
EEPROM_write寫入函數是用了遞歸嗎?還是代碼沒復制完
如果是遞歸就沒有必要了,就寫入一個字節(jié)而已,單片 ...

EEPROM_write這個寫入函數沒用遞歸,里面非常簡單,就是純寄存器的寫入,用的是官方的代碼,就幾行代碼而已,所以沒貼出來。大概是下面這樣:
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) //EEPROM寫函數
{
        while(EECR & (1<<EEPE)); //等待上一次寫操作結束
        EEAR = uiAddress;        //設置地址寄存器
        EEDR = ucData;           //設置數據寄存器
        EECR |= (1<<EEMPE);      //置位EEMWE 打開寫使能
        EECR |= (1<<EEPE);       //置位EEWE以啟動寫操作
}
回復

使用道具 舉報

10#
ID:997026 發(fā)表于 2022-5-12 14:51 | 只看該作者
glinfei 發(fā)表于 2022-5-12 14:31
我不習慣你這種寫法,但覺得你指針用的沒啥問題,難道指針的使用導致執(zhí)行效率下降了,使得數碼刷新率下降引 ...

之前不是這種寫法,之前是普通寫法,每一個保存的參數要寫一個函數,無法通用,100多個參數要寫100多個函數,太麻煩了。這里用指針是為了做成通用模板,用一個函數循環(huán)調用不同參數就可以了,大大簡化了代碼。但是確實影響了顯示,不知道為啥。我用很多方法寫過,就是結構體這種寫法有問題,所以懷疑是結構體用法問題。我之前用指針數組,把變量放到指針數組里面也能實現(xiàn)功能,沒有問題,后來想用結構體寫,沒想到一直有問題。
回復

使用道具 舉報

11#
ID:997026 發(fā)表于 2022-5-12 15:01 | 只看該作者
glinfei 發(fā)表于 2022-5-12 14:31
我不習慣你這種寫法,但覺得你指針用的沒啥問題,難道指針的使用導致執(zhí)行效率下降了,使得數碼刷新率下降引 ...

這部分EEPROM數據保存我用很多方法寫過,普通寫法不用說了,代碼量很大,但是沒問題。也用指針數組的方法寫過,就是把兩個待比較的變量分別放到兩個指針數組里,通過指針傳遞參數,這種同樣用指針,也沒問題。這次我用結構體指針就有問題了,估計是結構體哪里用法沒搞對,指針原則上效率更高才對啊
回復

使用道具 舉報

12#
ID:1012735 發(fā)表于 2022-5-12 15:37 | 只看該作者
將函數原型
void EEPROM_Write(timeset*, unsigned char, unsigned char) ; //數據保存并寫入EEPROM
改成
void EEPROM_Write(timeset,unsigned char)

就是:
void EEPROM_Write(timeset  table,        unsigned char addr)
{
        if ( *(table.min_set)!= *(table.min_set_backup)) //如果min_change和min_change_backup不相等,則開始保存
        {
              *(table.min_set_backup) = *(table.min_set) ; //保存數據
                  EEPROM_write(addr, *( table.min_set_backup));  //寫入EEPROM

         }
}調用處:
      for(int j=0; j <3; j++)
      {
         EEPROM_Write(EEPROM_SAVE[ j],       (j+1)) ;
      }

試試不一定能成!
回復

使用道具 舉報

13#
ID:997026 發(fā)表于 2022-5-12 15:53 | 只看該作者
同志們,我找到問題所在了,這種賦值方法
if (*(table[i].min_set)  != *(table[i].min_set_backup))

*(table[i].min_set) 和*(table[i].min_set_backup)是同一個結構體數組變量里的元素,也就是:
timeset  EEPROM_SAVE[3] ={      //定義并初始化一個結構體數組,數組元素是指針,數組元素為三組需要保存的數據
{&min_change0, &min_change_backup0},
{&min_change1, &min_change_backup1},
{&min_change2, &min_change_backup2}

};

也就是相當于我把&min_change_backup0賦值給&min_change0了,而這兩個成員是同一個結構體里的成員,我的疑問是同一個結構體里的成員相互之間不能賦值嗎?

我重新定義了一個結構體,現(xiàn)在有兩個結構體,然后把&min_change_backup0這個變量放到一個結構體中,把&min_change0放到另一個結構體中,相當于調用兩個結構體中的變量做對比了,這樣改動后測試沒有問題了。

所以同一個結構中的變量不能相互賦值嗎?
回復

使用道具 舉報

14#
ID:401564 發(fā)表于 2022-5-12 16:15 | 只看該作者
hxdby 發(fā)表于 2022-5-12 15:53
同志們,我找到問題所在了,這種賦值方法
if (*(table.min_set)  != *(table.min_set_backup))

不知道為什么要這么復雜的操作
但是,一般結構成員指向變量的話,是用圓點  .
你這個是指向指針的,你用->試一下
回復

使用道具 舉報

15#
ID:1012735 發(fā)表于 2022-5-12 16:48 | 只看該作者
數組初始化賦值應該賦常量值吧
回復

使用道具 舉報

16#
ID:997026 發(fā)表于 2022-5-12 16:53 | 只看該作者
Y_G_G 發(fā)表于 2022-5-12 16:15
不知道為什么要這么復雜的操作
但是,一般結構成員指向變量的話,是用圓點  .
你這個是指向指針的,你用-> ...

主要是我保存的參數太多,如果只有幾個參數的話,普通寫法就可以應付了,但是后面可能會有幾百個參數,如果普通寫法需要重復寫同樣的函數幾百次,導致代碼冗長。這種結構體封裝數組和指針的寫法,可以寫出一個通用模板函數,然后后面增加參數,往數組里面添加就行了,便于維護,以前普通寫法保存30個參數差不多寫了1000行代碼,現(xiàn)在用結構體數組封裝后30行代碼就搞定了。

-> 主要用于結構體指針取值,但是我這個涉及到通用性,還是使用for循環(huán)+結構體數組的方式好些
回復

使用道具 舉報

17#
ID:844772 發(fā)表于 2022-5-12 16:55 | 只看該作者
hxdby 發(fā)表于 2022-5-12 15:53
同志們,我找到問題所在了,這種賦值方法
if (*(table.min_set)  != *(table.min_set_backup))

原來你是賦值不對,還以為是數碼管亮度問題。而且同一個結構中變量一定能相互賦值。
賦值那句,我一般會這么寫: *((table+i)->min_set_backup) = *((table+i)->min_set) ;
回復

使用道具 舉報

18#
ID:997026 發(fā)表于 2022-5-12 16:56 | 只看該作者
hy47566398 發(fā)表于 2022-5-12 16:48
數組初始化賦值應該賦常量值吧

普通變量確實需要賦值常量,但是我這個數組的元素是指針,這個指針是全局變量賦初值后通過取地址符得到他的地址,所以也算是常量,只不過這值是指針而已
回復

使用道具 舉報

19#
ID:844772 發(fā)表于 2022-5-12 17:01 | 只看該作者
hxdby 發(fā)表于 2022-5-12 16:53
主要是我保存的參數太多,如果只有幾個參數的話,普通寫法就可以應付了,但是后面可能會有幾百個參數,如 ...

要是不用->,應該多加個*,
你賦值那句也可以這么寫 *((*table[ i]).min_set_backup) = *((*table[ i]).min_set) ; //保存數據
其他的也要改。
回復

使用道具 舉報

20#
ID:997026 發(fā)表于 2022-5-12 17:06 | 只看該作者
glinfei 發(fā)表于 2022-5-12 16:55
原來你是賦值不對,還以為是數碼管亮度問題。而且同一個結構中變量一定能相互賦值。
賦值那句,我一般會 ...

謝謝!我說的賦值不對是在同一個結構體中的兩個變量相互賦值,我什么都沒改,就把相互賦值的這兩個變量分別放到了不同的結構體中,然后再賦值,結果就正常了。我也很奇怪,所以我剛才才會問同一結構中變量不能相互賦值,如果你說同一結構中兩個變量可以相互賦值的話,那我真沒理解為啥我的不行,定義兩個結構體就行了,是不是還有其他問題,我也不知道了。你的這種方法我后面再試試,謝謝
回復

使用道具 舉報

21#
ID:997026 發(fā)表于 2022-5-12 17:08 | 只看該作者
glinfei 發(fā)表于 2022-5-12 17:01
要是不用->,應該多加個*,
你賦值那句也可以這么寫 *((*table).min_set_backup) = *((*table).min_set) ...

你這種寫法,我之前調的時候試過,結果編譯器直接報錯了。后來我就定義了兩個結構體,其他什么都沒改,就正常了,賦值方式也還是我之前的那種方式
回復

使用道具 舉報

22#
ID:997026 發(fā)表于 2022-5-13 15:42 | 只看該作者
glinfei 發(fā)表于 2022-5-12 16:55
原來你是賦值不對,還以為是數碼管亮度問題。而且同一個結構中變量一定能相互賦值。
賦值那句,我一般會 ...

我試過了,你這種寫法非常棒,可以把函數的形參減少到1個,我之前為了實現(xiàn)通用化,在for循環(huán)里不斷調用函數,我要傳遞四個參數,需要這個函數要有四個形參,用你這種寫法,只需傳遞一個參數就可以了,一個形參全部搞定,其他的都可以在函數內部用你這種方法實現(xiàn)。指針的這些玩法太靈活了,寫法好多種
回復

使用道具 舉報

23#
ID:997026 發(fā)表于 2022-5-13 15:51 | 只看該作者
hy47566398 發(fā)表于 2022-5-12 15:37
將函數原型
void EEPROM_Write(timeset*, unsigned char, unsigned char) ; //數據保存并寫入EEPROM
改成 ...

這種應該不行把,這種方式void EEPROM_Write(timeset  table,        unsigned char addr),你把timeset的指針類型拿掉了,那table只能傳入一個結構體普通變量,傳不進一個數組了,但你后面又傳入數組EEPROM_Write(EEPROM_SAVE[ j],       (j+1)) ; 編譯器應該會報錯。用指針主要是用數組名表示傳入的是數組的首地址,所以用指針
回復

使用道具 舉報

24#
ID:1026496 發(fā)表于 2022-5-14 19:06 | 只看該作者
EEPROM_write 不建議頻繁的寫入,建議掉電寫入一次
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一区免费 | 国产精品国产三级国产aⅴ中文 | 欧美精品影院 | 日日干日日 | 99精品视频在线观看 | pacopacomama在线 | 国产精品视频久久久 | 亚洲劲爆av | 久久久久国产 | 日韩av美女电影 | 亚洲一区二区三区在线视频 | 久久伊人久久 | 国产精品久久久久久久久免费丝袜 | 久久久久久久久久毛片 | 欧美日韩综合一区 | 精品国产91亚洲一区二区三区www | 激情福利视频 | 中文字幕在线一 | 国产精品国产成人国产三级 | 日韩一区二区三区在线观看 | 一级黄色毛片a | 亚洲精品在线免费观看视频 | 欧美在线播放一区 | 99精品在线 | 韩日精品在线观看 | 精品在线一区 | 国产精品视频导航 | 午夜精品久久 | 日韩成人一区 | 国产精品久久久久久久久久免费看 | 午夜影院在线观看版 | 九九热久久免费视频 | 在线91| 男女网站在线观看 | 日韩一区二区福利视频 | 国产99久久精品一区二区永久免费 | 国产伦精品一区二区三区视频金莲 | www.五月婷婷.com| 99这里只有精品视频 | 男女污网站| 亚洲一区二区在线 |