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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

有大神幫我改一下單片機代碼嗎? eeprom的按字節寫入

[復制鏈接]
跳轉到指定樓層
樓主
ID:1130333 發表于 2024-10-22 20:15 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
首先定義一個sbit cap=P32;
P32 連接一個22uf電容,然后接地.,上電后 P32在 0.5秒后,充滿電應該是屬于低電平,(P32=0)
在這0.5秒內,應該屬于高電平(P32=1).
那我直接判斷 if(P32==1) 那就寫eeprom(按字節寫入), 如果P32==0 那就讀取上一次寫的eeprom

這不就實現我的需求了嗎?  按照這個邏輯,我自己寫了一個代碼 .但是老是有問題.

單片機源程序如下:
  1. #include "stc8g.h"
  2. #include "intrins.h"
  3. #include <stdio.h>

  4. #define MAIN_Fosc 11059200UL
  5. #define BRT         (65536 - MAIN_Fosc / 115200 / 4)

  6. typedef unsigned char u8;
  7. typedef unsigned int u16;

  8. u8 dat;                                                //定義eeprom 儲存數據,但實際好像沒用上
  9. u16 EEPROMId = 0x0020;                                //定義eeprom的地址

  10. sbit cap = P3^2;                                        //p32引腳連電容,接地 做電平判定

  11. void sys_init();                                        //聲明系統初始化配置
  12. void PWM_init(void);                                //聲明pwm

  13. void main()
  14. {               
  15.         unsigned char x;                                 //定義變量x 用于讀取eeprom
  16.         unsigned char y=5;                        //定義變量y用于保存pwm值
  17.         sys_init();                                  //調用系統配置

  18.           P3M0 = 0x00; P3M1 = 0x00;                //P32 輸出對電容充電
  19.           P5M0 = 0x00; P5M1 = 0x00;                   //pwm 設置在p55口

  20.         x = IapRead(EEPROMId);                        //讀取的當前eeprom 賦值給x        
  21.         
  22.           while(1)
  23.         {         
  24.                 if(cap)                                //如果p32引腳 充電中 p32==1
  25.                 {
  26.                 IapProgram(EEPROMId,y);                //寫地址為0x0020 為 y(以后設置為switch或者數組)

  27.                 EEPROMId=EEPROMId+1;                //下次寫eeprom +1  0x0021 ,在下次0x0022 以此類推
  28.                 y=y+1;                                //pwm亮度 數組+1   (1,15,55,255)
  29.          
  30.                 }
  31.                  CCAP2H=x;                                //把x寫入的值 賦值給pwm

  32.                 if(EEPROMId >= 0X1FE)                                //如果當前字節到達EEPROM末尾,擦除扇區數據
  33.                  {        
  34.                           IapErase(0x0020);                                //擦除扇區
  35.                  
  36.                         EEPROMId = 0x0020;                        //從頭開始按字節寫入
  37.                  }
  38.         }
  39. }

  40. void sys_init(void)
  41. {
  42.         P_SW2=0x80;
  43.       PWM_init();
  44.         EA=1;                        //打開總中斷
  45. }


  46. //// 初始化PWM功能 P55 pwm
  47. void PWM_init(void)
  48. {
  49.     P_SW1=0x20;
  50.     CCON = 0x00;
  51.     CMOD = 0x08;
  52.     CL = 0x00;
  53.     CH = 0x00;

  54.     CCAPM2 = 0x42;
  55.     PCA_PWM2 = 0x00;
  56.     CCAP2L = 0x00;                  
  57.     CCAP2H = 0x00;
  58.     CR=1;        
  59. }

  60. void delayms(u16 ms)
  61. {
  62.         unsigned int i;
  63.         do{
  64.                 i = MAIN_Fosc /10000;
  65.                 while(--i);
  66.         }while(--ms);
  67. }

  68. void IapIdle()
  69. {
  70.         IAP_CONTR = 0;                                                 // 關閉 IAP 功能
  71.         IAP_CMD = 0;                                                         // 清除命令寄存器
  72.         IAP_TRIG = 0;                                                 // 清除觸發寄存器

  73.         IAP_ADDRH = 0x00;                                        // 清零高地址寄存器
  74.         IAP_ADDRL = 0x00;                                        // 清零低地址寄存器
  75. }

  76. char IapRead(unsigned int addr)
  77. {
  78.         
  79.         char dat;
  80.         IAP_CONTR = 0x80;                                 // 使能 IAP
  81.         IAP_TPS = 12;                                                 // 設置等待參數 12MHz
  82.         IAP_CMD = 1;                                                         // 設置 IAP 讀命令
  83.         IAP_ADDRL = addr;                                 // 設置 IAP 低地址
  84.         IAP_ADDRH = addr >> 8;                 // 設置 IAP 高地址
  85.         EA=0;
  86.         _nop_();
  87.         _nop_();        
  88.         IAP_TRIG = 0x5a;                                         // 寫觸發命令 (0x5a)
  89.         IAP_TRIG = 0xa5;                                         // 寫觸發命令 (0xa5)
  90.         EA=1;
  91.         _nop_();
  92.         _nop_();
  93.         _nop_();
  94.         _nop_();
  95.         dat = IAP_DATA;                                         // 讀 IAP 數據
  96.         IapIdle();                                                                 // 關閉 IAP 功能
  97.         return dat;

  98. }
  99. void IapProgram(unsigned int addr, char dat)
  100. {

  101.         IAP_CONTR = 0x80;                                 // 使能 IAP
  102.         IAP_TPS = 12;                                                 // 設置等待參數 12MHz
  103.         IAP_CMD = 2;                                                        // 設置 IAP 寫命令
  104.         IAP_ADDRL = addr;                                 // 設置 IAP 低地址
  105.         IAP_ADDRH = addr >> 8;                 // 設置 IAP 高地址

  106.         IAP_DATA = dat;                                         // 寫 IAP 數據
  107.         EA=0;
  108.         _nop_();
  109.         _nop_();        
  110.         IAP_TRIG = 0x5a;                                         // 寫觸發命令 (0x5a)
  111.         IAP_TRIG = 0xa5;                                         // 寫觸發命令 (0xa5)
  112.         EA=1;        
  113.         _nop_();
  114.         _nop_();
  115.         _nop_();
  116.         _nop_();
  117.         IapIdle();                                                                // 關閉 IAP 功能

  118. }
  119. void IapErase(unsigned int addr)
  120. {

  121.         IAP_CONTR = 0x80;                                 // 使能 IAP
  122.         IAP_TPS = 12;                                                 // 設置等待參數 12MHz
  123.         IAP_CMD = 3;                                                         // 設置 IAP 擦除命令
  124.         IAP_ADDRL = addr;                                 // 設置 IAP 低地址
  125.         IAP_ADDRH = addr >> 8;                 // 設置 IAP 高地址

  126.         EA=0;
  127.         _nop_();
  128.         _nop_();        
  129.         IAP_TRIG = 0x5a;                                         // 寫觸發命令 (0x5a)
  130.         IAP_TRIG = 0xa5;                                         // 寫觸發命令 (0xa5)
  131.         EA=1;        
  132.         _nop_();
  133.         _nop_();
  134.         _nop_();
  135.         _nop_();
  136.         IapIdle();                                                                 // 關閉 IAP 功能

  137. }
復制代碼
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:57657 發表于 2024-10-22 22:34 | 只看該作者
字節讀:可使用unsigned char/int/long code指針匯編成MOVC指令即可訪問,不需要配置EEPROM寄存器,字節寫將二進制1寫為0且不可逆,必須扇區擦除才能恢復,沒有字節擦除,擦除后全部為0xFF(二進制1),一次擦512字節。
回復

使用道具 舉報

板凳
ID:1130333 發表于 2024-10-22 23:07 | 只看該作者
npn 發表于 2024-10-22 22:34
字節讀:可使用unsigned char/int/long code指針匯編成MOVC指令即可訪問,不需要配置EEPROM寄存器,字節寫將 ...

可以幫忙完善下我的代碼嗎?
512 個字節,,
從0可以寫,每次小于0.5秒的關,開機,都寫一次新數據.
寫到510 就擦除這個扇區,然后再從 0 開始寫.
回復

使用道具 舉報

地板
ID:1133081 發表于 2024-10-23 06:10 | 只看該作者
P3M0 = 0x00; P3M1 = 0x00;配置是準雙向高電平,P32 連接一個22uf電容,然后接地,在上電后短暫時間內P32電壓由0逐漸上升到接近VCC。從一般意義講,端口電壓小于1/3VCC判斷為低電平,大于2/3VCC判斷為高電平。中間為不確定狀態(因芯片制造工藝不同,其電氣特性有差異,要以其用戶手冊為準)。樓主以此方法取樣不妥。再者樓主在主循環中頻繁讀寫EEPROM也是忌諱。通常做法是設置一個變量,掉電時保存這個變量的數據在EEPROM中,再次上電初始化時讀取保存的數據賦值這個變量。
回復

使用道具 舉報

5#
ID:143767 發表于 2024-10-23 10:05 | 只看該作者
上電瞬間是低電平,充滿電后是高電平,你正好理解反了
回復

使用道具 舉報

6#
ID:1130333 發表于 2024-10-23 12:49 | 只看該作者
WL0123 發表于 2024-10-23 06:10
P3M0 = 0x00; P3M1 = 0x00;配置是準雙向高電平,P32 連接一個22uf電容,然后接地,在上電后短暫時間內P32電 ...

可以幫忙完善下嗎?
回復

使用道具 舉報

7#
ID:1130333 發表于 2024-10-23 12:49 | 只看該作者
dj3365191 發表于 2024-10-23 10:05
上電瞬間是低電平,充滿電后是高電平,你正好理解反了

可以幫忙完善下代碼嗎?
回復

使用道具 舉報

8#
ID:69038 發表于 2024-10-23 16:41 | 只看該作者
如果是“上電后 P32在 0.5秒后,充滿電應該是屬于低電平”,充滿電后應是高電平的才對吧?
回復

使用道具 舉報

9#
ID:1130333 發表于 2024-10-24 10:19 | 只看該作者
關鍵是eeprom單字節寫入.
這個沒問題
回復

使用道具 舉報

10#
ID:1109793 發表于 2024-10-25 10:24 | 只看該作者
0.5秒關機再開機,開機后充電,此時單片機不一定能復位完成,關機后0.5秒,此時電容的電未必能放完。再開機不一定能及時復位并開始運行你的代碼。搞不懂為啥要這么操作。
回復

使用道具 舉報

11#
ID:624769 發表于 2024-10-25 20:54 | 只看該作者
你是那個要做手電筒的吧? 你的思路是不是搞錯了?
正確的思路應該是:
給單片機提供足夠大的電容,確保單片機在 0.5S 內不會被完全放電,當單片機檢測到“斷電”這個信號之后,給標志位F0置位1,然后設置 0.5秒的定時換醒后 休眠。 0.5秒后休眠喚醒 把F0清0繼續休眠。如果0.5秒內被來電喚醒,因為標志F0 為1 則模式增加1,同時跟新 Eeprom.  如果 0.5秒后被喚新,或者,時間很長徹底掉電了,重新上電,因為F0都為0 則 讀取Eeprom 數據,繼續使用,原來的模式。
回復

使用道具 舉報

12#
ID:1133081 發表于 2024-10-26 06:30 | 只看該作者
vb2002 發表于 2024-10-23 12:49
可以幫忙完善下嗎?

首先要明確表明你的需求是什么,才能提供有效的解決方案。
回復

使用道具 舉報

13#
ID:1130333 發表于 2024-10-29 23:36 來自手機 | 只看該作者
188610329 發表于 2024-10-25 20:54
你是那個要做手電筒的吧? 你的思路是不是搞錯了?
正確的思路應該是:
給單片機提供足夠大的電容,確保 ...

手電功能上已經搞定了,
現在就是每次都是寫 1字節,然后擦除整個扇區,
覺得這樣太浪費了,eeprom壽命怕頂不住多久,
想弄成 每次讀一字節,寫一字節,寫完 512或者 1024,2048,再擦除扇區,再從頭開始寫
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人精品免费视频 | 成人a视频在线观看 | 狠狠躁18三区二区一区 | 成人久久久 | 黄色一级免费观看 | 免费精品 | 久久中文免费视频 | 免费黄色日本 | 激情av网站 | 91影院在线观看 | 久久国产精品视频 | 精品欧美一区免费观看α√ | 另类在线 | 久久男人 | 精品91久久| 精品国产欧美 | 一区二区免费在线 | 国产伦一区二区三区久久 | 国产99久久精品一区二区永久免费 | 欧美日韩中文字幕在线 | 亚洲一区在线播放 | 欧美精品综合在线 | 一区二区三区日韩精品 | 亚洲成人三区 | 亚洲热在线视频 | 国产在线播 | 国产亚洲一区二区在线观看 | 成人毛片在线视频 | 亚洲一区二区三区乱码aⅴ 四虎在线视频 | 久久成人在线视频 | 亚洲久久在线 | 亚洲国产视频一区 | 中文字幕在线一区二区三区 | 亚洲一区 中文字幕 | 久久亚洲国产精品 | 久久精品亚洲精品国产欧美 | 国产黄色在线观看 | 综合网在线 | 欧美日本一区二区 | 91亚洲国产成人久久精品网站 | 午夜av成人 |